From 0bedf4fb30066e5e1d4342a1d3914dae7d37cba7 Mon Sep 17 00:00:00 2001 From: obrien Date: Thu, 26 Aug 1999 09:30:50 +0000 Subject: Virgin import of gcc from EGCS 1.1.2 --- contrib/gcc/BUGS | 2 +- contrib/gcc/ChangeLog | 16793 +++++++++++++++----- contrib/gcc/LANGUAGES | 79 + contrib/gcc/Makefile.in | 2093 ++- contrib/gcc/NEWS | 340 +- contrib/gcc/PROJECTS | 135 +- contrib/gcc/README | 5 +- contrib/gcc/README-bugs | 144 + contrib/gcc/README.DWARF | 6 +- contrib/gcc/README.g77 | 263 + contrib/gcc/SERVICE | 1821 ++- contrib/gcc/acconfig.h | 79 + contrib/gcc/aclocal.m4 | 221 + contrib/gcc/alias.c | 1261 ++ contrib/gcc/alloca.c | 16 +- contrib/gcc/basic-block.h | 227 +- contrib/gcc/bitmap.c | 642 + contrib/gcc/bitmap.h | 317 + contrib/gcc/build-make | 9 +- contrib/gcc/c-aux-info.c | 79 +- contrib/gcc/c-common.c | 1198 +- contrib/gcc/c-convert.c | 1 + contrib/gcc/c-decl.c | 954 +- contrib/gcc/c-iterate.c | 62 +- contrib/gcc/c-lang.c | 72 +- contrib/gcc/c-lex.c | 648 +- contrib/gcc/c-lex.h | 14 +- contrib/gcc/c-parse.in | 341 +- contrib/gcc/c-pragma.c | 23 +- contrib/gcc/c-tree.h | 73 +- contrib/gcc/c-typeck.c | 918 +- contrib/gcc/caller-save.c | 83 +- contrib/gcc/calls.c | 1278 +- contrib/gcc/cccp.1 | 21 +- contrib/gcc/cccp.c | 4094 ++--- contrib/gcc/cexp.y | 605 +- contrib/gcc/choose-temp.c | 211 + contrib/gcc/collect2.c | 1375 +- contrib/gcc/combine.c | 2125 ++- contrib/gcc/conditions.h | 2 + contrib/gcc/config.guess | 579 +- contrib/gcc/config.in | 202 + contrib/gcc/config.sub | 221 +- contrib/gcc/config/alpha/alpha.c | 3785 ++++- contrib/gcc/config/alpha/alpha.h | 1125 +- contrib/gcc/config/alpha/alpha.md | 3300 ++-- contrib/gcc/config/alpha/crtbegin.asm | 111 + contrib/gcc/config/alpha/crtend.asm | 105 + contrib/gcc/config/alpha/elf.h | 190 +- contrib/gcc/config/alpha/linux-ecoff.h | 36 + contrib/gcc/config/alpha/linux-elf.h | 47 + contrib/gcc/config/alpha/linux.h | 44 + contrib/gcc/config/alpha/netbsd-elf.h | 31 + contrib/gcc/config/alpha/netbsd.h | 38 + contrib/gcc/config/alpha/openbsd.h | 126 + contrib/gcc/config/alpha/osf.h | 127 + contrib/gcc/config/alpha/osf12.h | 10 +- contrib/gcc/config/alpha/osf2or3.h | 30 + contrib/gcc/config/alpha/t-crtbe | 9 + contrib/gcc/config/alpha/t-vms | 6 + contrib/gcc/config/alpha/va_list.h | 16 + contrib/gcc/config/alpha/vms-tramp.asm | 22 + contrib/gcc/config/alpha/vms.h | 510 + contrib/gcc/config/alpha/vxworks.h | 51 + contrib/gcc/config/alpha/x-alpha | 1 + contrib/gcc/config/alpha/xm-alpha.h | 18 +- contrib/gcc/config/alpha/xm-openbsd.h | 23 + contrib/gcc/config/alpha/xm-vms.h | 93 + contrib/gcc/config/aoutos.h | 47 - contrib/gcc/config/dbx.h | 30 + contrib/gcc/config/dbxcoff.h | 87 + contrib/gcc/config/float-i128.h | 96 + contrib/gcc/config/float-i32.h | 96 + contrib/gcc/config/float-i386.h | 104 + contrib/gcc/config/float-i64.h | 96 + contrib/gcc/config/float-m68k.h | 97 + contrib/gcc/config/float-sh.h | 130 + contrib/gcc/config/float-vax.h | 96 + contrib/gcc/config/fp-bit.c | 250 +- contrib/gcc/config/gnu.h | 7 - contrib/gcc/config/i386/386bsd.h | 9 +- contrib/gcc/config/i386/aix386ng.h | 15 +- contrib/gcc/config/i386/att.h | 21 +- contrib/gcc/config/i386/bsd.h | 8 +- contrib/gcc/config/i386/bsd386.h | 19 +- contrib/gcc/config/i386/crtdll.h | 42 + contrib/gcc/config/i386/dgux.c | 190 + contrib/gcc/config/i386/dgux.h | 265 + contrib/gcc/config/i386/freebsd-elf.h | 44 +- contrib/gcc/config/i386/freebsd.h | 349 +- contrib/gcc/config/i386/freebsd.h.fixed | 349 +- contrib/gcc/config/i386/gas.h | 48 +- contrib/gcc/config/i386/gmon-sol2.c | 409 + contrib/gcc/config/i386/gnu.h | 15 +- contrib/gcc/config/i386/go32.h | 34 +- contrib/gcc/config/i386/i386.c | 2908 +++- contrib/gcc/config/i386/i386.h | 1313 +- contrib/gcc/config/i386/i386.md | 4193 +++-- contrib/gcc/config/i386/isc.h | 8 +- contrib/gcc/config/i386/linux-aout.h | 20 +- contrib/gcc/config/i386/linux-oldld.h | 21 +- contrib/gcc/config/i386/linux.h | 73 +- contrib/gcc/config/i386/lynx.h | 8 +- contrib/gcc/config/i386/mingw32.h | 95 + contrib/gcc/config/i386/moss.h | 34 + contrib/gcc/config/i386/netbsd.h | 23 +- contrib/gcc/config/i386/next.h | 15 +- contrib/gcc/config/i386/openbsd.h | 130 + contrib/gcc/config/i386/osf1-ci.asm | 65 + contrib/gcc/config/i386/osf1-cn.asm | 46 + contrib/gcc/config/i386/osf1elf.h | 260 + contrib/gcc/config/i386/osf1elfgdb.h | 7 + contrib/gcc/config/i386/osfelf.h | 4 +- contrib/gcc/config/i386/osfrose.h | 37 +- contrib/gcc/config/i386/ptx4-i.h | 247 + contrib/gcc/config/i386/rtems.h | 34 + contrib/gcc/config/i386/rtemself.h | 169 + contrib/gcc/config/i386/sco.h | 8 +- contrib/gcc/config/i386/sco4.h | 6 +- contrib/gcc/config/i386/sco4dbx.h | 6 +- contrib/gcc/config/i386/sco5.h | 957 ++ contrib/gcc/config/i386/sco5gas.h | 24 + contrib/gcc/config/i386/scodbx.h | 8 +- contrib/gcc/config/i386/seq-gas.h | 4 +- contrib/gcc/config/i386/seq-sysv3.h | 14 - contrib/gcc/config/i386/sol2-c1.asm | 4 +- contrib/gcc/config/i386/sol2-gc1.asm | 160 + contrib/gcc/config/i386/sol2.h | 46 +- contrib/gcc/config/i386/sun386.h | 7 +- contrib/gcc/config/i386/svr3.ifile | 5 +- contrib/gcc/config/i386/svr3dbx.h | 22 +- contrib/gcc/config/i386/svr3gas.h | 18 +- contrib/gcc/config/i386/svr3z.ifile | 5 +- contrib/gcc/config/i386/sysv3.h | 8 +- contrib/gcc/config/i386/sysv4.h | 14 +- contrib/gcc/config/i386/t-crtpic | 1 + contrib/gcc/config/i386/t-dgux | 4 + contrib/gcc/config/i386/t-mingw32 | 4 + contrib/gcc/config/i386/t-next | 3 + contrib/gcc/config/i386/t-osf | 2 + contrib/gcc/config/i386/t-osf1elf | 18 + contrib/gcc/config/i386/t-sco5 | 20 + contrib/gcc/config/i386/t-sco5gas | 20 + contrib/gcc/config/i386/t-sol2 | 22 +- contrib/gcc/config/i386/t-winnt | 6 +- contrib/gcc/config/i386/unix.h | 47 +- contrib/gcc/config/i386/vxi386.h | 23 + contrib/gcc/config/i386/winnt.c | 526 +- contrib/gcc/config/i386/x-dgux | 11 + contrib/gcc/config/i386/x-osf1elf | 8 + contrib/gcc/config/i386/x-osfrose | 10 +- contrib/gcc/config/i386/x-sco5 | 10 + contrib/gcc/config/i386/xm-aix.h | 35 - contrib/gcc/config/i386/xm-bsd386.h | 3 - contrib/gcc/config/i386/xm-dgux.h | 12 + contrib/gcc/config/i386/xm-dos.h | 6 - contrib/gcc/config/i386/xm-isc.h | 2 - contrib/gcc/config/i386/xm-linux.h | 4 +- contrib/gcc/config/i386/xm-mingw32.h | 42 + contrib/gcc/config/i386/xm-openbsd.h | 23 + contrib/gcc/config/i386/xm-os2.h | 28 +- contrib/gcc/config/i386/xm-osf.h | 30 - contrib/gcc/config/i386/xm-osf1elf.h | 6 + contrib/gcc/config/i386/xm-sco.h | 9 - contrib/gcc/config/i386/xm-sco5.h | 7 + contrib/gcc/config/i386/xm-sun.h | 6 +- contrib/gcc/config/i386/xm-sysv4.h | 11 - contrib/gcc/config/i386/xm-vsta.h | 24 - contrib/gcc/config/libgloss.h | 35 + contrib/gcc/config/linux-aout.h | 13 +- contrib/gcc/config/linux.h | 67 +- contrib/gcc/config/lynx.h | 5 +- contrib/gcc/config/netbsd.h | 37 +- contrib/gcc/config/nextstep.c | 48 +- contrib/gcc/config/nextstep.h | 75 +- contrib/gcc/config/openbsd.h | 302 + contrib/gcc/config/psos.h | 183 + contrib/gcc/config/ptx4.h | 859 + contrib/gcc/config/sparc/aout.h | 26 + contrib/gcc/config/sparc/bsd.h | 7 + contrib/gcc/config/sparc/elf.h | 42 + contrib/gcc/config/sparc/gmon-sol2.c | 429 + contrib/gcc/config/sparc/lb1spc.asm | 784 + contrib/gcc/config/sparc/lb1spl.asm | 246 + contrib/gcc/config/sparc/linux-aout.h | 130 + contrib/gcc/config/sparc/linux.h | 259 + contrib/gcc/config/sparc/linux64.h | 245 + contrib/gcc/config/sparc/lite.h | 38 + contrib/gcc/config/sparc/litecoff.h | 113 + contrib/gcc/config/sparc/lynx-ng.h | 41 + contrib/gcc/config/sparc/lynx.h | 53 + contrib/gcc/config/sparc/netbsd.h | 46 + contrib/gcc/config/sparc/openbsd.h | 68 + contrib/gcc/config/sparc/pbd.h | 184 + contrib/gcc/config/sparc/rtems.h | 35 + contrib/gcc/config/sparc/sol2-c1.asm | 86 + contrib/gcc/config/sparc/sol2-ci.asm | 60 + contrib/gcc/config/sparc/sol2-cn.asm | 54 + contrib/gcc/config/sparc/sol2-g1.asm | 88 + contrib/gcc/config/sparc/sol2-sld.h | 11 + contrib/gcc/config/sparc/sol2.h | 232 + contrib/gcc/config/sparc/sp64-aout.h | 38 + contrib/gcc/config/sparc/sp64-elf.h | 157 + contrib/gcc/config/sparc/sparc.c | 6461 ++++++++ contrib/gcc/config/sparc/sparc.h | 3287 ++++ contrib/gcc/config/sparc/sparc.md | 6684 ++++++++ contrib/gcc/config/sparc/splet.h | 53 + contrib/gcc/config/sparc/sun4gas.h | 27 + contrib/gcc/config/sparc/sun4o3.h | 29 + contrib/gcc/config/sparc/sunos4.h | 49 + contrib/gcc/config/sparc/sysv4.h | 231 + contrib/gcc/config/sparc/t-elf | 39 + contrib/gcc/config/sparc/t-sol2 | 30 + contrib/gcc/config/sparc/t-sp64 | 2 + contrib/gcc/config/sparc/t-sparcbare | 26 + contrib/gcc/config/sparc/t-sparclite | 24 + contrib/gcc/config/sparc/t-splet | 23 + contrib/gcc/config/sparc/t-sunos40 | 7 + contrib/gcc/config/sparc/t-sunos41 | 16 + contrib/gcc/config/sparc/t-vxsparc | 17 + contrib/gcc/config/sparc/vxsim.h | 131 + contrib/gcc/config/sparc/vxsparc.h | 61 + contrib/gcc/config/sparc/x-sysv4 | 2 + contrib/gcc/config/sparc/xm-linux.h | 26 + contrib/gcc/config/sparc/xm-lynx.h | 39 + contrib/gcc/config/sparc/xm-openbsd.h | 23 + contrib/gcc/config/sparc/xm-pbd.h | 10 + contrib/gcc/config/sparc/xm-sol2.h | 4 + contrib/gcc/config/sparc/xm-sp64.h | 25 + contrib/gcc/config/sparc/xm-sparc.h | 49 + contrib/gcc/config/sparc/xm-sysv4.h | 48 + contrib/gcc/config/svr3.h | 36 +- contrib/gcc/config/svr4.h | 187 +- contrib/gcc/config/t-freebsd | 5 + contrib/gcc/config/t-gnu | 13 + contrib/gcc/config/t-libc-ok | 1 + contrib/gcc/config/t-linux-aout | 11 + contrib/gcc/config/t-netbsd | 9 + contrib/gcc/config/t-openbsd | 9 + contrib/gcc/config/t-openbsd-thread | 5 + contrib/gcc/config/t-rtems | 6 + contrib/gcc/config/t-svr4 | 3 +- contrib/gcc/config/x-linux | 15 +- contrib/gcc/config/x-linux-aout | 14 + contrib/gcc/config/xm-alloca.h | 4 + contrib/gcc/config/xm-freebsd.h | 9 - contrib/gcc/config/xm-gnu.h | 5 +- contrib/gcc/config/xm-linux.h | 19 +- contrib/gcc/config/xm-netbsd.h | 1 - contrib/gcc/config/xm-openbsd.h | 35 + contrib/gcc/config/xm-siglist.h | 6 + contrib/gcc/config/xm-std32.h | 34 + contrib/gcc/config/xm-svr3.h | 10 +- contrib/gcc/config/xm-svr4.h | 12 +- contrib/gcc/configure | 6178 ++++++-- contrib/gcc/configure.frag | 77 + contrib/gcc/configure.in | 3833 +++++ contrib/gcc/configure.lang | 233 + contrib/gcc/convert.c | 290 +- contrib/gcc/cp/ChangeLog | 15356 ++++++++++-------- contrib/gcc/cp/Make-lang.in | 192 +- contrib/gcc/cp/Makefile.in | 168 +- contrib/gcc/cp/NEWS | 226 + contrib/gcc/cp/call.c | 6367 +++++--- contrib/gcc/cp/class.c | 2837 ++-- contrib/gcc/cp/config-lang.in | 8 +- contrib/gcc/cp/cp-tree.def | 240 + contrib/gcc/cp/cp-tree.h | 1549 +- contrib/gcc/cp/cvt.c | 1292 +- contrib/gcc/cp/decl.c | 8164 +++++----- contrib/gcc/cp/decl.h | 2 +- contrib/gcc/cp/decl2.c | 3663 +++-- contrib/gcc/cp/errfn.c | 280 +- contrib/gcc/cp/error.c | 816 +- contrib/gcc/cp/except.c | 2147 ++- contrib/gcc/cp/exception.cc | 324 + contrib/gcc/cp/expr.c | 258 +- contrib/gcc/cp/friend.c | 484 + contrib/gcc/cp/g++.1 | 32 - contrib/gcc/cp/g++spec.c | 269 + contrib/gcc/cp/gxx.gperf | 24 +- contrib/gcc/cp/gxxint.texi | 575 +- contrib/gcc/cp/inc/exception | 43 + contrib/gcc/cp/inc/new | 46 + contrib/gcc/cp/inc/new.h | 13 + contrib/gcc/cp/inc/typeinfo | 62 + contrib/gcc/cp/init.c | 2703 ++-- contrib/gcc/cp/input.c | 81 +- contrib/gcc/cp/lang-options.h | 182 +- contrib/gcc/cp/lang-specs.h | 67 +- contrib/gcc/cp/lex.c | 2361 +-- contrib/gcc/cp/lex.h | 18 +- contrib/gcc/cp/method.c | 2976 ++-- contrib/gcc/cp/mpw-config.in | 11 + contrib/gcc/cp/mpw-make.sed | 112 + contrib/gcc/cp/new.cc | 42 + contrib/gcc/cp/new1.cc | 89 + contrib/gcc/cp/new2.cc | 80 + contrib/gcc/cp/parse.y | 3187 ++-- contrib/gcc/cp/pt.c | 7971 ++++++++-- contrib/gcc/cp/ptree.c | 61 +- contrib/gcc/cp/repo.c | 136 +- contrib/gcc/cp/rtti.c | 1135 ++ contrib/gcc/cp/search.c | 1407 +- contrib/gcc/cp/semantics.c | 1393 ++ contrib/gcc/cp/sig.c | 149 +- contrib/gcc/cp/spew.c | 232 +- contrib/gcc/cp/tinfo.cc | 134 + contrib/gcc/cp/tinfo.h | 55 + contrib/gcc/cp/tinfo2.cc | 300 + contrib/gcc/cp/tree.c | 1801 ++- contrib/gcc/cp/typeck.c | 4156 +++-- contrib/gcc/cp/typeck2.c | 514 +- contrib/gcc/cp/xref.c | 94 +- contrib/gcc/cplus-dem.c | 2385 ++- contrib/gcc/cpp.texi | 185 +- contrib/gcc/cppalloc.c | 28 +- contrib/gcc/cpperror.c | 95 +- contrib/gcc/cppexp.c | 182 +- contrib/gcc/cpphash.c | 78 +- contrib/gcc/cpphash.h | 4 +- contrib/gcc/cpplib.c | 2517 +-- contrib/gcc/cpplib.h | 184 +- contrib/gcc/cppmain.c | 43 +- contrib/gcc/cross-make | 6 +- contrib/gcc/crtstuff.c | 221 +- contrib/gcc/cse.c | 1171 +- contrib/gcc/cstamp-h.in | 1 + contrib/gcc/dbxout.c | 673 +- contrib/gcc/dbxout.h | 33 + contrib/gcc/demangle.h | 48 +- contrib/gcc/doprint.c | 286 + contrib/gcc/doschk.c | 8 +- contrib/gcc/dwarf.h | 6 +- contrib/gcc/dwarf2.h | 548 + contrib/gcc/dwarf2out.c | 9884 ++++++++++++ contrib/gcc/dwarf2out.h | 41 + contrib/gcc/dwarfout.c | 1285 +- contrib/gcc/dwarfout.h | 40 + contrib/gcc/dyn-string.c | 100 + contrib/gcc/dyn-string.h | 31 + contrib/gcc/eh-common.h | 125 + contrib/gcc/emit-rtl.c | 876 +- contrib/gcc/enquire.c | 170 +- contrib/gcc/except.c | 2694 ++++ contrib/gcc/except.h | 385 + contrib/gcc/explow.c | 439 +- contrib/gcc/expmed.c | 780 +- contrib/gcc/expr.c | 10340 ++++++------ contrib/gcc/expr.h | 193 +- contrib/gcc/extend.texi | 814 +- contrib/gcc/f/BUGS | 211 + contrib/gcc/f/ChangeLog | 4804 ++++++ contrib/gcc/f/Make-lang.in | 472 + contrib/gcc/f/Makefile.in | 530 + contrib/gcc/f/NEWS | 1623 ++ contrib/gcc/f/README | 7 + contrib/gcc/f/ansify.c | 208 + contrib/gcc/f/assert.j | 27 + contrib/gcc/f/bad.c | 544 + contrib/gcc/f/bad.def | 711 + contrib/gcc/f/bad.h | 108 + contrib/gcc/f/bit.c | 201 + contrib/gcc/f/bit.h | 84 + contrib/gcc/f/bld-op.def | 69 + contrib/gcc/f/bld.c | 5794 +++++++ contrib/gcc/f/bld.h | 1024 ++ contrib/gcc/f/bugs.texi | 341 + contrib/gcc/f/bugs0.texi | 17 + contrib/gcc/f/com-rt.def | 282 + contrib/gcc/f/com.c | 16510 ++++++++++++++++++++ contrib/gcc/f/com.h | 376 + contrib/gcc/f/config-lang.in | 37 + contrib/gcc/f/config.j | 27 + contrib/gcc/f/convert.j | 28 + contrib/gcc/f/data.c | 1816 +++ contrib/gcc/f/data.h | 74 + contrib/gcc/f/equiv.c | 1498 ++ contrib/gcc/f/equiv.h | 103 + contrib/gcc/f/expr.c | 19304 +++++++++++++++++++++++ contrib/gcc/f/expr.h | 194 + contrib/gcc/f/fini.c | 773 + contrib/gcc/f/flags.j | 27 + contrib/gcc/f/g77.1 | 357 + contrib/gcc/f/g77.texi | 14999 ++++++++++++++++++ contrib/gcc/f/g77spec.c | 580 + contrib/gcc/f/glimits.j | 28 + contrib/gcc/f/global.c | 1536 ++ contrib/gcc/f/global.h | 200 + contrib/gcc/f/hconfig.j | 27 + contrib/gcc/f/implic.c | 382 + contrib/gcc/f/implic.h | 74 + contrib/gcc/f/info-b.def | 36 + contrib/gcc/f/info-k.def | 37 + contrib/gcc/f/info-w.def | 41 + contrib/gcc/f/info.c | 304 + contrib/gcc/f/info.h | 186 + contrib/gcc/f/input.j | 27 + contrib/gcc/f/intdoc.c | 1336 ++ contrib/gcc/f/intdoc.in | 2519 +++ contrib/gcc/f/intdoc.texi | 10745 +++++++++++++ contrib/gcc/f/intrin.c | 2055 +++ contrib/gcc/f/intrin.def | 3351 ++++ contrib/gcc/f/intrin.h | 130 + contrib/gcc/f/lab.c | 159 + contrib/gcc/f/lab.h | 154 + contrib/gcc/f/lang-options.h | 158 + contrib/gcc/f/lang-specs.h | 106 + contrib/gcc/f/lex.c | 4717 ++++++ contrib/gcc/f/lex.h | 201 + contrib/gcc/f/malloc.c | 554 + contrib/gcc/f/malloc.h | 183 + contrib/gcc/f/name.c | 242 + contrib/gcc/f/name.h | 109 + contrib/gcc/f/news.texi | 2330 +++ contrib/gcc/f/news0.texi | 14 + contrib/gcc/f/output.j | 28 + contrib/gcc/f/parse.c | 95 + contrib/gcc/f/proj.c | 68 + contrib/gcc/f/proj.h | 83 + contrib/gcc/f/rtl.j | 28 + contrib/gcc/f/src.c | 445 + contrib/gcc/f/src.h | 144 + contrib/gcc/f/st.c | 554 + contrib/gcc/f/st.h | 81 + contrib/gcc/f/sta.c | 2000 +++ contrib/gcc/f/sta.h | 117 + contrib/gcc/f/stb.c | 25198 ++++++++++++++++++++++++++++++ contrib/gcc/f/stb.h | 253 + contrib/gcc/f/stc.c | 13898 ++++++++++++++++ contrib/gcc/f/stc.h | 360 + contrib/gcc/f/std.c | 6905 ++++++++ contrib/gcc/f/std.h | 298 + contrib/gcc/f/ste.c | 5419 +++++++ contrib/gcc/f/ste.h | 168 + contrib/gcc/f/storag.c | 573 + contrib/gcc/f/storag.h | 167 + contrib/gcc/f/stp.c | 59 + contrib/gcc/f/stp.h | 508 + contrib/gcc/f/str-1t.fin | 135 + contrib/gcc/f/str-2t.fin | 60 + contrib/gcc/f/str-fo.fin | 55 + contrib/gcc/f/str-io.fin | 43 + contrib/gcc/f/str-nq.fin | 55 + contrib/gcc/f/str-op.fin | 57 + contrib/gcc/f/str-ot.fin | 50 + contrib/gcc/f/str.c | 217 + contrib/gcc/f/str.h | 85 + contrib/gcc/f/sts.c | 273 + contrib/gcc/f/sts.h | 89 + contrib/gcc/f/stt.c | 1044 ++ contrib/gcc/f/stt.h | 230 + contrib/gcc/f/stu.c | 1161 ++ contrib/gcc/f/stu.h | 69 + contrib/gcc/f/stv.c | 66 + contrib/gcc/f/stv.h | 165 + contrib/gcc/f/stw.c | 428 + contrib/gcc/f/stw.h | 184 + contrib/gcc/f/symbol.c | 1477 ++ contrib/gcc/f/symbol.def | 654 + contrib/gcc/f/symbol.h | 293 + contrib/gcc/f/system.j | 27 + contrib/gcc/f/target.c | 2564 +++ contrib/gcc/f/target.h | 1865 +++ contrib/gcc/f/tconfig.j | 27 + contrib/gcc/f/tm.j | 27 + contrib/gcc/f/top.c | 922 ++ contrib/gcc/f/top.h | 264 + contrib/gcc/f/toplev.j | 27 + contrib/gcc/f/tree.j | 28 + contrib/gcc/f/type.c | 107 + contrib/gcc/f/type.h | 64 + contrib/gcc/f/version.c | 1 + contrib/gcc/f/version.h | 6 + contrib/gcc/f/where.c | 542 + contrib/gcc/f/where.h | 138 + contrib/gcc/final.c | 1510 +- contrib/gcc/fix-header.c | 654 +- contrib/gcc/fixinc.ptx | 70 +- contrib/gcc/fixinc.sco | 112 + contrib/gcc/fixinc.svr4 | 133 +- contrib/gcc/fixincludes | 779 +- contrib/gcc/fixproto | 35 +- contrib/gcc/flags.h | 148 +- contrib/gcc/floatlib.c | 259 +- contrib/gcc/flow.c | 2521 ++- contrib/gcc/fold-const.c | 2252 ++- contrib/gcc/fp-test.c | 231 + contrib/gcc/frame.c | 815 + contrib/gcc/frame.h | 65 + contrib/gcc/function.c | 1639 +- contrib/gcc/function.h | 61 +- contrib/gcc/future.options | 29 + contrib/gcc/gansidecl.h | 91 + contrib/gcc/gbl-ctors.h | 18 +- contrib/gcc/gcc.1 | 84 +- contrib/gcc/gcc.c | 2881 ++-- contrib/gcc/gcc.texi | 7196 +++++---- contrib/gcc/gcov-io.h | 142 + contrib/gcc/gcov.c | 1375 ++ contrib/gcc/gcov.texi | 344 + contrib/gcc/gcse.c | 4758 ++++++ contrib/gcc/gen-protos.c | 218 +- contrib/gcc/genattr.c | 49 +- contrib/gcc/genattrtab.c | 687 +- contrib/gcc/gencheck.c | 82 + contrib/gcc/gencodes.c | 36 +- contrib/gcc/genconfig.c | 46 +- contrib/gcc/genemit.c | 94 +- contrib/gcc/genextract.c | 69 +- contrib/gcc/genflags.c | 46 +- contrib/gcc/gengenrtl.c | 337 + contrib/gcc/genopinit.c | 59 +- contrib/gcc/genoutput.c | 95 +- contrib/gcc/genpeep.c | 66 +- contrib/gcc/genrecog.c | 98 +- contrib/gcc/getopt.c | 397 +- contrib/gcc/getopt.h | 12 +- contrib/gcc/getopt1.c | 28 +- contrib/gcc/getpwd.c | 28 +- contrib/gcc/glimits.h | 7 +- contrib/gcc/global.c | 146 +- contrib/gcc/gmon.c | 21 +- contrib/gcc/gsyms.h | 12 +- contrib/gcc/gthr-dce.h | 150 + contrib/gcc/gthr-posix.h | 147 + contrib/gcc/gthr-single.h | 62 + contrib/gcc/gthr-solaris.h | 177 + contrib/gcc/gthr-vxworks.h | 132 + contrib/gcc/gthr.h | 99 + contrib/gcc/haifa-sched.c | 8738 +++++++++++ contrib/gcc/halfpic.c | 17 +- contrib/gcc/halfpic.h | 26 +- contrib/gcc/hard-reg-set.h | 199 + contrib/gcc/hash.c | 204 + contrib/gcc/hash.h | 130 + contrib/gcc/input.h | 4 +- contrib/gcc/integrate.c | 679 +- contrib/gcc/integrate.h | 12 +- contrib/gcc/invoke.texi | 2428 ++- contrib/gcc/jump.c | 693 +- contrib/gcc/just-fixinc | 2 +- contrib/gcc/libgcc1-test.c | 6 + contrib/gcc/libgcc2.c | 2871 +++- contrib/gcc/listing | 6 +- contrib/gcc/local-alloc.c | 874 +- contrib/gcc/longlong.h | 683 +- contrib/gcc/loop.c | 2022 ++- contrib/gcc/loop.h | 17 +- contrib/gcc/machmode.def | 10 +- contrib/gcc/machmode.h | 107 +- contrib/gcc/makefile.vms | 413 + contrib/gcc/md.texi | 329 +- contrib/gcc/mips-tdump.c | 141 +- contrib/gcc/mips-tfile.c | 617 +- contrib/gcc/objc/Make-lang.in | 312 + contrib/gcc/objc/Makefile.in | 91 + contrib/gcc/objc/NXConstStr.h | 8 +- contrib/gcc/objc/NXConstStr.m | 8 +- contrib/gcc/objc/Object.h | 2 +- contrib/gcc/objc/Object.m | 10 +- contrib/gcc/objc/README | 2 +- contrib/gcc/objc/archive.c | 203 +- contrib/gcc/objc/class.c | 45 +- contrib/gcc/objc/config-lang.in | 37 + contrib/gcc/objc/encoding.c | 27 +- contrib/gcc/objc/encoding.h | 4 +- contrib/gcc/objc/hash.c | 57 +- contrib/gcc/objc/hash.h | 6 +- contrib/gcc/objc/init.c | 535 +- contrib/gcc/objc/makefile.dos | 8 +- contrib/gcc/objc/misc.c | 130 +- contrib/gcc/objc/objc-act.c | 8455 ++++++++++ contrib/gcc/objc/objc-act.h | 117 + contrib/gcc/objc/objc-api.h | 147 +- contrib/gcc/objc/objc-tree.def | 37 + contrib/gcc/objc/objc.gperf | 64 + contrib/gcc/objc/objc.h | 12 +- contrib/gcc/objc/objects.c | 14 +- contrib/gcc/objc/runtime.h | 32 +- contrib/gcc/objc/sarray.c | 339 +- contrib/gcc/objc/sarray.h | 23 +- contrib/gcc/objc/selector.c | 191 +- contrib/gcc/objc/sendmsg.c | 301 +- contrib/gcc/objc/typedstream.h | 2 +- contrib/gcc/obstack.c | 198 +- contrib/gcc/obstack.h | 367 +- contrib/gcc/optabs.c | 591 +- contrib/gcc/output.h | 76 +- contrib/gcc/patch-apollo-includes | 69 + contrib/gcc/pexecute.c | 775 + contrib/gcc/prefix.c | 331 + contrib/gcc/print-rtl.c | 133 +- contrib/gcc/print-tree.c | 128 +- contrib/gcc/profile.c | 1702 ++ contrib/gcc/protoize.c | 473 +- contrib/gcc/real.c | 923 +- contrib/gcc/real.h | 99 +- contrib/gcc/recog.c | 138 +- contrib/gcc/recog.h | 86 +- contrib/gcc/reg-stack.c | 617 +- contrib/gcc/regclass.c | 588 +- contrib/gcc/regmove.c | 1983 +++ contrib/gcc/regs.h | 73 +- contrib/gcc/reload.c | 1345 +- contrib/gcc/reload.h | 39 +- contrib/gcc/reload1.c | 3054 +++- contrib/gcc/reorg.c | 698 +- contrib/gcc/rtl.c | 120 +- contrib/gcc/rtl.def | 123 +- contrib/gcc/rtl.h | 827 +- contrib/gcc/rtl.texi | 118 +- contrib/gcc/rtlanal.c | 235 +- contrib/gcc/scan-decls.c | 32 +- contrib/gcc/scan.c | 19 +- contrib/gcc/scan.h | 16 +- contrib/gcc/sched.c | 1322 +- contrib/gcc/sdbout.c | 196 +- contrib/gcc/sdbout.h | 39 + contrib/gcc/stab.def | 24 +- contrib/gcc/stmt.c | 2515 ++- contrib/gcc/stor-layout.c | 288 +- contrib/gcc/stupid.c | 131 +- contrib/gcc/sys-protos.h | 21 +- contrib/gcc/sys-types.h | 1 + contrib/gcc/system.h | 316 + contrib/gcc/tlink.c | 633 + contrib/gcc/tm.texi | 1547 +- contrib/gcc/toplev.c | 3114 ++-- contrib/gcc/toplev.h | 65 + contrib/gcc/tree.c | 1615 +- contrib/gcc/tree.def | 391 +- contrib/gcc/tree.h | 1036 +- contrib/gcc/unprotoize.c | 1 + contrib/gcc/unroll.c | 505 +- contrib/gcc/varasm.c | 1866 ++- contrib/gcc/varray.c | 70 + contrib/gcc/varray.h | 166 + contrib/gcc/version.c | 2 +- contrib/gcc/xcoffout.c | 34 +- contrib/gcc/xcoffout.h | 48 +- 641 files changed, 407231 insertions(+), 77199 deletions(-) create mode 100644 contrib/gcc/LANGUAGES create mode 100644 contrib/gcc/README-bugs create mode 100644 contrib/gcc/README.g77 create mode 100644 contrib/gcc/acconfig.h create mode 100644 contrib/gcc/aclocal.m4 create mode 100644 contrib/gcc/alias.c create mode 100644 contrib/gcc/bitmap.c create mode 100644 contrib/gcc/bitmap.h create mode 100644 contrib/gcc/choose-temp.c create mode 100644 contrib/gcc/config.in create mode 100644 contrib/gcc/config/alpha/crtbegin.asm create mode 100644 contrib/gcc/config/alpha/crtend.asm create mode 100644 contrib/gcc/config/alpha/linux-ecoff.h create mode 100644 contrib/gcc/config/alpha/linux-elf.h create mode 100644 contrib/gcc/config/alpha/linux.h create mode 100644 contrib/gcc/config/alpha/netbsd-elf.h create mode 100644 contrib/gcc/config/alpha/netbsd.h create mode 100644 contrib/gcc/config/alpha/openbsd.h create mode 100644 contrib/gcc/config/alpha/osf.h create mode 100644 contrib/gcc/config/alpha/osf2or3.h create mode 100644 contrib/gcc/config/alpha/t-crtbe create mode 100644 contrib/gcc/config/alpha/t-vms create mode 100644 contrib/gcc/config/alpha/va_list.h create mode 100644 contrib/gcc/config/alpha/vms-tramp.asm create mode 100644 contrib/gcc/config/alpha/vms.h create mode 100644 contrib/gcc/config/alpha/vxworks.h create mode 100644 contrib/gcc/config/alpha/xm-openbsd.h create mode 100644 contrib/gcc/config/alpha/xm-vms.h create mode 100644 contrib/gcc/config/dbx.h create mode 100644 contrib/gcc/config/dbxcoff.h create mode 100644 contrib/gcc/config/float-i128.h create mode 100644 contrib/gcc/config/float-i32.h create mode 100644 contrib/gcc/config/float-i386.h create mode 100644 contrib/gcc/config/float-i64.h create mode 100644 contrib/gcc/config/float-m68k.h create mode 100644 contrib/gcc/config/float-sh.h create mode 100644 contrib/gcc/config/float-vax.h create mode 100644 contrib/gcc/config/i386/crtdll.h create mode 100644 contrib/gcc/config/i386/dgux.c create mode 100644 contrib/gcc/config/i386/dgux.h create mode 100644 contrib/gcc/config/i386/gmon-sol2.c create mode 100644 contrib/gcc/config/i386/mingw32.h create mode 100644 contrib/gcc/config/i386/moss.h create mode 100644 contrib/gcc/config/i386/openbsd.h create mode 100644 contrib/gcc/config/i386/osf1-ci.asm create mode 100644 contrib/gcc/config/i386/osf1-cn.asm create mode 100644 contrib/gcc/config/i386/osf1elf.h create mode 100644 contrib/gcc/config/i386/osf1elfgdb.h create mode 100644 contrib/gcc/config/i386/ptx4-i.h create mode 100644 contrib/gcc/config/i386/rtems.h create mode 100644 contrib/gcc/config/i386/rtemself.h create mode 100644 contrib/gcc/config/i386/sco5.h create mode 100644 contrib/gcc/config/i386/sco5gas.h create mode 100644 contrib/gcc/config/i386/sol2-gc1.asm create mode 100644 contrib/gcc/config/i386/t-dgux create mode 100644 contrib/gcc/config/i386/t-mingw32 create mode 100644 contrib/gcc/config/i386/t-osf create mode 100644 contrib/gcc/config/i386/t-osf1elf create mode 100644 contrib/gcc/config/i386/t-sco5 create mode 100644 contrib/gcc/config/i386/t-sco5gas create mode 100644 contrib/gcc/config/i386/vxi386.h create mode 100644 contrib/gcc/config/i386/x-dgux create mode 100644 contrib/gcc/config/i386/x-osf1elf create mode 100644 contrib/gcc/config/i386/x-sco5 create mode 100644 contrib/gcc/config/i386/xm-dgux.h create mode 100644 contrib/gcc/config/i386/xm-mingw32.h create mode 100644 contrib/gcc/config/i386/xm-openbsd.h create mode 100644 contrib/gcc/config/i386/xm-osf1elf.h create mode 100644 contrib/gcc/config/i386/xm-sco5.h create mode 100644 contrib/gcc/config/libgloss.h create mode 100644 contrib/gcc/config/openbsd.h create mode 100644 contrib/gcc/config/psos.h create mode 100644 contrib/gcc/config/ptx4.h create mode 100644 contrib/gcc/config/sparc/aout.h create mode 100644 contrib/gcc/config/sparc/bsd.h create mode 100644 contrib/gcc/config/sparc/elf.h create mode 100644 contrib/gcc/config/sparc/gmon-sol2.c create mode 100644 contrib/gcc/config/sparc/lb1spc.asm create mode 100644 contrib/gcc/config/sparc/lb1spl.asm create mode 100644 contrib/gcc/config/sparc/linux-aout.h create mode 100644 contrib/gcc/config/sparc/linux.h create mode 100644 contrib/gcc/config/sparc/linux64.h create mode 100644 contrib/gcc/config/sparc/lite.h create mode 100644 contrib/gcc/config/sparc/litecoff.h create mode 100644 contrib/gcc/config/sparc/lynx-ng.h create mode 100644 contrib/gcc/config/sparc/lynx.h create mode 100644 contrib/gcc/config/sparc/netbsd.h create mode 100644 contrib/gcc/config/sparc/openbsd.h create mode 100644 contrib/gcc/config/sparc/pbd.h create mode 100644 contrib/gcc/config/sparc/rtems.h create mode 100644 contrib/gcc/config/sparc/sol2-c1.asm create mode 100644 contrib/gcc/config/sparc/sol2-ci.asm create mode 100644 contrib/gcc/config/sparc/sol2-cn.asm create mode 100644 contrib/gcc/config/sparc/sol2-g1.asm create mode 100644 contrib/gcc/config/sparc/sol2-sld.h create mode 100644 contrib/gcc/config/sparc/sol2.h create mode 100644 contrib/gcc/config/sparc/sp64-aout.h create mode 100644 contrib/gcc/config/sparc/sp64-elf.h create mode 100644 contrib/gcc/config/sparc/sparc.c create mode 100644 contrib/gcc/config/sparc/sparc.h create mode 100644 contrib/gcc/config/sparc/sparc.md create mode 100644 contrib/gcc/config/sparc/splet.h create mode 100644 contrib/gcc/config/sparc/sun4gas.h create mode 100644 contrib/gcc/config/sparc/sun4o3.h create mode 100644 contrib/gcc/config/sparc/sunos4.h create mode 100644 contrib/gcc/config/sparc/sysv4.h create mode 100644 contrib/gcc/config/sparc/t-elf create mode 100644 contrib/gcc/config/sparc/t-sol2 create mode 100644 contrib/gcc/config/sparc/t-sp64 create mode 100644 contrib/gcc/config/sparc/t-sparcbare create mode 100644 contrib/gcc/config/sparc/t-sparclite create mode 100644 contrib/gcc/config/sparc/t-splet create mode 100644 contrib/gcc/config/sparc/t-sunos40 create mode 100644 contrib/gcc/config/sparc/t-sunos41 create mode 100644 contrib/gcc/config/sparc/t-vxsparc create mode 100644 contrib/gcc/config/sparc/vxsim.h create mode 100644 contrib/gcc/config/sparc/vxsparc.h create mode 100644 contrib/gcc/config/sparc/x-sysv4 create mode 100644 contrib/gcc/config/sparc/xm-linux.h create mode 100644 contrib/gcc/config/sparc/xm-lynx.h create mode 100644 contrib/gcc/config/sparc/xm-openbsd.h create mode 100644 contrib/gcc/config/sparc/xm-pbd.h create mode 100644 contrib/gcc/config/sparc/xm-sol2.h create mode 100644 contrib/gcc/config/sparc/xm-sp64.h create mode 100644 contrib/gcc/config/sparc/xm-sparc.h create mode 100644 contrib/gcc/config/sparc/xm-sysv4.h create mode 100644 contrib/gcc/config/t-freebsd create mode 100644 contrib/gcc/config/t-gnu create mode 100644 contrib/gcc/config/t-linux-aout create mode 100644 contrib/gcc/config/t-netbsd create mode 100644 contrib/gcc/config/t-openbsd create mode 100644 contrib/gcc/config/t-openbsd-thread create mode 100644 contrib/gcc/config/t-rtems create mode 100644 contrib/gcc/config/x-linux-aout create mode 100644 contrib/gcc/config/xm-alloca.h create mode 100644 contrib/gcc/config/xm-openbsd.h create mode 100644 contrib/gcc/config/xm-siglist.h create mode 100644 contrib/gcc/config/xm-std32.h create mode 100644 contrib/gcc/configure.frag create mode 100644 contrib/gcc/configure.in create mode 100644 contrib/gcc/configure.lang create mode 100644 contrib/gcc/cp/NEWS create mode 100644 contrib/gcc/cp/cp-tree.def create mode 100644 contrib/gcc/cp/exception.cc create mode 100644 contrib/gcc/cp/friend.c create mode 100644 contrib/gcc/cp/g++spec.c create mode 100644 contrib/gcc/cp/inc/exception create mode 100644 contrib/gcc/cp/inc/new create mode 100644 contrib/gcc/cp/inc/new.h create mode 100644 contrib/gcc/cp/inc/typeinfo create mode 100644 contrib/gcc/cp/mpw-config.in create mode 100644 contrib/gcc/cp/mpw-make.sed create mode 100644 contrib/gcc/cp/new.cc create mode 100644 contrib/gcc/cp/new1.cc create mode 100644 contrib/gcc/cp/new2.cc create mode 100644 contrib/gcc/cp/rtti.c create mode 100644 contrib/gcc/cp/semantics.c create mode 100644 contrib/gcc/cp/tinfo.cc create mode 100644 contrib/gcc/cp/tinfo.h create mode 100644 contrib/gcc/cp/tinfo2.cc create mode 100644 contrib/gcc/cstamp-h.in create mode 100644 contrib/gcc/dbxout.h create mode 100644 contrib/gcc/doprint.c create mode 100644 contrib/gcc/dwarf2.h create mode 100644 contrib/gcc/dwarf2out.c create mode 100644 contrib/gcc/dwarf2out.h create mode 100644 contrib/gcc/dwarfout.h create mode 100644 contrib/gcc/dyn-string.c create mode 100644 contrib/gcc/dyn-string.h create mode 100644 contrib/gcc/eh-common.h create mode 100644 contrib/gcc/except.c create mode 100644 contrib/gcc/except.h create mode 100644 contrib/gcc/f/BUGS create mode 100644 contrib/gcc/f/ChangeLog create mode 100644 contrib/gcc/f/Make-lang.in create mode 100644 contrib/gcc/f/Makefile.in create mode 100644 contrib/gcc/f/NEWS create mode 100644 contrib/gcc/f/README create mode 100644 contrib/gcc/f/ansify.c create mode 100644 contrib/gcc/f/assert.j create mode 100644 contrib/gcc/f/bad.c create mode 100644 contrib/gcc/f/bad.def create mode 100644 contrib/gcc/f/bad.h create mode 100644 contrib/gcc/f/bit.c create mode 100644 contrib/gcc/f/bit.h create mode 100644 contrib/gcc/f/bld-op.def create mode 100644 contrib/gcc/f/bld.c create mode 100644 contrib/gcc/f/bld.h create mode 100644 contrib/gcc/f/bugs.texi create mode 100644 contrib/gcc/f/bugs0.texi create mode 100644 contrib/gcc/f/com-rt.def create mode 100644 contrib/gcc/f/com.c create mode 100644 contrib/gcc/f/com.h create mode 100644 contrib/gcc/f/config-lang.in create mode 100644 contrib/gcc/f/config.j create mode 100644 contrib/gcc/f/convert.j create mode 100644 contrib/gcc/f/data.c create mode 100644 contrib/gcc/f/data.h create mode 100644 contrib/gcc/f/equiv.c create mode 100644 contrib/gcc/f/equiv.h create mode 100644 contrib/gcc/f/expr.c create mode 100644 contrib/gcc/f/expr.h create mode 100644 contrib/gcc/f/fini.c create mode 100644 contrib/gcc/f/flags.j create mode 100644 contrib/gcc/f/g77.1 create mode 100644 contrib/gcc/f/g77.texi create mode 100644 contrib/gcc/f/g77spec.c create mode 100644 contrib/gcc/f/glimits.j create mode 100644 contrib/gcc/f/global.c create mode 100644 contrib/gcc/f/global.h create mode 100644 contrib/gcc/f/hconfig.j create mode 100644 contrib/gcc/f/implic.c create mode 100644 contrib/gcc/f/implic.h create mode 100644 contrib/gcc/f/info-b.def create mode 100644 contrib/gcc/f/info-k.def create mode 100644 contrib/gcc/f/info-w.def create mode 100644 contrib/gcc/f/info.c create mode 100644 contrib/gcc/f/info.h create mode 100644 contrib/gcc/f/input.j create mode 100644 contrib/gcc/f/intdoc.c create mode 100644 contrib/gcc/f/intdoc.in create mode 100644 contrib/gcc/f/intdoc.texi create mode 100644 contrib/gcc/f/intrin.c create mode 100644 contrib/gcc/f/intrin.def create mode 100644 contrib/gcc/f/intrin.h create mode 100644 contrib/gcc/f/lab.c create mode 100644 contrib/gcc/f/lab.h create mode 100644 contrib/gcc/f/lang-options.h create mode 100644 contrib/gcc/f/lang-specs.h create mode 100644 contrib/gcc/f/lex.c create mode 100644 contrib/gcc/f/lex.h create mode 100644 contrib/gcc/f/malloc.c create mode 100644 contrib/gcc/f/malloc.h create mode 100644 contrib/gcc/f/name.c create mode 100644 contrib/gcc/f/name.h create mode 100644 contrib/gcc/f/news.texi create mode 100644 contrib/gcc/f/news0.texi create mode 100644 contrib/gcc/f/output.j create mode 100644 contrib/gcc/f/parse.c create mode 100644 contrib/gcc/f/proj.c create mode 100644 contrib/gcc/f/proj.h create mode 100644 contrib/gcc/f/rtl.j create mode 100644 contrib/gcc/f/src.c create mode 100644 contrib/gcc/f/src.h create mode 100644 contrib/gcc/f/st.c create mode 100644 contrib/gcc/f/st.h create mode 100644 contrib/gcc/f/sta.c create mode 100644 contrib/gcc/f/sta.h create mode 100644 contrib/gcc/f/stb.c create mode 100644 contrib/gcc/f/stb.h create mode 100644 contrib/gcc/f/stc.c create mode 100644 contrib/gcc/f/stc.h create mode 100644 contrib/gcc/f/std.c create mode 100644 contrib/gcc/f/std.h create mode 100644 contrib/gcc/f/ste.c create mode 100644 contrib/gcc/f/ste.h create mode 100644 contrib/gcc/f/storag.c create mode 100644 contrib/gcc/f/storag.h create mode 100644 contrib/gcc/f/stp.c create mode 100644 contrib/gcc/f/stp.h create mode 100644 contrib/gcc/f/str-1t.fin create mode 100644 contrib/gcc/f/str-2t.fin create mode 100644 contrib/gcc/f/str-fo.fin create mode 100644 contrib/gcc/f/str-io.fin create mode 100644 contrib/gcc/f/str-nq.fin create mode 100644 contrib/gcc/f/str-op.fin create mode 100644 contrib/gcc/f/str-ot.fin create mode 100644 contrib/gcc/f/str.c create mode 100644 contrib/gcc/f/str.h create mode 100644 contrib/gcc/f/sts.c create mode 100644 contrib/gcc/f/sts.h create mode 100644 contrib/gcc/f/stt.c create mode 100644 contrib/gcc/f/stt.h create mode 100644 contrib/gcc/f/stu.c create mode 100644 contrib/gcc/f/stu.h create mode 100644 contrib/gcc/f/stv.c create mode 100644 contrib/gcc/f/stv.h create mode 100644 contrib/gcc/f/stw.c create mode 100644 contrib/gcc/f/stw.h create mode 100644 contrib/gcc/f/symbol.c create mode 100644 contrib/gcc/f/symbol.def create mode 100644 contrib/gcc/f/symbol.h create mode 100644 contrib/gcc/f/system.j create mode 100644 contrib/gcc/f/target.c create mode 100644 contrib/gcc/f/target.h create mode 100644 contrib/gcc/f/tconfig.j create mode 100644 contrib/gcc/f/tm.j create mode 100644 contrib/gcc/f/top.c create mode 100644 contrib/gcc/f/top.h create mode 100644 contrib/gcc/f/toplev.j create mode 100644 contrib/gcc/f/tree.j create mode 100644 contrib/gcc/f/type.c create mode 100644 contrib/gcc/f/type.h create mode 100644 contrib/gcc/f/version.c create mode 100644 contrib/gcc/f/version.h create mode 100644 contrib/gcc/f/where.c create mode 100644 contrib/gcc/f/where.h create mode 100644 contrib/gcc/fp-test.c create mode 100644 contrib/gcc/frame.c create mode 100644 contrib/gcc/frame.h create mode 100644 contrib/gcc/future.options create mode 100644 contrib/gcc/gansidecl.h create mode 100644 contrib/gcc/gcov-io.h create mode 100644 contrib/gcc/gcov.c create mode 100644 contrib/gcc/gcov.texi create mode 100644 contrib/gcc/gcse.c create mode 100644 contrib/gcc/gencheck.c create mode 100644 contrib/gcc/gengenrtl.c create mode 100644 contrib/gcc/gthr-dce.h create mode 100644 contrib/gcc/gthr-posix.h create mode 100644 contrib/gcc/gthr-single.h create mode 100644 contrib/gcc/gthr-solaris.h create mode 100644 contrib/gcc/gthr-vxworks.h create mode 100644 contrib/gcc/gthr.h create mode 100644 contrib/gcc/haifa-sched.c create mode 100644 contrib/gcc/hash.c create mode 100644 contrib/gcc/hash.h create mode 100644 contrib/gcc/makefile.vms create mode 100644 contrib/gcc/objc/Make-lang.in create mode 100644 contrib/gcc/objc/Makefile.in create mode 100644 contrib/gcc/objc/config-lang.in create mode 100644 contrib/gcc/objc/objc-act.c create mode 100644 contrib/gcc/objc/objc-act.h create mode 100644 contrib/gcc/objc/objc-tree.def create mode 100644 contrib/gcc/objc/objc.gperf create mode 100755 contrib/gcc/patch-apollo-includes create mode 100644 contrib/gcc/pexecute.c create mode 100644 contrib/gcc/prefix.c create mode 100644 contrib/gcc/profile.c create mode 100644 contrib/gcc/regmove.c create mode 100644 contrib/gcc/sdbout.h create mode 100644 contrib/gcc/system.h create mode 100644 contrib/gcc/tlink.c create mode 100644 contrib/gcc/toplev.h create mode 100644 contrib/gcc/varray.c create mode 100644 contrib/gcc/varray.h (limited to 'contrib') diff --git a/contrib/gcc/BUGS b/contrib/gcc/BUGS index dc023cf..33c9386 100644 --- a/contrib/gcc/BUGS +++ b/contrib/gcc/BUGS @@ -1,5 +1,5 @@ If you think you may have found a bug in GNU CC, please -read the Bugs section of the Emacs manual for advice on +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 diff --git a/contrib/gcc/ChangeLog b/contrib/gcc/ChangeLog index ffdc477..f1be44e 100644 --- a/contrib/gcc/ChangeLog +++ b/contrib/gcc/ChangeLog @@ -1,5890 +1,14111 @@ -Thu Aug 22 23:47:38 1997 H.J. Lu (hjl@gnu.ai.mit.edu) +Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com) - * Version 2.7.2.3 released. + * egcs-1.1.2 Released. -Wed Aug 13 08:28:18 1997 H.J. Lu (hjl@gnu.ai.mit.edu) +Sun Mar 14 03:23:47 1999 Jeffrey A Law (law@cygnus.com) - * INSTALL, install.texi: Update for m68k-*-linuxaout, - m68k-*-linux-gnulibc1 and m68k-*-linux. + * README, gcc.1, gcc.texi, version.c: Update for egcs-1.1.2 release. -1997-08-12 Andreas Schwab +Thu Mar 11 14:00:58 1999 Richard Henderson - * config/m68k/t-linux: Define INSTALL_ASSERT_H and - TARGET_LIBGCC2_CFLAGS. - * config/m68k/t-linux-gnulibc1: New file. + * alpha.h (HARD_REGNO_MODE_OK): Disallow QI/HImode in fp regs. + (MODES_TIEABLE_P): Update. - * configure: Don't use GNU setup for *-*-linux-gnu*. - (m68k-*-linux*gnulibc1): New target. - (m68k-*-linux*): Set $extra_parts correctly. +Thu Mar 11 00:20:52 1999 Alexandre Oliva - * config/m68k/linux.h (STRICT_ALIGNMENT): Define to zero. - (CPP_SPEC, LIB_SPEC, LINK_SPEC): Add support for glibc 2. - (LIBGCC_SPEC): Always link in -lgcc independent of -shared. - (LIBCALL_VALUE): Use correct register for XFmode. - (LEGITIMATE_PIC_OPERAND_P): Reject CONST_DOUBLE with MEM with - invalid pic address. - (FINALIZE_TRAMPOLINE, CLEAR_INSN_CACHE): New. + * gcc.texi: Update bug reporting instructions to match + current ezmlm list reality. -Mon Mar 17 17:03:55 1997 J.T. Conklin +Mon Mar 8 01:19:23 1999 Jeffrey A Law (law@cygnus.com) - * m68k.md (beq0_di, bne0_di, bge0_di, blt0_di): Use cmpw #0 - instead of tstl when testing address registers on the 68000. + * version.c: Bump for prerelease. -Fri Aug 8 08:15:55 1997 H.J. Lu (hjl@gnu.ai.mit.edu) +Mon Mar 8 01:16:30 1999 Manfred Hollstein + Jeff Law - * Makefile.in (INSTALL): Fix the rule. - (stamp-crtS): Depend on stamp-crt for parallel make. + * configure.in (cpp_install_dir): Initialize from $enable_cpp + if that's looking like a pathname. + * configure: Rebuilt. - * install1.texi: New. + * Makefile.in (install-cpp, uninstall-cpp): cpp_install_dir is an + absolute pathname, not a $prefix relative pathname. -Mon Jul 21 22:47:13 1997 H.J. Lu (hjl@gnu.ai.mit.edu) +Fri Mar 5 01:19:22 1999 Jeffrey A Law (law@cygnus.com) - * configure (gxx_include_dir): Set it to $prefix/include/g++ - for Linux. + Thu Dec 17 18:21:49 1998 Rainer Orth + * fixincludes (c_asm.h): Wrap Digital UNIX V4.0B DEC C specific + asm() etc. function declarations in __DECC. -Tue Jun 24 11:24:56 1997 H.J. Lu (hjl@gnu.ai.mit.edu) +Wed Mar 3 23:55:14 1999 Zack Weinberg - * INSTALL, install.texi: Refer Linux running libc 5.x.x as - i386-*-linux-gnulibc1. + * cpp.in: New. Better cpp shell script. + * cpp.sh: Delete. + * Makefile.in (cpp.sh): Build from cpp.in - * config/i386/linux.h, config.guess, config.sub, configure: - Correct support for glibc 2. +Tue Mar 2 01:27:52 1999 H.J. Lu (hjl@gnu.org) - * config/t-linux: New, makefile fragment for Linux target with - glibc 2. + * 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. - * config/t-linux-gnulibc1: New, makefile fragment for Linux - target with libc 5.x.x. +Mon Mar 1 23:38:20 1999 Jeffrey A Law (law@cygnus.com) - * config/t-linux-libc1: Removed. + Tue Feb 2 23:38:35 1999 David O'Brien + * i386/freebsd*.h now allows '$' in label names and does not use the + PCC struct return method. - * config.sub: Add support for i686. + Wed Dec 30 23:00:28 1998 David O'Brien + * configure.in (FreeBSD ELF): Needs special crt files. + * configure: Rebuilt. - * gcc.c (main): check and read ${libdir}/gcc-lib/specs to - override the default specs. +Sun Feb 28 14:47:53 1999 Arturo Montes -Mon Jun 23 22:48:00 1997 Jim Wilson - - * unroll.c (find_splittable_givs): Set splittable_regs_updates - to biv_count for reduced givs. + * config/i386/t-sco5gas (crti.o): New target. -Tue Apr 16 16:59:49 1996 Richard Henderson +Sun Feb 28 00:50:28 1999 Franz Sirl + Jeffrey A Law (law@cygnus.com) - * function.c (expand_function_end): Allow TRAMPOLINE_TEMPLATE - to be omitted on systems for which it is not cost effective. - * varasm.c (assemble_trampoline_template): No such function - if no TRAMPOLINE_TEMPLATE. - * m68k.h: Greatly simplify the run-time trampoline code: - (TRAMPOLINE_TEMPLATE, TRANSFER_FROM_TRAMPOLINE): Delete define. - (TRAMPOLINE_SIZE, INITIALIZE_TRAMPOLINE): Changed. - (TRAMPOLINE_ALIGN): No point aligning to cache line. - (FINISH_INIT_TRAMPOLINE): New define. - * m68k/next.h: Instead of redefining INITIALIZE_TRAMPOLINE, - make use of the new FINISH_INIT_TRAMPOLINE. - * m68k/{m68k.h,next.h} (FINISH_INIT_TRAMPOLINE): - Rename to FINALIZE_TRAMPOLINE. + * 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) + + * 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 -Mon Apr 15 08:49:20 1996 Tom May (ftom@netcom.com) + * config/t-openbsd (T_CFLAGS): Add -Dmkstemps=my_mkstemps. - * cse.c (invalidate_skipped_set): Ignore CLOBBER after calling - note_mem_written, not before. +Sat Feb 27 19:37:04 1999 Arturo Montes -Sat Jun 29 12:33:39 1996 Richard Kenner + * 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. - * Version 2.7.2.1 released. +Sat Feb 27 19:29:46 1999 Toon Moene + Mark Mitchell + Jeffrey A Law (law@cygnus.com) -Tue Jun 11 20:18:03 1996 Per Bothner + * 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. - * fix-header.c (read_scna_file): Invoke FIXPROTO_INIT if defined. - * alpha.h (FIXPROTO_INIT): Define new macro. +Sat Feb 27 19:19:36 1999 Jeffrey A Law (law@cygnus.com) -Fri May 10 18:35:00 1996 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * SERVICE: Update from the FSF. - * loop.c (maybe_eliminate_biv_1): Disable all but two cases - of biv elimination with givs and restrict those two cases to - an ADD_VAL that is an address. +Fri Feb 26 19:31:25 1999 Dave Love -Mon Apr 22 16:50:19 1996 Jeremy Bettis + * md.texi, invoke.texi: Fix unterminated @xrefs. - * objc/hash.c (hash_value_for_key): Prevent endless loop when 0 was - stored in a hashtable. +Fri Feb 26 01:47:46 1999 Jeffrey A Law (law@cygnus.com) -Wed Apr 17 17:53:23 1996 Michael Meissner + 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. - * rs6000.c (expand_block_move_mem): Copy RTX_UNCHANGING_P. - (expand_block_move): Copy dest/src to registers using - copy_addr_to_reg, call expand_block_move_mem to copy all of the - bits. + * Makefile.in (compare, gnucompare): We do not care about + comparison failures for objc/linking.o either. -Mon Apr 8 13:46:28 1996 Michael Meissner +Wed Feb 24 23:17:41 1999 Jeffrey A Law (law@cygnus.com) - * rs6000.c (output_{prolog,epilog}): For V.4/eabi systems, change - prologue and epilogue so that accesses beyond the current stack - pointer are not done like they are for AIX. + Thu Feb 18 19:59:37 1999 Marc Espie + * 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. -Fri Mar 26 05:43:06 1996 Torbjorn Granlund + Thu Feb 18 13:15:56 1999 Marc Espie + * 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. - * vax.md (insv matcher): Call CC_STATUS_INIT. - * vax.h (NOTICE_UPDATE_CC): Handle ZERO_EXTRACT destination. + Wed Nov 19 12:56:54 1997 Andreas Schwab + * configure.in: Fix check for . + * configure: Rebuilt. -Sat Mar 23 18:25:39 1996 J"orn Rennecke (amylaar@meolyon.hanse.de) + * 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) - * c-typeck.c (set_init_index): Check for use outside an array - initializer. + * version.c: Bump for prerelease. -Sat Mar 23 09:21:40 1996 Doug Evans + * Makefile.in (compare, gnucompare): Ignore comparison failures + for some objects in the ObjC runtime. - * sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Don't unfix %g[234] - if fixed with -ffixed-. +Wed Feb 24 02:39:08 1999 Jeffrey A Law (law@cygnus.com) -Wed Mar 13 20:36:10 1996 Jim Wilson + Mon Dec 7 16:15:51 1998 J"orn Rennecke + * sh.c (output_far_jump): Emit braf only for TARGET_SH2. - * mips.c (mips_expand_prologue): Change TYPE_NEEDS_CONSTRUCTING to - TREE_ADDRESSABLE; - * pa.h (ASM_DECLARE_FUNCTION_NAME): Likewise. + Mon Nov 23 16:46:46 1998 J"orn Rennecke + * va-sh.h (__va_arg_sh1): Use __asm instead of asm. -Tue Mar 12 14:36:02 1996 Jason Merrill +Tue Feb 23 00:38:17 1999 Jeffrey A Law (law@cygnus.com) - * lex.c (real_yylex): Warn about using the `namespace' keyword. + Thu Sep 3 00:23:21 1998 Richard Henderson + * ginclude/va-alpha.h: Protect entire second portion of the + file against double inclusion. -Tue Feb 27 08:18:12 1996 Richard Earnshaw (rearnsha@armltd.co.uk) + Mon Aug 31 13:57:55 1998 Richard Henderson + * alpha/va_list.h: New file. + * alpha/x-alpha (EXTRA_HEADERS): New. Add va_list.h. - * arm.md (mov{si,sf,df}cc and matchers): All conditional move - patterns must have a mode. + Sat Aug 1 17:59:30 1998 Richard Henderson + * ginclude/va-alpha.h (va_list): Use a typedef, not a define. -Mon Feb 19 07:35:07 1996 Torbjorn Granlund +Sun Feb 21 20:35:10 1999 Jeffrey A Law (law@cygnus.com) - * rs6000.md (not:SI with assign and compare): Fix typo. + Wed Oct 28 22:58:35 1998 Jason Merrill + * tree.c (append_random_chars): New fn. + (get_file_function_name_long): Use it. -Wed Jan 24 18:00:12 1996 Brendan Kehoe + Thu Aug 13 17:08:11 1998 Jason Merrill + * tree.c (get_file_function_name_long): Split out... + (get_file_function_name): ...from here. - * alpha.c (alpha_write_verstamp): Only emit MS_STAMP and LS_STAMP, - not the extra numbers. + * config/aoutos.h (ASM_OUTPUT_CONSTRUCTOR): Delete. + (ASM_OUTPUT_DESTRUCTOR, ASM_OUTPUT_GC_ENTRY): Likewise. + * tm.texi: Update docs for constructors and destructors. -Wed Jan 17 21:22:40 1996 Brendan Kehoe +Tue Feb 16 21:02:07 1999 Anton Hartl - * cp/decl2.c (grokfield): Call cplus_decl_attributes with the attrlist. - Pass a null tree to grokdeclarator for its ATTRLIST arg, since it's - only ever used for functions in it. + * rs6000.md (call_value): Fix typo. -Tue Jan 16 06:01:28 1996 Thomas Graichen +Tue Feb 16 01:37:33 1999 Charles G Waldman - * i386/freebsd.h (ASM_WEAKEN_LABEL): Deleted; not supported. + * c-common.c (shorten_compare): Get the min/max value from the + underlying type of an enumeration, not the enumerated type itself. -Sun Jan 7 17:11:11 1996 David Edelsohn +Mon Feb 15 11:33:51 1999 Jeffrey A Law (law@cygnus.com) - * collect2.c (scan_libraries): Correct Import File ID interpretation. + Sat Jan 16 21:48:17 1999 Marc Espie (Marc.Espie@openbsd.org) + * gcc.c: (do_spec_1): Fix obvious typo. -Thu Dec 28 22:24:53 1995 Michael Meissner + * 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 (common mode functions): Add condition reg clobbers. + * sparc.c (output_scc_insn): Add missing argument to output_cbranch. -Tue Dec 19 15:08:31 1995 Jason Merrill + * loop.c (mark_loop_jump): Handle LO_SUM. If we encounter something + we do not understand, mark the loop and containing loops as invalid. - * collect2.c: Remove auto_export functionality. +Sun Feb 14 23:05:34 1999 Jeffrey A Law (law@cygnus.com) -Mon Dec 18 18:40:34 1995 Jim Wilson + Tue Feb 9 21:14:03 1999 J"orn Rennecke + * alias.c (init_alias_analysis): Avoid self-referential value + when setting reg_known_value from REG_EQUAL notes. - * svr4.h (ASM_IDENTIFY_GCC): Don't output stab here. - (ASM_IDENTIFY_GCC_AFTER_SOURCE): Output stab here instead of - above. + Mon Aug 17 02:03:55 1998 Richard Henderson + * regclass.c (allocate_reg_info): Respect MIN when clearing data. -Sat Dec 16 07:03:33 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * loop.c (scan_loop): Fix typo in last change. - * stor-layout.c (layout_record): When PCC_BITFIELD_TYPE_MATTERS, - compute bitpos using field_size % type_align instead of field_size. +Sat Feb 13 11:53:12 1999 Jeffrey A Law (law@cygnus.com) -Fri Dec 15 18:41:50 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + 1999-02-05 Michael Meissner + J"orn Rennecke + * 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. - * fixincludes (sys/wait.h): Add forward declaration of struct rusage - on AIX 3.2.5. + 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. -Sat Dec 9 18:05:03 1995 Jim Wilson + 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. - * expr.c (expand_expr, case INDIRECT_REF): Correct typo in May 8 - change. + Sun Sep 20 20:57:02 1998 Robert Lipe + * configure.in (i*86-*-sysv5*): Use fixinc.svr4 to patch byteorder + problems. + * configure: Regenerate. -Sun Nov 26 14:47:42 1995 Richard Kenner +Fri Feb 12 23:20:54 1999 Michael P. Hayes - * Version 2.7.2 released. + * loop.c (scan_loop): Call reg_in_basic_block_p before + loop_reg_used_before_p. - * function.c (fixup_var_refs_1): Make pseudo for DEST - in PROMOTED_MODE unless in a SUBREG. +Thu Feb 11 01:53:10 1999 Jeffrey A Law (law@cygnus.com) - * cse.c (insert): Don't put a REG into qty_const. + Wed Nov 18 22:13:00 1998 J"orn Rennecke + * expr.c (store_expr): Don't generate load-store pair + if TEMP is identical (according to ==) with TARGET. - * msdos/top.sed: Change version to 2.7.2. - * winnt/config-nt.sed: Likewise. +Thu Feb 11 01:06:49 1999 Nathan Sidwell -Sun Nov 26 14:41:49 1995 Douglas Rupp (drupp@cs.washington.edu) + * fold-const.c (range_binop): Take account of the bounded nature + of fixed length arithmetic when comparing unbounded ranges. - * Makefile.in (stamp-objlist): Change .o to $objext. +Wed Feb 10 11:03:22 1999 Richard Henderson - * alpha/win-nt.h (CPP_PREDEFINES): Set __unaligned and __stdcall - to null. - (ASM_SPEC): Add a translation for -g to -Zi. - * winnt/ld.c (main): Don't pass -g to link. - * winnt/oldnames.c: Reformat and add some new functions for gnat1. - * winnt/win-nt.h (LINK_SPEC): Pass -g to ld.exe. - Increase default stack size. - * configure ({alpha-dec,i386-ibm}-winnt3.5): Add oldnames.o - to extra_objs. - * libgcc2.c (trampoline): Add getpagesize and mprotect for WINNT. - -Sun Nov 26 14:25:26 1995 Uwe Seimet (seimet@chemie.uni-kl.de) + * configure.in (alphaev6*): Fix typo in target_cpu_default2. - * atari.h (FUNCTION_VALUE): Deleted; incorrect. +Tue Feb 9 00:00:14 1999 Mark Kettenis -Sun Nov 26 14:23:03 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * configure.in (i[34567]86-*gnu*): Set float_format to i386. + * configure: Rebuilt. - * fixincludes (curses.h): Allow space or tab after bool keyword, - instead of tab or tab. +Sat Feb 6 16:03:36 1999 Jeffrey A Law (law@cygnus.com) -Sun Nov 26 14:14:11 1995 Oliver Kellogg (oliver.kellogg@space.otn.dasa.de) + * invoke.texi, expr.c: Update email addresses. - * 1750a.md (pattern for HImode PSHM): Corrected. - (trunchiqi2, zero_extendqihi2, extendhftqf2): Corrected. - (pattern for movhi of CONST_INT to REG): Corrected. - (divmodqi pattern for DISN): Corrected. - (all shift patterns): Corrected. + * gcc.c, gcc.texi: Update email addresses. - * 1750a.h (REG_OK_FOR_INDEX_P, REG_OK_FOR_BASE_P): Corrected. - (ASM_OUTPUT_[datatype]): Corrected datalbl[].size computation - for output of arrays. +Sat Jan 30 05:27:25 1999 Jeffrey A Law (law@cygnus.com) -Sun Nov 26 14:08:57 1995 Dave Love + Thu Jan 21 01:59:30 1999 Richard Henderson + * explow.c (allocate_dynamic_stack_space): Use register_operand + instead of arith_operand, which does not exist. - * mips/iris5.h (NO_IMPLICIT_EXTERN_C): Define this again so - that unistd.h doesn't get badly `fixed' for C++. libg++ will now - build with this definition. +Thu Jan 28 09:44:04 1999 Jeffrey A Law (law@cygnus.com) -Sun Nov 26 14:02:43 1995 Robert E. Brown (brown@grettir.bibliotech.com) + * configure.in (hppa1.0-hp-hpux10*): Use t-pa. + * configure: Rebuilt. - * configure: Better workaround for Nextstep bug. +Thu Jan 21 23:27:06 1999 Jeffrey A Law (law@cygnus.com) -Sun Nov 26 13:55:07 1995 Torbjorn Granlund + * 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. - * rs6000.md (load_multiple matcher): Fix typo in opcode. +Thu Jan 21 20:33:31 1999 Richard Henderson -Sun Nov 26 13:51:08 1995 Lee Iverson + * rs6000.h (LEGITIMIZE_RELOAD_ADDRESS): Recognize and accept + transformations that we have performed earlier. + * alpha.h (LEGITIMIZE_RELOAD_ADDRESS): Likewise. - * final.c (final_start_function): Move call to sdbout_begin_function - back to final_scan_insn on MIPS systems so parameter descriptions are - recognized. +Sun Jan 17 20:39:20 1999 Richard Henderson -Sun Nov 26 13:43:06 1995 DJ Delorie (dj@delorie.co)m + * jump.c (rtx_renumbered_equal_p): Special case CODE_LABEL. - * msdos/top.sed: Don't insert "go32". +Sun Jan 17 19:01:47 1999 Jeffrey A Law (law@cygnus.com) -Sun Nov 26 12:08:23 1995 Jim Wilson + * i386.md (integer conditional moves): Add missing earlyclobbers. - * combine.c (nonzero_bits, case REG): Put POINTERS_EXTEND_UNSIGNED - code before stack pointer code. Return nonzero at end of stack - pointer code. + * 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. - * sparc.h (PRINT_OPERAND_ADDRESS): Handle CONST inside PLUS. +Fri Jan 15 01:19:42 1999 Jeffrey A Law (law@cygnus.com) - * Makefile.in (cppalloc.o): Add a rule to build it. + * 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. - * alpha.c (alpha_emit_set_const): Don't output SImode sequences - that rely on invisible overflow. Sign extend new when SImode. - Don't recur if new == c. Don't allow shift outside mode. Make - logical right shift be unsigned. + * h8300.h (ASM_OUTPUT_LABELREF): Use asm_fprintf, not fprintf. -Sun Nov 26 11:37:50 1995 Arne H. Juul (arnej@idt.unit.no) +Mon Jan 11 20:23:34 1999 Richard Henderson - * Makefile.in (compare*): Add "|| true" to avoid spurious - failure messages from some versions of make. + * 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. -Sun Nov 26 11:20:09 1995 Dmitry K. Butskoy (buc@stu.spb.su) +Thu Jan 7 00:33:33 1999 Bernd Schmidt - * expr.c (truthvalue_conversion): Add declaration. + * 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. -Sun Nov 12 18:09:35 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Wed Jan 6 23:37:47 1999 Jeffrey A Law (law@cygnus.com) - * Version 2.7.1 released. + * h8300.h (ASM_OUTPUT_LABELREF): Define. - * function.c (put_reg_into_stack): New arg volatile_p. - (put_var_into_stack): Call with new arg. +Wed Jan 6 02:23:36 1999 "Charles M. Hannum" -Sat Nov 11 08:25:34 1995 Jim Wilson + * 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. - * reload.c (output.h): Include it. - * Makefile.in (reload.o): Add dependence on output.h. +Fri Jan 1 11:48:20 1999 Jeffrey A Law (law@cygnus.com) -Thu Nov 9 11:24:20 1995 Jim Wilson + * i386.md (doubleword shifts): Fix dumb mistakes in previous change. - * mips.h (HARD_REGNO_NREGS): If FP_REG_P, always use UNITS_PER_FPREG - to calculate number of words needed. +Wed Dec 30 23:44:11 1998 Jeffrey A Law (law@cygnus.com) -Thu Nov 9 11:04:50 1995 Oliver Kellogg (Oliver.Kellogg@space.otn.dasa.de) + * m68k.md (adddi_dilshr32): Allow all operands to be registers too. + (adddi_dishl32): Similarly. - * 1750a.md (cmphf): Addd Base Reg with Offset address mode (LB,STB,..) - (movqi,movhi,movhf,addqi3,addhf3,subqi3,subhf3,mulqihi3): Likewise. - (mulhf3,divhf3,andqi3,iorqi3): Likewise. - (define_peephole): Remove the Base mode peepholes. Replace the - special addqi define_insn for "LIM Ra,sym,Rb" by a define_peephole. - (ashlqi3): Took out futile 0th alternative. - (lshrqi3, lshrhi3, ashrqi3, ahsrhi3): Correct case of non-constant - shift count. + * cse.c (invalidate_skipped_block): Call invalidate_from_clobbers + for each insn in the skipped block. - * 1750a.h (REG_ALLOC_ORDER): Define. - (REGNO_OK_FOR_BASE_P): Include stack pointer in test against - reg_renumber[REGNO]. - (ASM_OUTPUT_DESTRUCTOR): Remove bogus assembler comment. + * i386.md (doubleword shifts): Avoid namespace pollution. -Thu Nov 9 11:01:33 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Mon Dec 28 10:44:40 1998 Richard Henderson - * expr.c (expand_expr, case ARRAY_REF): Properly convert types - of index, size, and multiplication. + * combine.c (subst): Process the inputs to a parallel asm_operands + only once. -Wed Nov 8 09:00:22 1995 Richard Earnshaw (rearnsha@armltd.co.uk) +Sun Dec 13 00:09:47 1998 Jeffrey A Law (law@cygnus.com) - * arm.md (mov*cc_{,soft_}insn): Use match_operator to test the - comparison and check that the condition code register is used. + * i386/next.h (ASM_OUTPUT_ALIGN): Use 0x90 for fill character. -Wed Nov 8 08:49:35 1995 Michael Meissner + * h8300.c (h8300_encode_label): Use '&' for tiny data items. + * h8300.h (TINY_DATA_NAME_P): Likewise. + (STRIP_NAME_ENCODING): Handle '&'. - * rs6000/sysv4.h (ASM_OUTPUT_{CONSTRUCTOR,DESTRUCTOR}): Undef before - including svr4.h. +Wed Dec 2 01:44:58 1998 Jeffrey A Law (law@cygnus.com) -Tue Nov 7 10:58:12 1995 Torbjorn Granlund + * egcs-1.1.1 released. - * m68k.md (subxf3): Properly name pattern. +Mon Nov 23 20:28:02 1998 Mike Stump -Tue Nov 7 10:53:09 1995 Michael Meissner + * 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. - * libgcc2.c (__{C,D}TOR_LIST): For AIX, initialize these arrays to - 0,0, just like NeXT to avoid a warning message from the AIX 4.1 - linker. +Mon Nov 23 09:53:44 1998 Richard Henderson -Tue Nov 7 09:58:34 1995 John F. Carr + * local-alloc.c (local_alloc): Use malloc not alloca for + reg_qty, reg_offset, ref_next_in_qty. - * cppexp.c (cpp_lex): Correctly parse character constants. +Mon Nov 23 09:49:49 1998 Andrew MacLeod -Tue Nov 7 09:52:15 1995 Jason Merrill + * cplus-dem.c (demangle_prefix): Use the last "__" + in the mangled name when looking for the signature. This allows + template names to begin with "__". - * rs6000.h (ASM_OUTPUT_{DES,CONS}TRUCTOR): Define. +Mon Nov 23 09:40:41 1998 David Edelsohn -Mon Nov 6 10:27:15 1995 Doug Evans + * rs6000.h (LEGITIMIZE_ADDRESS): Add missing "goto WIN". - * combine.c (force_to_mode): Fix typo. +Mon Nov 9 23:29:39 1998 David Edelsohn -Sun Nov 5 18:37:02 1995 Torbjorn Granlund + * rs6000.md (floatunssidf2_internal splitter): Use base register + operand, not hard-coded SP. - * m68k.md (cmpxf): Don't call force_const_mem, it looses for PIC; - get predicates right instead. Get rid of separate DEFINE_EXPAND. - (addxf3, subxf3, mulxf3, divxf3): Likewise. - (All XFmode patterns): Delete `F' and `G' constraints. - (absxf2, negxf2): Delete spurious condition on TARGET_FPA. +Mon Nov 9 23:05:51 1998 Richard Earnshaw (rearnsha@arm.com) -Sun Nov 5 11:05:44 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + Restore ABI compatibility for NetBSD. + * arm/netbsd.h (DEFAULT_PCC_STRUCT_RETURN): Override setting in + arm.h + (RETURN_IN_MEMORY): Likewise. - * fixincludes (malloc.h): Fix return type of {m,re}alloc. + * arm.c (add_constant): When taking the address of an item in the + pool, get the mode of the item addressed. -Sun Nov 5 11:02:26 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) + * 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. - * cse.c (invalidate): For a pseudo register, do a loop to - invalidate all table entries, irrespective of mode. +Mon Nov 9 22:43:57 1998 Jean-Pierre Radley -Sun Nov 5 10:57:43 1995 Richard Kenner + * fixinc.sco: Paramaterize #include_next values. + * fixinc/fixinc.sco: Likewise. - * combine.c (force_to_mode): Put in last change properly. +Mon Nov 9 22:43:57 1998 Robert Lipe -Sun Nov 5 10:53:49 1995 Jeffrey A Law (law@cygnus.com) + * fixinc.sco: Borrow code to wrap 'bool' typedefs from tinfo.h + and term.h from fixinc.wrap. - * pa.h (CONDITIONAL_REGISTER_USAGE): Make sure FP regs - get disabled regardless of PA1.0 vs PA1.1 code generation - when TARGET_SOFT_FLOAT or TARGET_DISABLE_FPREGS is on. +Thu Nov 5 07:57:45 EST 1998 Andrew MacLeod -Sun Nov 5 10:49:43 1995 Doug Evans + * except.c (expand_fixup_region_end): Make sure outer context labels + are not issued in an inner context during cleanups. - * i960.c (emit_move_sequence): Add a scratch register to - multi-reg stores. - (i960_output_move_{double,quad}): New functions. - (i960_print_operand): Handle new operand types E, F. - * i960.md (movdi matchers): Rewrite. - (store_unaligned_di_reg): New pattern. - (movti matchers): Rewrite. - (store_unaligned_ti_reg): New pattern. - -Sun Nov 5 10:45:24 1995 Ian Lance Taylor (ian@cygnus.com) +Sun Nov 1 11:04:32 1998 Jeffrey A Law (law@cygnus.com) - * mips.h (MULTILIB_DEFAULTS): Define. - * mips/elf64.h, mips/iris6.h (MULTILIB_DEFAULTS): Define. + * i386/linux.h (CPP_PREDEFINES): Bring back -Di386 for the last time. -Sun Nov 5 10:41:48 1995 Jim Wilson + * 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__. - * reload.c (push_reload): Delete abort for RELOAD_OTHER case added - in last change. - * reload1.c (emit_reload_insns): For RELOAD_OTHER output reloads, - output the reload insns in descending order of reloads. - - * sh.md (mulsidi3-1, mulsidi3, umulsidi3-1, umulsidi3): Enable. - (smulsi3_highpart-1, smulsi3_highpart): New patterns. - (umulsi3_highpart-1, umulsi3_highpart): Likewise. - (movdi-1): Add r/x constraint. - * t-sh (MULTILIB_OPTIONS): Add m2. - (MULTILIB_DIRNAMES): Add m2. - (MULTILIB_MATCHES): Define. +Sat Oct 31 00:40:05 1998 Jeffrey A Law (law@cygnus.com) - * sparc.h (RTX_COSTS, case MULT): Check for TARGET_SPARCLITE. + * 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. - * abi64.h, elf64.h (CPP_SPEC): Add -EB and -EL support. +Fri Oct 30 00:54:25 1998 Peter Jakubek -Sat Nov 4 10:36:26 1995 Jim Wilson + * m68k.h (INDIRECTABLE_1_ADDRESS_P): Fix thinko. - * sh.md (casesi_worker): Change constraint from = to +. +Thu Oct 29 12:14:58 1998 Jason Merrill - * svr4.h (ASM_IDENTIFY_GCC_AFTER_SOURCE): Delete. - (ASM_IDENTIFY_GCC): Output stab here. + * alpha/linux.h (CPP_PREDEFINES): Add missing space. -Sat Nov 4 10:32:37 1995 John Carr +Tue Oct 27 16:11:43 1998 David Edelsohn - * cpplib.c (finclude): Set current input pointer when input - is not a regular file. + * 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. - * cppmain.c: Define progname, required by cpplib. +Sun Oct 25 23:36:52 1998 Jason Merrill -Sun Oct 29 07:48:36 1995 Michael Meissner + * stmt.c (expand_fixup): Set fixup->before_jump to a + NOTE_INSN_DELETED instead of a NOTE_INSN_BLOCK_BEG. - * xcoffout.h (DBX_FINISH_SYMBOL): Deal with names created via - the __asm__ construct that start with a leading '*'. - * xcoffout.c (xcoff_declare_function): Likewise. +Sun Oct 25 18:35:06 1998 David Edelsohn -Sun Oct 29 07:45:41 1995 Jim Wilson + * ginclude/va-ppc.h (va_arg): longlong types in overflow area are + not doubleword aligned. - * stupid.c (stupid_mark_refs): Handle SUBREG of pseudo-reg in a - SET_DEST same as we handle a pseudo-reg in a SET_DEST. +Sun Oct 25 12:07:00 1998 Mumit Khan -Sun Oct 29 07:43:15 1995 Pat Rankin + * i386/crtdll.h (CPP_PREDEFINES): Fix typo. + * i386/mingw32.h (CPP_PREDEFINES): Likewise. - * libgcc2.c (L_eh: __unwind_function): Implement for VAX. - * vax.h (RETURN_ADDRESS_OFFSET, RETURN_ADDR_RTX): Define. +Fri Oct 23 22:41:40 1998 David Edelsohn -Sun Oct 29 12:39:08 1995 Richard Kenner a + * rs6000.md (movsf): Disable explicit secondary-reload-like + functionality if TARGET_POWERPC64. + (movdf): Remove TARGET_POWERPC64 explicit secondary-reload-like + functionality. - * i386/sol2.h (CPP_PREDEFINES): Add -D__SVR4. +Fri Oct 23 22:38:57 1998 Jeffrey A Law (law@cygnus.com) -Sun Oct 29 07:14:36 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) + * 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. - * reload.c (find_equiv_reg): Check for nonsaving setjmp. +Fri Oct 23 00:56:11 1998 Jason Merrill -Fri Oct 27 15:15:56 1995 Jim Wilson + * 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. - * Makefile.in (out_object_file): Depend on TREE_H. +Mon Oct 19 13:22:13 1998 Geoff Keating -Fri Oct 27 06:42:36 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * loop.c (scan_loop): Be more selective about what invariants are + moved out of a loop. - * alpha.c (call_operand): Only allow reg 27 on NT too. - * alpha.md (call_value_nt, call_nt): Force non-SYMBOL_REF - into reg 27, just like for OSF. +Wed Oct 14 23:27:08 1998 Didier FORT (didier.fort@fedex.com) - * rs6000.c (struct asm_option): Changed from struct option. - (expand_block_move_mem): Remove erroneously-added line. + * fixincludes: Fix up rpc/{clnt,svr,xdr}.h for SunOS. - * expr.c (clear_storage): SIZE is now rtx, not int. - (store_constructor): Call clear_storage with rtx. - (get_inner_reference): Convert index to precision of - sizetype, not POINTER_SIZE. - (expand_expr, case ARRAY_REF): Likewise. - * expr.h (clear_storage): Second arg is rtx, not int. +Wed Oct 14 22:13:28 1998 Joel Sherrill (joel@OARcorp.com) -Fri Oct 27 05:45:58 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) + * Makefile.in (stmp-fixinc): Do not install assert.h if not desired. + * config/t-rtems: Do not install assert.h -- use newlib's. - * combine.c (force_to_mode, case ASHIFTRT): Properly handle - mask wider than HOST_WIDE_INT. +Sat Oct 3 19:01:03 1998 Richard Henderson - * c-decl.c (pushdecl): Don't test TREE_PUBLIC when deciding whether - to register a duplicate decl in the current block. + * alpha/linux.h (CPP_PREDEFINES): Define __alpha__ for imake. -Thu Oct 26 21:55:39 1995 Jason Merrill +Fri Oct 2 01:33:30 1998 Jim Wilson - * calls.c (expand_call): Don't trust the callee to copy a - TREE_ADDRESSABLE type. - * function.c (assign_parms): Likewise. + * i386/winnt.c (i386_pe_asm_file_end): Check + TREE_SYMBOL_REFERENCED. -Thu Oct 26 19:25:05 1995 Mike Stump +Fri Oct 2 01:31:54 1998 Jeffrey A Law (law@cygnus.com) - * libgcc2.c (__unwind_function): Provide a default definition for - implementations that don't yet have a function unwinder. + * regclass.c (reg_scan_mark_refs): Return immediately if passed a + NULL_RTX as an argument. -Thu Oct 26 18:08:19 1995 Paul Eggert + * gcc.texi: Fix version # that somehow slipped through. - * cccp.c (handle_directive): Don't treat newline as white - space when coalescing white space around a backslash-newline. +Fri Oct 2 01:24:19 1998 Geoff Keating -Thu Oct 26 17:57:34 1995 Ian Lance Taylor + * 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. - * mips-tdump.c (enum st): Define st_Struct, st_Union, and st_Enum. - (st_to_string): Handle them. - (type_to_string): Add fdp argument; pass it to emit_aggregate. - (print_symbol): Add fdp argument; pass it to type_to_string. - Handle st_Struct, st_Union, and st_Enum. - (emit_aggregate): Add fdp argument. Handle opaque types. Map - through RFD entries. - (print_file_desc): Pass FDR to print_symbol. - (main): Pass null FDR to type_to_string. +Fri Oct 2 01:20:04 1998 Richard Earnshaw (rearnsha@arm.com) -Thu Oct 26 08:07:10 1995 Michael Meissner + * 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. - * configure (powerpc-ibm-aix[456789]*): Use rs6000/t-newas, - not rs6000/t-rs6000. - (rs6000-ibm-aix3.2.[456789]*): Likewise. - (rs6000-ibm-aix[456789]*): Likewise. + * 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. - * rs6000/t-newas: Copy from t-rs6000. - * t-rs6000: Don't build -mcpu=common multilib variants of libgcc.a. +Fri Oct 2 01:16:02 1998 Jeffrey A Law (law@cygnus.com) - * rs6000.md (load_multiple insn): If address register is among regs, - don't load it with a lwsi instruction, which is undefined on PowerPC. + * reg-stack.c (straighten_stack): Do nothing if the virtual stack is + empty or has a single entry. -Thu Oct 26 08:01:32 1995 Jim Wilson +Sat Sep 5 23:29:39 1998 Mumit Khan - * dwarfout.c (output_compile_unit_die): Handle language_string - of "GNU F77". + * i386/cygwin32.h (ASM_OUTPUT_SECTION_NAME): Don't check for + for exact section attributions. - * reload.c (find_reloads_address): When check for out of range constant - plus register, accept any hard register instead of just fp, ap, sp. + * i386/mingw32.h (CPP_PREDEFINES): Add __MSVCRT__ for msvc + runtime. + * i386/crtdll.h (CPP_PREDEFINES): Define. - * combine.c (distribute_notes): For Oct 19 change, add additional - check to verify that place has a valid INSN_CUID. +Sat Sep 5 21:46:47 1998 Richard Henderson - * sparc/t-vxsparc (LIBGCC1_TEST): Define. + * alpha.c (alpha_ra_ever_killed): Inspect the topmost sequence, + not whatever we're generating now. - * sh.md (negdi2): Use TARGET_LITTLE_ENDIAN. +Sat Sep 5 14:23:31 1998 Torbjorn Granlund - * combine.c (force_to_mode, case ASHIFTRT): Verify mode bitsize is - within HOST_BITS_PER_WIDE_INT before shifting by it. + * m68k.md (zero_extendsidi2): Fix typo. - * final.c (final_scan_insn): When recur for instruction in delay slot, - add loop around recursive call in case the instruction gets split. +Tue Sep 1 01:58:38 1998 Jeffrey A Law (law@cygnus.com) -Thu Oct 26 07:28:45 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) + * egcs-1.1 released. + * version.c: Update for egcs-1.1 release. - * genrecog.c (write_tree_1): Avoid emitting '-2147483648'. +Mon Aug 31 14:55:02 1998 Jeffrey A Law (law@cygnus.com) - * jump.c (duplicate_loop_exit_test): Return 0 if found - a NOTE_INSN_LOOP_CONT. + * NEWS: Add SCO Openserver and Unixware 7 notes. -Tue Oct 24 15:30:14 1995 Jeffrey A Law + * NEWS: Fix typos. - * calls.c (expand_call): Make sure valreg is at least - a full word. +Sat Aug 29 14:52:28 1998 David S. Miller -Sun Oct 22 19:35:41 1995 Jim Wilson + * 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. - * sh.h (INIT_SECTION_ASM_OP): Delete. - (HAVE_ATEXIT): Define. +Sat Aug 29 14:59:32 1998 Mumit Khan -Sun Oct 22 07:46:04 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * i386/cygwin32.h (ASM_OUTPUT_SECTION_NAME): Don't emit + .linkonce directive after the first time. - * libgcc2.c (__fixuns[xds]fsi): #undef MIN and MAX before #include - of limits.h. +Sat Aug 29 14:48:12 1998 Jeffrey A Law (law@cygnus.com) - * pa.c (pa_adjust_cost): Use pa_cpu, not pa_cpu_attr. + * m68k.md (beq0_di): Generate correct (and more efficient) code when + the clobbered operand overlaps with an input. + (bne0_di): Similarly. -Sun Oct 22 07:38:58 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) +Sat Aug 29 12:38:54 1998 Jeffrey A Law (law@cygnus.com) - * alpha.h (CONST_OK_FOR_LETTER_P): Use 'U' for unsigned constants. - * alpha.c (alpha_emit_set_const): Likewise. - * mips.c (gen_int_relational): Likewise. + * NEWS: Various updates. -Sun Oct 22 07:14:35 1995 Douglas Rupp (drupp@cs.washington.edu) +Tue Aug 25 19:35:24 1998 Jim Wilson - * i386.c (i386_return_pops_args): Don't need a FUNDECL to - check for type attributes in FUNTYPE. + * configure.in (powerpc-ibm-aix4.[12]*): Change from 4.[12].*. + (rs6000-ibm-aix4.[12]*): Likewise. + * configure: Regnerate. -Sat Oct 21 18:17:42 1995 Jim Wilson +Thu Aug 27 23:44:49 1998 Jeffrey A Law (law@cygnus.com) - * sh.md (define_delay): Don't accept any instruction for an annulled - slot, only accept those for which in_delay_slot is yes. - * sh.c (find_barrier): When hi_const returns true, increment count_si - by two if found_si is true. - Always use get_attr_length to compute length of instructions. - If count_hi or count_si out of range at end, need two PREV_INSN calls - not one. - When create new label, set LABEL_NUSES to 1. - (reg_unused_after): Ifdef out code for handling labels. - (prepare_scc_operands): New local variable mode. Set it from - sh_compare_op0 or sh_compare_op1. Use it instead of SImode in - force_reg calls. - - * optabs.c (expand_float): Emit missing barrier after unconditional - jump. + * 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. -Sat Oct 21 14:16:46 1995 Torbjorn Granlund +Tue Aug 25 19:43:11 1998 Jeffrey A Law (law@cygnus.com) - * alpha.md (cmpdf): Make conditional on TARGET_FP. + * From Alexandre: + * configure.in: Do not set thread_file to "irix" since no such + support exists yet. -Fri Oct 20 19:11:12 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) + * 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. - * combine.c (distribute_notes): Delete instructions without - side effect that set a subreg of an unused register. +Mon Aug 24 15:20:19 1998 David Edelsohn - * m68k.h (PREFERRED_RELOAD_CLASS): Check for !G constants - for DATA_OR_FP_REGS also. + * 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. -Fri Oct 20 18:57:10 1995 Ian Lance Taylor + * rs6000.md (movqi, movhi): Add CONSTANT_P_RTX. - * genmultilib: Output negations of unused alternatives, even if - one of the alternatives is selected. +Mon Aug 24 01:21:38 PDT 1998 Jeff Law (law@cygnus.com) -Fri Oct 20 18:48:50 1995 Jeff Law (law@hurl.cygnus.com) + * version.c: Bump for snapshot. - * integrate.c (output_inline_function): Turn on flag_no_inline - to avoid function integration once we begin writing deferred - output functions. +Sun Aug 23 00:47:52 1998 Jeffrey A Law (law@cygnus.com) -Fri Oct 20 18:46:33 1995 Michael Meissner + * regmove.c (optimize_reg_copy_3): Disable for egcs-1.1. - * rs6000.c (float_conv_temp): Delete global variable. - (stack_temps): New static array to hold stack temps. - (offsettable_mem_operand): Delete function. - (offsettable_addr_operand, rs6000_stack_temp): New functions. - (output_epilog): Zero stack_temps. +Thu Aug 20 13:56:53 1998 Michael Meissner - * rs6000.h (offsettable_addr_operand): Declare instead of - offsettable_mem_operand. - (PREDICATE_CODES): Use offsettable_addr_operand. - (float_conv_temp): Delete variable. + * 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. - * rs6000.md (move_to_float insns): Change move_to_float so - that it doesn't have a clobber of the memory address, and instead - passes the stack temp's memory address as one of the unspec args. - (fix_truncdfsi2): Use rs6000_stack_temp to allocate the temp. - (multiply, shift insns): Fix all cases of multiply and shift insns so - that the right mnemonics are used for -mcpu=common with both - -m{old,new}-mnemonics. +Wed Aug 19 21:33:19 1998 David Edelsohn -Fri Oct 20 17:58:19 1995 Jim Wilson + * 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. - * expr.c (safe_from_p, case RTL_EXPR): Return 0 if RTL_EXPR_SEQUENCE - exists. Delete code to return 0 if exp_rtl is zero. +Tue Aug 18 23:48:30 1998 Richard Henderson - * function.c (init_function_start): Don't call init_insn_lengths here. - * toplev.c (rest_of_compilation): Call it here. + * c-common.c (decl_attributes): Issue an error if the argument + to alias is not a string. -Thu Oct 19 19:19:06 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue Aug 18 13:05:59 BST 1998 Richard Earnshaw (rearnsha@arm.com) - * c-common.c (check_format_info): Make test for null pointer - more general. + * arm.c (arm_override_options): Remove lie about ignoring PIC flag. -Thu Oct 19 18:56:16 1995 Satoshi Adachi (adachi@wisdom.aa.ap.titech.ac.jp) +Tue Aug 18 10:32:11 1998 Jeffrey A Law (law@cygnus.com) - * fixincludes (stdlib.h): Be more general in edit to change - declaration of {c,m,re}alloc. + * haifa-sched.c (sched_analyze): Put all JUMP_INSNs on the last + pending memory flush list. -Thu Oct 19 18:48:53 1995 Torbjorn Granlund + * regmove.c (fixup_match_2): Do not call reg_overlap_mentioned_p + on notes. - * libgcc2.c (__udiv_w_sdiv): If we don't have sdiv_qrnnd, define - dummy variant of __udiv_w_sdiv. - -Thu Oct 19 18:45:21 1995 Jim Wilson + * regmove.c (optimize_reg_copy_1): Update REG_N_CALLS_CROSSED + and REG_LIVE_LENGTH as successful substitutions are made. - * alpha.h (ASM_SPEC): If GNU as is the default, then pass -g to - the assembler if -malpha-as. If GNU as is not the default, then pass - -g to the assembler is not -mgas. +Mon Aug 17 21:07:19 1998 Jeffrey A Law (law@cygnus.com) - * combine.c (distribute_notes): When search for new place to put - REG_DEAD note, call distribute_links if this new place is between - i2 and i3, and i2 uses the register. + * 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. -Thu Oct 19 18:41:36 1995 Michael Meissner + * 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. - * rs6000.md (float{,uns}sidf2): Rewrite to break the conversion - process into several general insns. - (move_to_float): New insns to move 2 integer regs into a float register - through memory, taking endianess into account. Make sure that the - floating temporary is a valid address. Use one temporary for all - floats converted. - (fix_truncdfsi2): Take endianess into account. +Mon Aug 17 11:25:52 1998 Richard Earnshaw - * rs6000.c ({low_32_bit,offsettable_mem}_operand): The function - low_32_bit_operand is now unused, delete it. New function - offsettable_mem_operand to determine if a memory address is - offsettable. - * rs6000.h ({low_32_bit,offsettable_mem}_operand): Ditto. - (PREDICATE_CODES): Ditto. + * arm.h (SECONDARY_INPUT_RELOAD_CLASS): Return NO_REGS if compiling + for architecture v4. - * rs6000.{c,h} (float_conv_temp): New global. - * rs6000.c (output_epilog): Zero out float_conv_temp. +Sun Aug 16 00:57:48 PDT 1998 Jeff Law (law@cygnus.com) - * Makefile.in (libgcc{1,2}.a): Allow LIB{1,2}FUNCS_EXTRA files to - end in .S as well as .c and .asm. + * version.c: Bump for snapshot. -Wed Oct 18 17:56:45 1995 Jose Alonso (sidinf@fpsp.fapesp.br) +Sun Aug 16 01:53:21 1998 Richard Henderson - * c-typeck.c (parser_build_binary_op): Warn about x^y==z, etc. + * reload.c (find_equiv_reg): Reject equivalences separated + by a volatile instruction. -Mon Oct 9 12:38:06 1995 Michael Meissner +Sun Aug 16 00:21:44 1998 Franz Sirl - * protoize.c (reverse_def_dec_list): Silence compiler warnings. + * rs6000/linux.h (CPP_OS_DEFAULT_SPEC): Define. -Mon Oct 9 12:35:54 1995 Andrew Cagney +Sat Aug 15 20:22:33 1998 H.J. Lu (hjl@gnu.org) - * ginclude/va-ppc.h (va_arg): Deal with long longs that would be - passed in the 7th register, and are passed in the stack instead. + * config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): Handle aggregated + return type. + * config/alpha/win-nt.h (ASM_OUTPUT_MI_THUNK): Likewise. -Fri Oct 6 13:47:10 1995 Jim Wilson +Fri Aug 14 21:07:03 1998 Jeffrey A Law (law@cygnus.com) - * alpha.h (ASM_SPEC): Add -g. + From Joern: + * expr.c (store_expr): Don't optimize away load-store pair + when either source or destination have a side effect. -Fri Oct 6 13:42:50 1995 Richard Kenner + * 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.h (alpha_{arg,auto}_offset): Make extern. + * pa.h (ASM_OUTPUT_MI_THUNK): Strip name encoding. -Fri Oct 6 13:24:43 1995 Michael Meissner + * m68k.md (adddi_dilshr32): One of the operands must be a register. + (adddi_dishl32): Similarly. - * rs6000.h (RETURN_ADDRESS_OFFSET): Correct previous change. +Fri Aug 14 01:45:06 1998 Mumit Khan -Fri Oct 6 13:14:43 1995 Doug Evans + * i386/cygwin32.h (DEFAULT_PCC_STRUCT_RETURN): Define. - * rtlanal.c (reg_set_last): Fix call to reg_set_between_p. +Fri Aug 14 01:40:21 1998 Geoffrey Keating -Tue Oct 3 12:31:38 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * rs6000/linux.h (LINK_SPEC): Pass -G args to the linker. - * stor-layout.c (layout_type, case ARRAY_TYPE): Strip MAX_EXPR - from upper bound when computing length if it just protects against - negative length. +Fri Aug 14 01:23:23 1998 Richard Earnshaw (rearnsha@arm.com) - * expr.c (emit_move_insn_1): When doing multi-word move, show - output is clobbered. + * arm/netbsd.h (TARGET_DEFAULT): Default includes software floating + point. + (CPP_FLOAT_DEFAULT_SPEC): Re-define accordingly. -Tue Oct 3 12:26:07 1995 Jim Wilson +Fri Aug 14 01:23:23 1998 Jeffrey A Law (law@cygnus.com) - * cse.c (set_nonvarying_address_components, case AND): Add *pend to - end. Add constant to start instead of subtracting it. + * README.RS6000: Bring over dje's changes from the mainline + source tree. -Tue Oct 3 12:23:28 1995 Torbjorn Granlund +Fri Aug 14 01:19:08 1998 Robert Lipe - * combine.c (simplify_rtx): In code that attempts to simplify - conditional expressions, if the result is an NE around another - comparison, return the original expression. + * install.texi: Various SCO OpenServer tweaks. - * longlong.h (mips umul_ppmm): Use `l' and `h' constraints; - remove mflo and mfhi instructions. +Thu Aug 13 19:55:05 1998 Jim Wilson -Tue Oct 3 12:21:29 1995 Michael Meissner + * 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. - * ginclude/va-ppc.h (va_start, stdarg case): Call - __builtin_next_arg, and ignore the result, so that the compiler - can report the proper error, if the second argument is not the - last argument. +Tue Aug 11 17:45:39 1998 Dave Love -Tue Oct 3 12:02:51 1995 Kohtala Marko + * README.g77: Update from Craig. - * function.c (assign_stack_temp): Adjust full_size field of - temp_slot when splitting an unused slot. +Sat Aug 8 19:20:22 1998 Gary Thomas (gdt@linuxppc.org) -Tue Oct 3 11:51:59 1995 Mike Stump + * rs6000.c (rs6000_allocate_stack_space) Fix typo which + caused bad assembly code to be generated. - * expr.c (expand_builtin_return_addr): Break out functionality - from expand_builtin. - (expand_builtin): Call expand_builtin_return_addr. - * rs6000.h (RETURN_ADDR_RTX): Remove call to copy_to_reg. - Offset to return address is 4 when !TARGET_64BIT and v4_call_p, - 8 otherwise. - * sparc.h (RETURN_ADDR_RTX): Remove call to copy_to_reg. - * alpha.h (RETURN_ADDR_RTX): New definition. +Sat Aug 8 18:52:51 1998 Jeffrey A Law (law@cygnus.com) -Sun Oct 1 21:23:30 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * netbsd.h: Fix typo. - * tree.c (staticp, case INDIRECT_EXPR): Disable case. +Mon Aug 3 23:43:55 PDT 1998 Jeff Law (law@cygnus.com) - * expr.c (expand_expr, case COMPONENT_REF): If getting component - of union of variable size, propagate TARGET. + * version.c: Bump for snapshot. -Fri Sep 29 07:48:09 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Sun Aug 2 00:42:50 1998 Jeffrey A Law (law@cygnus.com) - * expr.c (store_expr): When storing promoted value, don't return - MEM if address contains target. + * i386/netbsd.h: Undo previous change to DWARF2_UNWIND_INFO. + * m68k/netbsd.h: Likewise. + * ns32k/netbsd.h: Likewise. + * sparc/netbsd.h: Likewise. -Thu Sep 28 14:30:03 1995 Paul Eggert +Fri Jul 31 17:08:59 1998 Jeffrey A Law (law@cygnus.com) - * cccp.c (rescan): Expand `#if foo && #bar' without a bogus - complaint about preprocessor directives within macro args. - Expand `foo' in `foo#bar' without requiring a space before `#'. + * configure.in (mingw configuration): Fix typo. + * configure: Rebuilt. -Thu Sep 28 14:24:26 1995 Philippe De Muyter (phdm@info.ucl.ac.be) +Fri Jul 31 20:22:02 1998 Michael Meissner - * m68k.md (anonymous DImode shift patterns setting cc0): Turned - off due to reload problems. + * rs6000.c (rs6000_override_options): If big endian and -Os, use + load/store multiple instructions unless user overrides. -Thu Sep 28 14:05:22 1995 Niklas Hallqvist (niklas@appli.se) +Fri Jul 31 17:08:59 1998 Jeffrey A Law (law@cygnus.com) - * Makefile.in (USER_H): Move up so can override. - (INSTALL_ASSERT_H): New definition. - (install-headers): Use it. - (stmp-int-hdrs): Handle USER_H being empty. - * config/x-netbsd (INSTALL_ASSERT_H): Define as empty. + * ns32k/netbsd.h: Fix typo. - * i386/netbsd.h (WCHAR_{TYPE,UNSIGNED,TYPE_SIZE}): Now int. - * m68k/netbsd.h, ns32k/netbsd.h, sparc/netbsd.h: Likewise. - * vax/netbsd.h: Likewise. - (SIZE_TYPE): Use unsigned int. +Thu Jul 30 19:50:15 1998 David Edelsohn - * m68k.c (output_scc_di): Swap operands when needed. - * m68k.h (LEGITIMATE_PIC_OPERAND): Allow SYMBOL_REF_FLAG symref. - * m68k.md: Make both assembler syntaxes do the same for PIC calls. + * rs6000/x-aix43 (AR_FOR_TARGET_FLAGS): Delete. + (AR_FOR_TARGET): Define. -Tue Sep 26 16:51:44 1995 Michael Meissner +Thu Jul 30 19:11:30 1998 Richard Henderson - * mips.c (override_options): Don't allow anything but integers to - go in the HI/LO registers. + * alpha.md (fp cmp): Replicate patterns for ALPHA_TP_INSN. + (fcmov): Remove ALPHA_TP_INSN patterns -- fcmov doesn't trap. -Tue Sep 26 16:36:18 1995 John F. Carr +Thu Jul 30 12:51:09 1998 Mark Mitchell - * c-common.c (check_format_info): Don't warn about format type - mismatch if the argument is an ERROR_MARK. + * 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 Sep 25 17:50:50 1995 Craig Burley (burley@gnu.ai.mit.edu) +Thu Jul 30 00:58:34 1998 Jeffrey A Law (law@cygnus.com) - * stor-layout.c (put_pending_sizes): New function. - * tree.h (put_pending_sizes): Add declaration. - * tree.c (save_expr): Return original for ERROR_MARK. + * i386.md (movqi): When optimizing a load of (const_int 1) into a + NON_QI_REG_P, pretend the register is SImode. -Fri Sep 22 19:20:01 1995 Jeff Law (law@hurl.cygnus.com) +Wed Jul 29 23:49:23 1998 Todd Vierling - * expr.c (expand_builtin, case BUILT_IN_MEMCPY): Strip off - all NOP exprs from the source and destination nodes, then - set MEM_IN_STRUCT_P. + * 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. -Fri Sep 22 18:50:31 1995 Michael Meissner +Wed Jul 29 22:39:21 1998 Jeffrey A Law (law@cygnus.com) - * rs6000/eabi.h (ASM_OUTPUT_INT): Test for whether the integer - being output is also a constant so &sym - &sym2 is not fixed up. + * unroll.c (unroll_loop): Do not abort for an UNROLL_MODULO + or UNROLL_COMPLETELY loop that starts with a jump to its + exit code. -Fri Sep 22 18:49:07 1995 Peter Flass (FLASS@LBDRSCS.BITNET) +Wed Jul 29 22:18:14 1998 David Edelsohn - * i370.md (cmpsi): Add missing constraints to operand 1. + * 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. -Fri Sep 22 18:27:33 1995 Torbjorn Granlund +Tue Jul 28 23:29:04 1998 Jason Merrill - * i386.h (CONST_OK_FOR_LETTER_P): Make `N' match range 0..255 - for `outb' instruction. + * configure.in: Fix --without/--disable cases for local-prefix, + gxx-include-dir and checking. - * pyr.h (PRINT_OPERAND): Handle code `R' for REG. - * longlong.h (pyr umul_ppmm): Use it. +Tue Jul 28 22:10:43 1998 David S. Miller -Fri Sep 22 18:24:38 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * configure.in (enable_haifa): Set by default for sparc64 too. + configure: Rebuilt. - * c-parse.in (enumlist): Propagate error_mark_node. +Tue Jul 28 23:29:04 1998 Jason Merrill - * c-aux-info.c (gen_type): Handle ERROR_MARK. + * 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. - * alpha.md (movdi): Avoid memory sharing problem when in reload. + From Antonio M. O. Neto : + * i386.c (i386_valid_type_attribute_p): Also accept + attributes for METHOD_TYPEs. -Wed Sep 20 14:27:09 1995 Peter Flass +Tue Jul 28 23:17:39 1998 Peter Gerwinski - * mvs.h (FUNCTION_PROLOGUE): Maintain savearea forward chain - per MVS standards. + * tree.c (build_range_type): Copy TYPE_SIZE_UNIT. -Wed Sep 20 14:20:52 1995 Torbjorn Granlund +Tue Jul 28 22:31:12 1998 Craig Burley - * pyr.md (cmphi recognizer): Make condition match constraints. - (cmpqi recognizer): Likewise. + * gcc.c: Fix commentary describing %g, %u, %U, and %O. -Wed Sep 20 12:42:59 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * integrate.c (expand_inline_function): Do copy something setting - the result register if it is setting it to itself and has a REG_NOTE. +1998-07-28 Vladimir N. Makarov - * integrate.c (set_decl_{origin_self,abstract_flags}): Treat - a DECL_INITIAL of error_mark_node the same as one of NULL_TREE. + * cse.c (cse_insn): Enable subsitution inside libcall only for REG, + SUBREG, MEM. + * rtlanal.c (replace_rtx): Prohibit replaces in CONST_DOUBLE. -Tue Sep 19 19:30:18 1995 Dave Pitts (dpitts@nyx.cs.du.edu) +Mon Jul 27 00:54:41 1998 Jason Merrill - * i370.md (cmphi, movhi, movstricthi, extendhisi2): Correct generation - of short integer (Halfword) - ({add,sub,mul,and,ior,xor}hi3): Likewise. - * i370/mvs.h (MACROPROLOGUE): New macro. - (FUNCTION_{PRO,EPI}LOGUE): Added ability to use IBM supplied function - prologue macros. - (FUNCTION_PROLOGUE): Corrected function "in-line" prologue alignment - problems. - (ASM_DECLARE_FUNCTION_NAME): Changed alignment to FullWord. - (ASM_OUTPUT_{SHORT,ASCII}): Reworked. + * tree.c (simple_cst_equal, case CONSTRUCTOR): OK if the elts are + identical. + +Mon Jul 27 22:20:02 1998 Jeffrey A Law (law@cygnus.com) + + * pa.c (move_operand): Accept CONSTANT_P_RTX. + +Mon Jul 27 00:46:56 PDT 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +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:02:54 1998 Jeffrey A Law (law@cygnus.com) + + * regmove.c (regmove_optimize): Fix typo initializing regmove_bb_head. + +Sat Jul 25 23:29:23 1998 Gerald Pfeifer + + * Makefile.in (install-info): Only try to update the info + directory file if it exists in the first place. + +Fri Jul 24 18:58:37 1998 Klaus Espenlaub + + * rs6000.h (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Delete. + +Thu Jul 23 18:53:20 1998 Jim Wilson + + * dbxout.c (dbxout_range_type): Only call dbxout_type_index for + already defined type. + +Wed Jul 22 14:08:54 1998 David S. Miller + + * profile.c (branch_prob): Call allocate_reg_info after outputting + profile rtl in instrument_arcs. + +Tue Jul 21 22:40:09 PDT 1998 Jeff Law (law@cygnus.com) -Tue Sep 19 19:22:15 1995 Douglas Rupp (drupp@cs.washington.edu) + * version.c: Bump for snapshot. - * winnt/win-nt.h: Renamed from winnt/win-nt.h. - (LINK_SPEC): Add -noinhibit-exec. - * {alpha,i386}/win-nt.h: Renamed from {alpha,i386}/winnt.h. - Include winnt/win-nt.h, not winnt/winnt.h. - * winnt/oldnames.c: New file. - * winnt/headers.mak (fixinc-nt.obj): Fix typo. - * winnt/config-nt.bat: Change winnt.h to win-nt.h. - * i386/config-nt.sed: Likewise. - * configure ({alpha,i386}-*-winnt3*): Likewise. +Tue Jul 21 23:28:35 1998 Klaus Kaempf -Mon Sep 18 14:00:45 1995 Oliver Kellogg (Oliver.Kellogg@space.otn.dasa.de) + * cccp.c (do_include): Fix vax c style include handling. - * 1750a.h (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): - Added R2 and R0_1. - (REG_CLASS_FROM_LETTER): New letters 't' and 'z'. - (EXTRA_CONSTRAINT): New letter 'Q'. +Tue Jul 21 15:49:31 1998 David Edelsohn -Sun Sep 17 12:39:22 1995 Jeff Law (law@snake.cs.utah.edu) + * 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. - * pa.h (ASM_DECLARE_FUNCTION_NAME): If a parameter's type - has TYPE_NEEDS_CONSTRUCTING on, then it's passed by invisible - reference. +Tue Jul 21 03:59:08 1998 David S. Miller -Sat Sep 16 17:42:33 1995 Jim Wilson + * 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. - * loop.c (find_and_verify_loops): Fix error in last change. +Tue Jul 21 00:31:01 1998 Jeffrey A Law (law@cygnus.com) -Sat Sep 16 08:38:22 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * gcc.c (do_spec): Call "error" not "warning". - * alpha.h (GO_IF_LEGITIMATE_ADDRESS): Disallow SYMBOL_REF for - current function. + * configure.in: Fix minor problems with gas feature detection code. + * configure: Rebuilt. - * cse.c (recorded_label_ref): New variable. - (insert): Set instead of cse_jumps_altered. - (cse_main): Initialize it and return 1 if nonzero at end. + * gcc.c (do_spec): Issue a warning for '%[]' usage. -Fri Sep 15 18:26:49 1995 Torbjorn Granlund (tege@matematik.su.se) + * Undo this change. + * gcc.c: Delete %[spec] support. + (do_spec_1, case '('): Likewise. + (do_spec_1, case '['): Call error. - * fold-const (div_and_round_double): Change `carry', `quo_est', - and `scale' from plain int to `unsigned HOST_WIDE_INT'. +Mon Jul 20 22:34:17 1998 Richard Henderson -Fri Sep 15 18:24:24 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * cse.c (insert): Set cse_jumps_altered when inserting a LABEL_REF. +Mon Jul 20 22:51:57 1998 Ken Raeburn -Fri Sep 15 17:29:41 1995 Oliver Kellogg (Oliver.Kellogg@space.otn.dasa.de) + * 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. - * 1750a.c (b_mode_operand): New function. - (print_operand): Added code 'Q'. + * mips.h (MASK_DEBUG_E, MASK_DEBUG_I): Set to zero. -Fri Sep 15 17:27:23 1995 Jim Wilson + * 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 (find_and_verify_loops): When moving exit blocks out of - the loop, verify that the target of P is within the current loop. +Mon Jul 20 01:13:19 1998 Jim Wilson - * reorg.c (fill_slots_from_thread): Update thread if it is split. + * function.c (fixup_var_refs_insns): Handle CLOBBER of a CONCAT. -Fri Sep 15 17:06:51 1995 Michael Meissner +Sat Jul 18 15:20:19 1998 Mark Mitchell - * rs6000.md (decrement_and_branchsi and related insns): Don't use - a "2" to select a register preference for operand 1 if operand 2 - hasn't been seen yet. - Add appropriate clobbers in decrement_and_branchsi. - Add patterns where the pc/label_ref are interchanged. + * loop.c (maybe_eliminate_biv_1): Avoid signed/unsigned comparison + confusion when setting cc0. - * Makefile.in (gnucompare, stmp-multilib-sub): Remove extra . in - front of $(objext). +Fri Jul 17 03:26:12 1998 Rihcard Earnshaw (rearnsha@arm.com) - * rs6000.c (output_toc): Align DF constants if STRICT_ALIGNMENT. + * tree.c (valid_machine_attribute): Only create a new type variant if + there is a decl to use it. - * config/fp-bit.c (FLO_union_type): Add words field if double - precision to get at the separate words. - (FLO_union_type, pack_d, unpack_d): Use FLOAT_BIT_ORDER_MISMATCH - to determine when the bitfields need to be reversed, and - FLOAT_WORD_ORDER_MISMATCH when the words need to be reversed. +Fri Jul 17 02:01:00 1998 Jeffrey A Law (law@cygnus.com) -Fri Sep 15 16:41:43 1995 Jeff Law (law@snake.cs.utah.edu) + * Makefile.in (WARN_CFLAGS): Disable -W -Wall for the release + branch. - * reorg.c (fill_simple_delay_slots): When filling insn's delay slot - with JUMP_INSN, don't assume it immediately follows insn on - unfilled slots obstack. +Thu Jul 16 14:48:04 1998 Nick Clifton - * Makefile.in (caller-save.o): Depend on insn-codes.h. + * gcc.c (do_spec_1): Cope with %g/%u/%U options which do not have + a suffix. -Thu Sep 14 17:41:49 1995 Jim Meyering (meyering@comco.com) +Thu Jul 16 17:07:24 1998 Kaveh R. Ghazi - * protoize.c (do_cleaning): Don't blank out backslash-escaped - newlines in double quoted strings. + * cplus-dem.c (demangle_nested_args): Make function definition + static to match the prototype. -Thu Sep 14 16:20:35 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Thu Jul 16 01:17:44 1998 Richard Henderson - * emit-rtl.c (gen_lowpart): If gen_lowpart_common fails - for a REG, load it into a pseudo and try again. + * loop.c (emit_iv_add_mult): Scan the entire insn list generated + for the sequence, recording base values. -Thu Sep 14 14:15:16 1995 Stan Cox (coxs@dg-rtp.dg.com) +Wed Jul 15 00:52:54 PDT 1998 Jeff Law (law@cygnus.com) - * m88k.h (VERSION_INFO1): Removed BCS reference. - * m88k/dgux.h (ASM_SPEC, *_LEGEND): - Added -mno-legend option. -mstandard no longer implies that legend - legend information not be produced. - (LINK_SPEC): Removed -z text + * version.c: Bump for snapshot. -Tue Sep 12 19:05:39 1995 Jim Wilson +Wed Jul 15 00:52:20 PDT 1998 Jeff Law (law@cygnus.com) - * cccp.c (is_system_include): Call skip_redundant_dir_prefix. + * version.c: Bump for snapshot. -Tue Sep 12 18:58:21 1995 John Carr +Tue Jul 14 14:15:30 1998 Nick Clifton - * sparc.md: Change `*return "string"' to "string" in patterns. + * gcc.c: Remove ANSI-C ism from --help code. -Tue Sep 12 18:48:47 1995 Craig Burley (burley@gnu.ai.mit.edu) + * toplev.c: Support --help with USE_CPPLIB. - * function.c (put_var_into_stack): For CONCAT case, order of - placement depends on FRAME_GROWS_DOWNWARD, not STACK_GROWS_DOWNWARD. +Tue Jul 14 02:20:38 1998 Jeffrey A Law (law@cygnus.com) -Tue Sep 12 18:34:10 1995 Doug Evans + * configure.in: Rework gas feature code to work with symlink based + source trees. - * va-sparc.h (v9 varargs va_start): Handle __builtin_va_alist - being stack argument. + * version.c: Bump to avoid problems with old spec files during + bootstrap. - * sparc.h (STATIC_CHAIN_REGNUM): Use %g5 for sparc64. - (TRAMPOLINE_TEMPLATE): Rewrite for sparc64. - (TRAMPOLINE_SIZE): Is 40 for sparc64. - * sparc.c (sparc64_initialize_trampoline): Rewrite. +Mon Jul 13 23:11:44 1998 David S. Miller -Tue Sep 12 18:30:22 1995 Douglas Rupp (drupp@cs.washington.edu) + * 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. - * cp/Make-lang.in (cc1plus) : Removed unnecessary $(exeext). +Mon Jul 13 23:57:21 1998 Kamil Iskra - * configure: Added code to handle gcc_extra_objs. - (alpha-winnt): Changed xmake_file to winnt/x-winnt. - Added extra_gcc_objs=spawnv.o; changed extra_programs to ld.exe. - (i386-winnt): Changed xmake_file to winnt/x-winnt. - Added extra_gcc_objs=spawnv.o; changed extra_programs to ld.exe. - * configure.bat: Changed to used common winnt/config-nt.bat. - * Makefile.in: Changed various .o's to .$(objext)'s - (specs): Removed unnecessary $(exeext). - (EXTRA_GCC_OBJS): New variable. - (clean): Removed $(LIB2FUNCS_EXTRA) - * objc/Makefile: Changed archive command for libobjc.a to use $? - for objects. + * m68k/m68k.h (TARGET_SWITCHES): Clear MASK_68040_ONLY for + -m68020-40, -m68020-60 and -m5200. - * alpha/x-winnt, i386/x-winnt: Deleted. - * alpha/config-nt.bat, i386/config-nt.bat: Deleted. - * alpha/config-nt.sed, i386/config-nt.sed: Moved architecture - independent commands to config/winnt/config-nt.sed. - * alpha/winnt.h: Added -D_M_ALPHA to CPP_PREDEFINES. - Changed LIB_SPEC to be compatible with Gnu ld for NT. - * i386/winnt.h: Added -D_cdecl=__attribute__((__cdecl__)). - Change LIB_SPEC to be compatible with Gnu ld for NT. - * winnt/config-nt.bat, winnt/config-nt.sed: New files. - * winnt/dirent.{c,h}, winnt/fixinc-nt.c, winnt/headers.mak: New files. - * winnt/ld.c: Changed precedence of libraries to look for - libfoo.lib before libfoo.a - Changed to work like Gnu ld for NT. - * winnt/libgcc.mak, winnt/mklibgcc.c: New files. - * winnt/spawnv.c: Changed spawn function entry points to __spawn* - instead of spawn*. - * winnt/x-winnt: New file. - * fixinc-nt.sed: New file. - * fixinc.winnt: Rewritten to use fixinc-nt.sed. +Mon Jul 13 23:52:05 1998 Weiwen Liu - * gcc.c: Remove fix_argv kludge. + * gcc.c (do_spec_1): Fix %O handling for secure temporary file + creation. -Tue Sep 12 13:24:17 1995 Michael Meissner +Mon Jul 13 23:42:36 1998 Ralf Corsepius - * rs6000.md (power subdi3 pattern): Fix pattern to have 5 - alternatives, and correct 4th alternative to match reality. + * sh/elf.h (MAX_OFILE_ALIGNMENT): Undefine before including svr4.h. - * rs6000.md (adddi3, subdi3, negdi2): Add constraints so output reg - does not overlap one reg with one of the inputs. +Mon Jul 13 23:36:08 1998 Jim Wilson -Tue Sep 12 13:09:48 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * 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]. - * m68k.c (output_scc_di): Fixed for non-SGS_CMP_ORDER syntax. +Mon Jul 13 23:31:04 1998 Andreas Schwab - * collect2.c (scan_libraries): Cast lsyms' alloca to LDSYM*. + * m68k.c (output_scc_di): Use cmpw #0 only for address registers. -Tue Sep 12 13:04:12 1995 Niklas Hallqvist (niklas@appli.se) +Mon Jul 13 23:26:43 1998 Jeffrey A Law (law@cygnus.com) - * stmt.c (expand_start_stmt_expr): Do stack adjust in right place. + * tree.h (tree_common): Note front-end dependencies on layout of + this structure. - * stdarg.h (__gnuc_va_list): Make char * for NetBSD. +Mon Jul 13 23:18:39 1998 Craig Burley -Tue Sep 12 12:44:46 1995 Jason Merrill + * stmt.c (expand_expr_stmt): If not assigning fresh + value to last_expr_value, zero it, so old garbage + doesn't get dereferenced. - * ginclude/va-ppc.h (va_arg): Reorganize to avoid BIND_EXPRs of - aggregate or array type. +Mon Jul 13 23:06:55 1998 Henning.Petersen@t-online.de (Henning Petersen) -Tue Sep 12 12:42:27 1995 Ian Lance Taylor + * gcse.c (hash_scan_insn): Add missing argument declaration. - * fixincludes: Fix HP/UX for g++ -pedantic-errors. +Mon Jul 13 18:59:13 1998 Jim Wilson - * fixincludes (curses.h): typedef bool need not take up entire line. + * 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. -Mon Sep 11 19:05:42 1995 Stan Cox (coxs@dg-rtp.dg.com) +Mon Jul 13 17:18:47 1998 Nick Clifton - * c-typeck.c (digest_init): Don't recursively call digest_init - when in traditional mode if the type is invalid. + * cccp.c (main): Add support for parsing --help. + (display_help): New function: display command line switches. -Mon Sep 11 18:58:26 1995 Oliver Kellogg (Oliver.Kellogg@space.otn.dasa.de) + * cpplib.c (cpp_handle_option): Add support for parsing --help. + (display_help): New function: display command line switches. - * 1750a.md: Added DLB/DSTB peepholes for HFmode. - Corrected mnemonics for HImode DSTB peephole. + * 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 Sep 11 18:48:06 1995 Michael Meissner + * tm.texi (TARGET_SWITCHES and TARGET_OPTIONS): Document + 'description' field added to structure. - * config/fp-bit.c (FLO_union_type): Remove bitfields to set sign, - exponent, and mantissa, and add value_raw field, which is an - integer of the appropriate type. If _DEBUG_BITFLOAT is defined, - provide little and big endian bitfields. If the macro - FLOAT_BIT_ORDER_MISMATCH is defined, use explicit bitfields. - (pack_d, unpack_d): Switch to use value_raw and explicit shifts - and masks so that we don't have to worry about whether the target - is big or little endian unless FLOAT_BIT_ORDER_MISMATCH is - defined. If single precision floating point, rename to pack_f and - unpack_f, so there is no confusion in the debugger. + * toplev.c: Add support for parsing --help. + Add documentation strings to command line option tables. + (display_help): New function: display comman line switches. + +Mon Jul 13 16:15:10 1998 John Carr + + * 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. + +Mon Jul 13 15:10:09 1998 Philippe De Muyter + + * invoke.texi(-fno-builtin): Explain that the names of built-in + functions begin with `__builtin_', not `__'. + +Mon Jul 13 19:01:52 1998 J"orn Rennecke + + * reload1.c (reload_reg_free_before_p): Abort for RELOAD_FOR_OUTPUT. + +Mon Jul 13 10:50:17 1998 Mark Mitchell + + * 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. + +Mon Jul 13 10:19:00 1998 Jeffrey A Law (law@cygnus.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. + + * 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. + +Mon Jul 13 02:24:08 1998 David S. Miller + + * 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. + +Sun Jul 12 13:08:14 1998 Jeffrey A Law (law@cygnus.com) + + * collect2.c (main): Use "-x c" instead of "-lang-c" for force the + compiler into C mode. + +Sun Jul 12 01:27:05 1998 Jason Merrill + + * cplus-dem.c (demangle_nested_args): Return a value. + + * tree.h (TYPE_P): New macro. + +Sat Jul 11 16:19:48 1998 Mark Mitchell + + * 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. - * rs6000.h (rs6000_abi): New enumeration to describe which - ABI we're conforming to. - (rs6000_stack): Use abi enum, not AIX vs. V.4 boolean. - (ASM_OUTPUT_OPTIONS): New macro to print output options in .s file. - (ASM_FILE_START): Use it. - (output_options,rs6000_float_const): Declare new functions. +Sat Jul 11 02:59:08 1998 Richard Earnshaw - * rs6000.c (output_option{,s}): New functions to write -f, -m, - and -W options to the asm file. - (rs6000_float_const): New function to generate floating point - constants portably used in signed,unsigned -> double conversions. - (rs6000_stack_info,debug_stack_info): Use ABI enumeration instead - of AIX vs. V.4 boolean. + * 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. - * rs6000.md (float{,uns}sidf2): Call rs6000_float_const to - portably build the proper floating point constant for conversions. - (movdi): Properly handle movdi of CONST_{INT,DOUBLE} on little - endian systems. + * configure.in (thumb-*-coff*): Don't cause fixincludes to be run. - * rs6000/sysv4.h (LIBGCC2_WORDS_BIG_ENDIAN): Define to be 0/1 - depending on the target endianess. - (ASM_FILE_START): Define, to call output_options in addition to - output_file_directive. - (TRAMPOLINE_SIZE): Correct size to match code. +Fri Jul 10 19:06:59 1998 Michael Meissner - * rs6000/eabi{,le}sim.h (CPP_SPEC): Define the correct endian - macro for varargs/stdargs use. + * varray.h: Include system.h if it hasn't already been included + before to get size_t declared. -Mon Sep 11 18:41:58 1995 Jim Wilson +Fri Jul 10 12:53:58 1998 David S. Miller - * c-decl.c (redeclaration_error_message): For TYPE_DECLs, return 0 - if TYPE_MAIN_VARIANT of old type is same as new type. + * jump.c (jump_optimize): If after_regscan and our transformations + generate new REGs, rerun reg_scan. -Mon Sep 11 17:39:35 1995 Rob Ryan (robr@cmu.edu) +Fri Jul 10 11:50:43 EDT 1998 Andrew MacLeod - * xcoffout.c (xcoff_inlining): New variable, used in place of - xcoff_current_include_file when determining whether to use - absolute line numbers. - (xcoffout_source_file): Switched to using xcoff_inlining to - determine when to emit .bi/.ei directives. + * config/i960/i960.c (i960_address_cost): MEMA operands with + positive offsets < 4096 are free. -Mon Sep 11 16:55:06 1995 Torbjorn Granlund +Fri Jul 10 12:34:37 1998 Andreas Schwab - * m68k.md (cmpdi): Change patterns to allocate scratch register at - RTL generation time. - (tstdi): Likewise. + * config/m68k/m68k.c (const_uint32_operand): Recognize + CONSTANT_P_RTX. + (const_sint32_operand): Likewise. -Sun Sep 3 09:03:50 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Thu Jul 9 22:58:59 1998 Jeffrey A Law (law@cygnus.com) - * fold-const.c (size_binop): Don't pass 1 to NOTRUNC. + * Makefile.in (alias.o): Depend on $(EXPR_H). -Thu Aug 31 19:27:00 1995 Roland McGrath +Thu Jul 9 18:24:56 1998 J"orn Rennecke - * libgcc2.c: Include longlong.h. - [L_udivdi3 || L_divdi3 || L_umoddi3 || L_moddi3] (__udivmoddi4): - Define this `static inline' when defining these, so they all - remain leaf functions. + * 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. -Thu Aug 31 18:38:21 1995 Paul Eggert +Thu Jul 9 18:12:49 1998 J"orn Rennecke - * c-parse.in (ends_in_label): New %union member. - (stmts, stmt_or_label): Use new member to avoid lexical lookahead hack. - (lineno_stmt_or_labels): New rule. - (lineno_stmt_or_label, stmt_or_label): Yield nonzero if it ends - in a label. + * 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. -Thu Aug 31 08:31:40 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Thu Jul 9 18:01:05 1998 J"orn Rennecke - * cse.c (canon_hash, CONST_DOUBLE): Hash integer and real - differently. - * varasm.c (struct rtx_const): Add new field DI to union. - (decode_rtx_const, case CONST_DOUBLE): Use to hash CONST_DOUBLE - representing an integer. + * reload.c (find_equiv_reg): If need_stable_sp is set, + check if stack pointer is changed directly in a PARALLEL. - * va-alpha.h (__gnuc_va_list): Make __offset an int. - * alpha.c (alpha_builtin_saveregs): Properly compute address - of __offset both both OSF and WINNT. +Thu Jul 9 10:38:14 1998 Jeffrey A Law (law@cygnus.com) - * xm-alpha.h (sbrk): Don't define here. - * gmon.c (sbrk): Define here for __alpha. - * toplev.c (sbrk): Likewise. - * mips-tfile.c (malloc, calloc, realloc): Don't define for anybody. + * jump.c (duplicate_loop_exit_test): Fix thinko. - * reload.c (push_reload): Add case for output reload of a SUBREG - of a hard reg when output mode is invalid for that mode. - In both that case and existing case for in, don't remove SUBREG. - * reload1.c (emit_reload_insn): Emit RELOAD_OTHER output reloads last. +Thu Jul 9 01:30:37 1998 Joel Sherrill + Ralf Corsepius -Tue Aug 29 19:16:06 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * config/i386/rtemself.h: Updated to keep in sync with + config/i386/linux.h. - * c-common.c (decl_attribute, case A_PACKED): Check is_type first. - (decl_attribute, case A_T_UNION): Likewise. - Don't access TYPE_FIELDS if DECL is zero. - * c-decl.c (finish_struct): If transparent_union attribute - specified, validate it once we finish laying the union out. + * 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. -Mon Aug 28 05:58:03 1995 Paul Eggert + * config/rs6000/rtems.h: Defined STARTFILE_DEFAULT_SPEC. - * arm.c (arm_gen_movstrqi): Remove unused variable const_sxteen. +Wed Jul 8 21:43:14 1998 Jeffrey A Law (law@cygnus.com) - * bi-lexer.c (buffer, inpoint): Remove unused variables. + * 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. - * i370/mvs.h, i370/mvs370.c (mvs_label_emitted): Renamed - from mvs_label_emited. + * print-rtl.c (print_rtx): Revert previous patch. - * msdos/configur.bat: Fix misspelling of `maintainer-clean'. + * jump.c (duplicate_loop_exit_test): Do not duplicate the loop exit + test if the exit code has an insn with ASM_OPERANDS. -Sat Aug 26 06:57:17 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * i386/cygwin32.h (STDIO_PROTO): Fix typo. + * m32r.h (STDIO_PROTO): Fix typo. - * reload.c (push_secondary_reload): If X is a paradoxical SUBREG, - get mode and thing to reload from inside. - * reload1.c (emit_reload_insns): Do nothing for SUBREG whose - operand is unused subsequently. - In secondary reload case, if paradoxical SUBREG for output, reload - thing inside SUBREG, just like gen_reload. + * 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. -Fri Aug 25 19:26:53 1995 Paul Eggert + * flow.c (find_auto_inc): Remove most recent change. Real bug was + elsewhere. - * c-typeck.c (set_init_label): Don't die if an entire - brace-pair level is superfluous in the containing level. + * cse.c (count_reg_usage): Count registers used in addresses of + CLOBBERs. -Fri Aug 25 19:22:46 1995 Michael Meissner +Wed Jul 8 15:08:29 1998 Jim Wilson - * configure (powerpc{,le}-eabisim): Add support for a new target - that works under the PSIM simulator. - * rs6000/eabisim.h, rs6000/eabilesim.h, rs6000/t-eabisim: New files. + * Makefile.in (STAGESTUFF): Readd line lost during June 9 FSF merge. - * rs6000/eabi.h (STRICT_ALIGNMENT): If little endian, always set - strict alignment to 1. + * configure.in (mips64orion-*-rtems*): Use elf64.h not elfl64.h. -Fri Aug 25 19:22:23 1995 David Edelsohn +1998-07-08 Vladimir N. Makarov - * rs6000.md ({add,sub,mulsi}di3): Support both endian possibilities. - (negdi2): Likewise. + * config/fp-bit.c (__gexf2, __fixxfsi, __floatsixf): Add function + stubs. -Fri Aug 25 19:10:41 1995 Oliver Kellogg (Oliver.Kellogg@space.otn.dasa.de) + * 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) - * 1750a.md: Added peephole definitions for Load/Store Base insns - and eliminating redundant load in an equivalent store/load sequence. + * 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. -Fri Aug 25 18:33:27 1995 Craig Burley (burley@gnu.ai.mit.edu) + * configure.in: Also look at $srcdir/gas/configure to find a + gas version #. - * toplev.c (report_error_function): Don't attempt to use input - file stack to identify nesting of #include's if file name oflocation - diagnosed is not same as input_filename. +Wed Jul 8 00:28:22 1998 Carlo Wood -Fri Aug 25 07:31:47 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * dsp16xx.h : Clean up of macro OPTIMIZATION_OPTIONS - * integrate.c (output_inline_function): Switch to function obstack. +Tue Jul 7 21:18:14 1998 Mumit Khan -Mon Aug 21 13:29:54 1995 J"orn Rennecke (amylaar@meolyon.hanse.de) + * i386/cygwin32.h (ASM_DECLARE_FUNCTION_NAME): Merge duplicate + definitions from last two patches. - * i386.c (arithmetic_comparison_operator): New function. - (print_operand): Take into account that overflow flag is not - set the same as after a compare instruction. - * i386.md (decrement_and_branch_until_zero): Use - arithmetic_comparison_operator to decide if there is comparison - suitable to be expressed by condition code from an arithmetic op. +Tue Jul 7 23:03:34 1998 J"orn Rennecke -Mon Aug 21 13:26:13 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * reload1.c (choose_reload_regs): Don't set reload_override_in + if EQUIV is clobbered in INSN and the reload is done after INSN. - * m68k.md (adddi3, subdi3): "&" added to clobber's constraints. +Tue Jul 7 21:23:36 1998 J"orn Rennecke -Mon Aug 21 12:11:14 1995 Jim Wilson + * expr.c (emit_queue): If emitting a SEQUENCE, set QUEUED_INSN + to the first insn of the sequence. - * t-sparclite (MULTILIB_*, LIBGCC, INSTALL_LIBGCC): Define. +Tue Jul 7 21:05:25 1998 J"orn Rennecke - * sh.md (movdi-1, movdf-1): Make conditional on reload_completed, - delete conditions checking for pseudo registers and Q addresses. - Add code to handle SUBREG. + * cse.c (cse_insn): Don't make change without validation. - * local-alloc.c (wipe_dead_reg): Make a register mentioned in a - REG_INC note die after the instruction. +Tue Jul 7 11:40:05 1998 Jeffrey A Law (law@cygnus.com) - * m68k.md: For all dbra pattern, change constraint from 'g' to 'd*g'. + * mn10200.md (various zero/sign extension patterns): zero and sign + extensions which use "sub" clobber cc0. - * Makefile.in: (underscore.c): Rename rule to stamp-under, and - touch stamp-under at the end. Add new rule for underscore.c that - depends on stamp-under. +Tue Jul 7 09:12:08 PDT 1998 Jeff Law (law@cygnus.com) - * sh.c (reg_unused_after): For a SEQUENCE, make sure all insns are - safe before returning 1. + * version.c: Bump for snapshot. - * sh.h (PROMOTE_FUNCTION_ARGS, PROMOTE_FUNCTION_RETURN): Define. +Tue Jul 7 10:07:20 1998 Jeffrey A Law (law@cygnus.com) - * sh.c (output_stack_adjust): Add new argument reg. Use it instead - of stack_pointer_rtx. - (sh_expand_prologue, sh_expand_epilogue): Pass new argument to - output_stack_adjust. + * print-rtl.c (print_rtx): Use REAL_VALUE_TYPE instead of "double". -Sat Aug 19 17:34:15 1995 Jim Wilson +Tue Jul 7 08:41:27 1998 Richard Henderson (rth@cygnus.com) - * sparc/gmon-sol2.c (_mcount): Define. - * sparc/sol2.h (STARTFILE_SPEC, ENDFILE_SPEC): Delete superfluous - -pg tests. - (LINK_SPEC): Add libp directories to -Y when -pg. + * print-rtl.c (print_rtx): Only print fp values when REAL_VALUE_TYPE + is a double. - * unroll.c (calculate_giv_inc): Handle increment computed by ASHIFT. +Tue Jul 7 00:31:58 PDT 1998 Jeff Law (law@cygnus.com) -Sat Aug 19 17:28:56 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * version.c: Bump for snapshot. - * m68k.md (subdi3): Should not be commutative. - (one_cmpldi2): Fixed typo with register operand. +Tue Jul 7 01:03:03 1998 Mumit Khan -Sat Aug 19 17:20:43 1995 Michael Meissner + Support for dllimport and dllexport attributes for i386-pe. - * rs6000.c (output_prolog): Fixup code to set stack pointer - if stack size > 32k. - * rs6000.md (sync_isync): Renamed from sync; added an isync insn - after the sync to properly deal with PowerPC's with split I/D caches. - * sysv4.h (INITIALIZE_TRAMPOLINE): Sync function now named sync_isync. + * tree.h (DECL_NON_ADDR_CONST_P): New accessor macro. + (struct tree_decl): Add non_addr_const_p field. + * tree.c (staticp): Use. -Sat Aug 19 17:07:09 1995 Doug Evans + * 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. - * h8300.h (STATIC_CHAIN_REGNUM): Use r3. - (REGISTER_NAMES): Print r7 as sp. - (ADDITIONAL_REGISTER_NAMES): Recognize r7. - (ASM_OUTPUT_ALIGN): Alignment is power of 2. - * h8300.md (fancy_btst,fancy_btst1): Branch target must be - operand 0 for length attribute to work. + * i386/mingw32.h (CPP_PREDEFINES): Map __declspec(x) to GCC + attributes. -Sat Aug 19 16:43:11 1995 Paul Franklin + * 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. - * assert.h: Declare __eprintf with attribute noreturn. +Tue Jul 7 00:50:17 1998 Manfred Hollstein (manfred@s-direktnet.de) -Sat Aug 19 16:40:12 1995 Jason Merrill + * libgcc2.c (L_exit): Provide a fake for atexit on systems which + define ON_EXIT but not HAVE_ATEXIT. - * stddef.h: Don't define wchar_t if __cplusplus is defined. +Tue Jul 7 00:44:35 1998 Franz Sirl -Tue Aug 15 18:01:01 1995 Paul Eggert + * m68k.md (zero_extend QI to HI): Correctly handle TARGET_5200. - * cccp.c (warning_with_line): Fix typo in declaration when - !HAVE_VPRINTF and defined (__STDC__). +Tue Jul 7 00:36:41 1998 Ulrich Drepper -Tue Aug 15 17:57:54 1995 Stephen L Moshier + * i386.c: Remove random whitespace at end of lines. - * real.c (ediv, emul): Set sign bit of IEEE -0.0 result. + * i386.c (ix86_epilogue): For pentium processors, try to deallocate + 4 or 8 byte stacks with pop instructions instead of an add instruction. -Tue Aug 15 17:49:47 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue Jul 7 00:30:08 1998 Klaus Kaempf - * expr.c (safe_from_p): Only safe if EXP is variable-size and X - is BLKmode. + * alpha.c: Include tree.h before expr.h. - * stmt.c (fixup_gotos): When some fixups done, reset to point - to next instead of zeroing TREE_VALUE, which may be shared. +Mon Jul 6 22:50:48 1998 Jason Merrill -Mon Aug 14 09:15:45 1995 Doug Evans + * 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. - * m68k/m68kemb.h (STARTFILE_SPEC): Define as empty. + * 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. -Mon Aug 14 09:08:57 1995 Pat Rankin +Mon Jul 6 22:47:55 1998 J"orn Rennecke - * vax.c (vms_check_external): Update `pending_head' properly - when the first list element is removed. + * reload.c (find_equiv_reg): When looking for stack pointer + const, + make sure we don't use a stack adjust. -Mon Aug 14 09:01:32 1995 Jeffrey A. Law + * reload.c (find_equiv_reg): If need_stable_sp is set, + check if stack pointer is changed directly. - * pa.md (call expanders): Emit a blockage insn after restoring - %r19 when generating PIC. + * reload1.c (delete_dead_insn): Don't delete feeding insn + if that insn has side effects. -Sun Aug 13 21:58:49 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * flow.c (find_auto_inc): Clear UNCHANGING bit of register that is + changed. - * toplev.c (main): Change text of unsupported -g option warning. + * reload1.c (reload_reg_free_before_p): RELOAD_FOR_OPADDR_ADDR + precedes RELOAD_FOR_OUTADDR_ADDRESS. -Sun Aug 13 21:47:57 1995 Andrew McCallum + * gcse.c (hash_scan_insn): New argument IN_LIBCALL_BLOCK. Changed + caller. - * objc/selector.c (sel_get_any_typed_uid): New function. - * objc/objc-api.h (sel_get_any_typed_uid): Declare new function. +Mon Jul 6 22:21:56 1998 Kamil Iskra -Sun Aug 13 21:43:17 1995 John Carr + * m68k.c (output_scc_di): Use cmpw #0 instead of tstl when + testing address registers on the 68000. - * c-typeck.c (c_expand_asm_operands): Check for read-only output - operand where the variable is read-only but the type is not. +Mon Jul 6 22:17:19 1998 Alasdair Baird -Sun Aug 13 21:16:12 1995 David Edelsohn + * i386.c (is_fp_test): Fix thinko. - * rs6000.c (direct_return): Epilogue required if CR saved. + * jump.c (jump_optimize) Check for CONST_INT before using INTVAL. -Sun Aug 13 19:09:25 1995 Jeff Law (law@snake.cs.utah.edu) +Mon Jul 6 22:14:31 1998 Richard Henderson (rth@cygnus.com) - * configure (hppa1.?-hp-hpux10): Recognize and treat just like hpux9. + * print-rtl.c (print_rtx): Display the real-value equivalent of + a const_double when easy. -Sun Aug 13 19:07:23 1995 Doug Evans + * 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. - * i960.md (movdi matchers): Fix src/dest order in unaligned - reg->reg case. + * regclass.c (allocate_reg_info): Initialize the entire reg_data + virtual array. -Sun Aug 13 18:49:01 1995 DJ Delorie +Mon Jul 6 22:09:32 1998 Ian Lance Taylor + Jeff Law - * i386/xm-dos.h (HAVE_STRERROR): New definition. - * msdos/configur.bat: Add missing carriage return. + * 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. -Sun Aug 13 18:40:55 1995 Andrew Cagney + * cpplib.c (cpp_options_init): Initialize cplusplus_comments to 1, + matching July 18, 1995 change to cccp.c. If -traditional then + disable cplusplus_comments. - * Makefile.in (USER_H): Add va-ppc.h. +Mon Jul 6 21:28:14 1998 Jeffrey A Law (law@cygnus.com) -Sun Aug 13 18:36:17 1995 M. Warner Losh + * combine.c (expand_compound_operation): Fix thinko in code to optimize + (zero_extend:DI (subreg:SI (foo:DI) 0)) to foo:DI. - * stmt.c (expand_asm_operands): Type '0'..'4' operands may - allow regs, so move them to the default case. + * Disable the following change from gcc2. Not appropriate for egcs: -Sun Aug 13 18:32:35 1995 Paul Eggert + Sun Jun 7 09:30:31 1998 Richard Kenner + * reload.c (find_reloads): Give preference to pseudo that was the + reloaded output of previous insn. - * cccp.c (warning_with_line): New function. - (trigraph_pcp): Use it, to avoid reporting line number. - (vwarning_with_line): Don't report line number if zero. +Mon Jul 6 21:07:14 1998 Kaveh R. Ghazi -Sun Aug 13 18:23:08 1995 Jason Merrill + * 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. - * toplev.c (vmessage): Support four arguments. + * 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. -Sun Aug 13 18:19:51 1995 Michael Meissner + * mips-tfile.c: Include machmode.h to get HOST_PTR_PRINTF. - * ginclude/stdarg.h: Add ppc svr4 calling sequence support. - * ginclude/varargs.h: Likewise. - * ginclude/va-ppc.h: New file. + * Makefile.in (mips-tfile.o): Depend on machmode.h. -Sun Aug 13 18:05:20 1995 Michael Gschwind +Mon Jul 6 10:42:05 1998 Mark Mitchell - * configure (pdp-*-*): Add support for t-pdp11. - * t-pdp11: New file. - * Makefile.in (LIBGCC2_CFLAGS): Add TARGET_LIBGCC2_CFLAGS. + * 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}. -Sun Aug 13 14:50:58 1995 Jim Wilson +Mon Jul 6 09:38:15 1998 Mark Mitchell - * final.c (final_start_function): Always call sdbout_begin_function - and xcoffout_begin_function, even if no line number info. + * cse.c (CSE_ADDRESS_COST): New macro, based on ADDRESS_COST, but + dealing with ADDRESSOF. + (find_best_addr): Use it. - * mips/abi64.h (SETUP_INCOMING_VARARGS): In if statement, only - subtract one for stdarg. Don't subtract PRETEND_SIZE from - argument pointer when calculating stack address. - * mips.h (INITIAL_ELIMINATION_OFFSET): For 64 bit ABI, subtract - current_function_pretend_args_size when converting from argument - pointer. - * va-mips.h (va_start): For stdarg, delete separate define for - 64 bit ABI. For varargs, don't subtract 64, and only add -8 when - all argument registers are used. +Mon Jul 6 09:27:08 1998 Richard Henderson - * gcc.c (main): When concat gcc_exec_prefix and - standard_startfile_prefix, put machine_suffix in the middle. + * alpha/vms.h (TRAMPOLINE_TEMPLATE): Revert last change. - * iris6.h (INIT_SECTION_ASM_OP): Don't define. - (LD_INIT_SWITCH, LD_FINI_SWITCH, HAS_INIT_SECTION): Don't undef. - (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Ifdef out. - * configure (mips-sgi-irix6, mips-sgi-irix5cross64): Define - use_collect2 to yes. +Mon Jul 6 09:25:06 1998 Dave Love - * combine.c (move_deaths): When have a multi-reg hard register, - if don't find a note, then recur for each individual hard register. + * libgcc2.c (__eprintf): Make args consistent with prototype in + assert.h. - * cse.c (set_nonvarying_address_components): Handle addresses - which are the sum of two constant pseudo regs. - (cse_rtx_addr_varies_p): Likewise. +Mon Jul 6 00:28:43 1998 Mark Mitchell - * Makefile.in (gfloat.h): Add a - before the rm command. + * cse.c (cse_insn): When SETting (MEM (ADDRESSOF (X))) to Y, + don't claim that the former is equivalent to the latter. - * loop.c (find_and_verify_loops): Set dest_loop only if - JUMP_LABEL (insn) is non-zero. +Sun Jul 5 23:58:19 1998 Jeffrey A Law (law@cygnus.com) -Mon Jul 31 14:31:53 1995 Ian Lance Taylor + * 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. - * fixincludes: Avoid clobbering VxWorks drv/netif/if_med.h file. + * combine.c (simplify_comparison): Do not commute a AND into + a paradoxical SUBREG if not WORD_REGISTER_OPERATIONS. -Sat Jul 29 16:21:42 1995 Jason Merrill + * 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 + + * 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 + + * 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 + + * config/m32r/m32r.h (MUST_PASS_IN_STACK): Override default + version. + +Thu Jul 2 14:34:48 1998 David Edelsohn + + * 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 - * collect2.c: (XCOFF_SCAN_LIBS): Define if OBJECT_FORMAT_COFF and - XCOFF_DEBUGGING_FORMAT. - (SCAN_LIBRARIES): Also define if XCOFF_SCAN_LIBS. + * varray.{c,h}: New files to provide virtual array support. -Sat Jul 29 16:19:42 1995 Stuart D. Gathman + * 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). - * collect2.c (scan_libraries): Implement for AIX. + * toplev.c (x{m,re}alloc): If size is 0, allocate 1 byte. + (xcalloc): Provide frontend for calloc. + * {tree,rtl}.h (xcalloc): Add declaration. -Sat Jul 29 09:59:33 1995 Michael Gschwind + * basic-block.h (REG_BASIC_BLOCK): Convert reg_n_info to be a + varray. - * configure: (pdp11-*-bsd) New target. - * 2bsd.h: New file. + * 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. - * pdp11.c (output_move_double): Handle CONST_INT parameters properly. - * pdp11.h (RTX_COSTS): Fill in missing default values. - * pdp11.md (truncdfsf2, extendsfdf2, floatsidf2, fix_truncdfsi2): - Allow register parameters, required by gcc to generate correct code. - * xm-pdp11.h: Include tm.h. + * 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. -Sat Jul 29 09:55:17 1995 Andreas Schwab + * flow.c (reg_n_info): Switch to use varrays. - * configure (m68k-*-linux*aout*, m68k-*-linux*): New targets. - * m68k/linux-aout.h, m68k/linux.h, m68k/t-linux, m68k/xm-linux.h: New. - * m68k.md [USE_GAS]: Output `jbsr' instead of `jsr' for normal - function calls and `bsr.l' instead of `bsr' for pic function calls. +Thu Jul 2 10:11:47 1998 Robert Lipe -Sat Jul 29 09:44:13 1995 Jim Wilson + * 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 - * sh.h (CAN_DEBUG_WITHOUT_FP): Comment out. +Thu Jul 2 08:20:00 1998 Catherine Moore - * reload.c (find_reloads_address_1, case PLUS): When handle SUBREG, - add SUBREG_WORD offset to SUBREG_REG register number. - (find_reloads_address_1, case SUBREG): If a pseudo register inside - a SUBREG is larger than the class, then reload the entire SUBREG. - * sh.h (SUBREG_OK_FOR_INDEX_P): New macro. - (INDEX_REGISTER_RTX_P): Use it. + * haifa-sched.c (alloc_EXPR_LIST): Change to use + unused_expr_list. -Sat Jul 29 09:33:19 1995 Doug Evans +Thu Jul 2 14:13:28 1998 Dave Love - * mips/netbsd.h (CPP_SPEC): Fix typo. + * Makefile.in (install-info): Don't use $realfile. Ignore + possible errors from the install-info program. - * configure (a29k-*-vxworks*): Define extra_parts for crt{begin,end}.o. - * t-a29k, t-a29kbase, t-vx29k ({,CROSS_}LIBGCC1): Define as empty. +Thu Jul 2 01:53:32 1998 Alasdair Baird -Sat Jul 29 09:15:17 1995 Jeffrey A. Law + * combine.c (simplify_comparison): Apply SUBREG_REG to SUBREGs. - * pa/lib2funcs.asm (gcc_plt_call): Rewrite to avoid the need - for being called by _sr4export. Inline expand $$dyncall to - avoid the need for long-call and PIC support. +Wed Jul 1 23:06:03 1998 Richard Henderson -Sat Jul 29 07:30:04 1995 Oliver Kellogg (Oliver.Kellogg@space.otn.dasa.de) + * i386.h (HARD_REGNO_MODE_OK): Kill spurrious test. + (MODES_TIEABLE_P): Tie SImode and HImode. - * ms1750.inc (ucim.m, ucr.m, uc.m): New. - * 1750a.md (cmpqi): Account for unsigned comparisons. - (rotrqi3, rotrhi3): Reworked. - * 1750a.c (notice_update_cc): INCM and DECM set condition codes. - (unsigned_comparison_operator, next_cc_user_is_unsigned): New fcns. - * 1750a.h (FUNCTION_EPILOGUE): Local variables freed from SP, not FP. - (ASM_OUTPUT_BYTE): Make distinct from ASM_OUTPUT_CHAR. - (ASM_OUTPUT_CONSTRUCTOR): Add FILE arg to assemble_name. +1998-07-01 Andreas Jaeger -Fri Jul 28 09:40:07 1995 Jeffrey A. Law + * invoke.texi (Optimize Options): Fix typo. - * pa.h (DO_GLOBAL_DTORS_BODY): Use an asm statement to keep optimizer - from deleting an assignment it believes dead. +Wed Jul 1 22:25:43 1998 Jim Wilson -Fri Jul 28 08:47:51 1995 Jim Wilson + * xcoffout.c (xcoffout_begin_function): Call xcoffout_block for + the zero'th block. - * unroll.c (unroll_loop): When preconditioning, output code to - execute loop once if initial value is greater than or equal to final - value. +Wed Jul 1 23:12:58 1998 Ken Raeburn - * configure (lang_specs_files, lang_options_files): Add $srcdir to - file names when adding them to these variables. + * h8300.c (print_operand): Delete %L support. + * h8300.md (branch_true, branch_false): Use %= with a prefix + instead of %L for local branch labels. - * c-typeck.c (pointer_int_sum): Don't distribute if intop is unsigned - and not the same size as ptrop. +Wed Jul 1 21:27:13 1998 J"orn Rennecke - * function.c (assign_stack_temp): When split a slot, set base_offset - and full_size in the newly created slot. - (combine_temp_slots): Update full_size when slots are combined. + * reload1.c (emit_reload_insns): Use proper register classes for + SECONDARY_INPUT_RELOAD_CLASS / SECONDARY_MEMORY_NEEDED code. - * sh.c (reg_unused_after): New function. - * sh.md (define_peephole): Add peepholes to use r0+rN addressing mode - for some address reloads. +Wed Jul 1 21:17:36 1998 J"orn Rennecke - * final.c (final_start_function): If SDB_DEBUG, call - sdbout_begin_function. If XCOFF_DEBUG, call xcoffout_begin_function - instead of xcoffout_output_first_source_line. - (final_scan_insn): Don't call sdbout_begin_function or - xcoffout_begin_function. - * xcoffout.c (xcoffout_output_first_source_line): Delete. - (xcoffout_begin_function): Call dbxout_parms and - ASM_OUTPUT_SOURCE_LINE. + * 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. - * va-mips.h: Change every occurance of #if __mips>=3 to - #ifdef __mips64. - * mips/abi64.h (CPP_SPEC): Output -D__mips64 when -mips3, or -mips4, - or -mgp64. Output -U__mips64 when -mgp32. - * mips/dec-bsd.h, mips/elf64.h, mips/iris3.h: Likewise. - * mips/iris5.h, mips/mips.h, mips/netbsd.h, mips/osfrose.h: Likewise. +Wed Jul 1 17:23:23 1998 J"orn Rennecke - * i960.c (i960_function_epilogue): Don't clear g14 for functions with - an argument block. - (i960_output_reg_insn): Likewise. - (i960_output_call_insn): Clear g14 for functions wtih an argument - block. + * regmove.c (fixup_match_2): Check that P has RTX_CLASS 'i' before + using its PATTERN. -Fri Jul 28 08:43:52 1995 Doug Evans +Wed Jul 1 05:04:41 1998 Richard Henderson - * i960.c (i960_arg_size_and_align): Correct alignment of XFmode - values in library calls. - * i960.md (movdi matchers): Support odd numbered regs. + * 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. -Fri Jul 28 08:37:25 1995 Michael Gschwind +Wed Jul 1 04:22:23 1998 Richard Henderson - * pdp11.md (divhi3, modhi3, divmodhi4): Rewrite. - -Wed Jul 26 10:15:52 1995 Hallvard B Furuseth (h.b.furuseth@usit.uio.no) + * sparc.c (function_arg_record_value): Take a MODE arg with which to + create the PARALLEL. Update all callers. - * collect2.c (end_file): Fix typo in error message text. +Wed Jul 1 04:10:35 1998 Richard Henderson -Wed Jul 26 09:22:22 1995 Jeff Law (law@snake.cs.utah.edu) + * expr.c (expand_assignment, store_constructor, expand_expr): Use + convert_memory_address instead of convert_to_mode when possible. - * xm-pa.h (USE_C_ALLOCA): Always define. - * xm-pahpux.h (USE_C_ALLOCA): Likewise. +Wed Jul 1 03:48:00 1998 Richard Henderson - * x-pa (CC): Remove useless definition. - * xm-pa.h (HAVE_STRERROR): Define. - (__BSD_NET2__): Define. + * 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. -Wed Jul 26 09:10:25 1995 Jason Merrill + * alpha/linux.h: Revert gcc2 merge lossage. - * expr.c (preexpand_calls): Don't look past a CLEANUP_POINT_EXPR. +Wed Jul 1 10:56:55 1998 Andreas Schwab -Wed Jul 26 08:43:42 1995 Jim Wilson + * c-decl.c (grokdeclarator): Don't warn about implicit int in + `typedef foo = bar'. - * cse.c (cse_insn): When do special handling for (set REG0 REG1), - must delete REG_EQUAL note from insn if it mentions REG0. +Wed Jul 1 02:12:33 1998 Robert Lipe - * loop.c (find_and_verify_loops): When moving blocks of code, verify - that the just destination is not in an inner nested loop. - (mark_loop_jump): Don't mark label as loop exit if it jumps to - an inner nested loop. + * i386.c (asm_output_function_prefix): Make 686 function + prologues not issue .types for non-global lables. -Wed Jul 26 08:40:31 1995 Paul Eggert +Tue Jun 30 23:46:53 1998 Dmitrij Tejblum - * cccp.c (do_include, read_name_map): Omit leading "./" and - trailing "/" when it makes sense. - (skip_redundant_dir_prefix): New function. + * i386/freebsd.h (WCHAR_TYPE): Chagne to an "int". + (WCHAR_TYPE_SIZE): Update appropriately. -Wed Jul 26 08:36:41 1995 Michael Meissner +Tue Jun 30 23:16:39 1998 Jeffrey A Law (law@cygnus.com) - * stmt.c (emit_nop): Do not emit a nop if there is a single - insn before a label or at the start of a function. + * flow.c (recompute_reg_usage): Does not return a value. + * rtl.h (recompute_reg_usage): Update prototype. -Wed Jul 26 08:21:21 1995 Doug Evans + * jump.c (jump_optimize): Show that the jump chain is not + valid when not optimizing. - * Makefile.in (gfloat.h): Delete previous copy before updating. +Tue Jun 30 16:01:01 1998 Richard Henderson -Wed Jul 26 08:18:29 1995 Roland McGrath + * 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. - * Makefile.in (STAGESTUFF): Add stamp-crtS. - (crtbeginS.o, crtendS.o, stamp-crtS): New rules; just like - crtbegin.o et al, but compiled using -fPIC. - * configure (*-*-gnu*): Add crtbeginS.o and crtendS.o to $extra_parts. + * 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. -Wed Jul 26 08:11:52 1995 Michael Gschwind +1998-06-30 Benjamin Kosnik - * pdp11.md: Fixed typos ('bhos' -> 'bhis'). + * dbxout.c (dbxout_type_methods): Remove warn_template_debugging. -Wed Jul 26 08:05:41 1995 Jim Wilson +Tue Jun 30 14:03:34 1998 Kaveh R. Ghazi - * hp320.h, m68k.h, m68kv4.h (LEGITIMATE_PIC_OPERAND_P): Reject - CONST_DOUBLE with MEM with invalid pic address. - * reload1.c (real.h): Include it. - * Makefile.in (reload1.o): Depends on real.h. + * 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. -Wed Jul 26 07:58:22 1995 Ian Lance Taylor + * configure.in (GCC_NEED_DECLARATIONS): Add checks for getrlimit + and setrlimit, search for them in sys/resource.h. - * gcc.c (MULTILIB_DIRS): Provide default if not defined. - (multilib_defaults): New static variable. - (default_arg): New static function. - (set_multilib_dir): Ignore default arguments. - (print_multilib_info): Ignore entries which use default arguments. + * acconfig.h: Add stubs for NEED_DECLARATION_GETRLIMIT and + NEED_DECLARATION_SETRLIMIT. -Tue Jul 25 10:06:09 1995 Michael Meissner + * system.h: Prototype getrlimit/setrlimit if necessary. - * rs6000.md (allocate_stack): Don't copy the LR register to - the new stack end. - * rs6000.c (rs6000_stack_info): Correctly store the LR in - the caller's frame, not the current frame, for V.4 calls. - * rs6000/eabi.asm (_save*, _rest*): Provide all mandated V.4 save - and restore functions, except for the save*_g functions which - return the GOT address. +Tue Jun 30 10:54:48 1998 Mark Mitchell -Fri Jul 21 14:24:25 1995 Michael Meissner + * rtl.texi: Don't say that RTX_INTEGRATED_P is not depended + upon. - * rs6000/eabi.h (__eabi): Load up r13 to be the small data - pointer, unless -mrelocatable. +Tue Jun 30 13:11:42 1998 Franz Sirl - * rs6000/aix3newas.h (LINK_SPEC): Import machine independent - functions if -mcpu=common. - * rs6000/milli.exp: Import file referenced in aix3newas.h. + * rs6000/sysv4.h (asm output): add tabs for asm directives. - * rs6000/eabi.asm (__eabi): Support for fixing up user initialized - pointers when -mrelocatable is used. - * rs6000/eabi.h (ASM_OUTPUT_INT): Record any pointers initialized - by the user if -mrelocatable, to be fixed up by __eabi. - (CONST_SECTION_ASM_OP): If -mrelocatable, put read-only stuff in .data, - not .rodata, to allow user initialized pointers to be updated by __eabi. +Tue Jun 30 13:11:42 1998 David Edelsohn - * rs6000.h (TARGET_SWITCHES): Add -mdebug-{stack,arg}. - (TARGET_{ELF,NO_TOC,TOC}): Add defaults for non system V. - (rs6000_stack): New structure to describe stack layout. - (RS6000_{REG_SAVE,SAVE_AREA,VARARGS_*}): New macros used to - support both AIX and V.4 calling sequences. - (FP_ARG_*, GP_ARG_*): Ditto. - (FP_SAVE_INLINE): Ditto. - (STARTING_FRAME_OFFSET): Modify to support both AIX and V.4 - calling sequences. - (FIRST_PARM_OFFSET): Ditto. - (REG_PARM_STACK_SPACE): Ditto. - (STACK_POINTER_OFFSET): Ditto. - (FUNCTION_ARG_REGNO_P): Ditto. - ({,INIT_}CUMULATIVE_ARGS): Ditto. - (LEGITIMATE_LO_SUM_ADDRESS_P): Ditto. - (FUNCTION_ARG{,_ADVANCE,PARTIAL_NREGS,PASS_BY_REFERENCE}): Ditto. - (SETUP_INCOMING_VARARGS): Ditto. - (EXPAND_BUILTIN_SAVEREGS): Ditto. - (CAN_ELIMINATE): Ditto. - (INITIAL_ELIMINATION_OFFSET): Ditto. - (LEGITIMATE_CONSTANT_POOL_{BASE,ADDRESS}_P): Ditto. - (GO_IF_{LEGITIMATE_ADDRESS,MODE_DEPENDENT_ADDRESS}): Ditto. - (LEGITIMIZE_ADDRESS): Ditto. - (CONST_COSTS): Ditto. - (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): Ditto. - (ASM_OUTPUT_REG_{PUSH,POP}): Use reg_names to print registers. - (function declarations): Add new rs6000.c function declarations, - and delete decls of deleted functions. - (SHIFT_COUNT_TRUNCATED): Parenthesize the expression. - - * rs6000.c (init_cumulative_args): New function to support AIX - and V.4 calling sequences. - (function_arg{,_advance,partial_nregs,pass_by_reference}): Ditto. - (setup_incoming_varargs): Ditto. - (expand_builtin_saveregs): Ditto. - (rs6000_stack_info): Ditto. - (debug_stack_info): Ditto. - (direct_return): Changes to support AIX and V.4 calling sequences. - (first_reg_to_save): Ditto. - (svr4_traceback): Ditto. - (output_{prolog,epilog}): Ditto. - (print_operand): Use reg_names to print registers. Add support - for V.4 HIGH/LO_SUM address modes. - (must_save_cr): Function deleted, in rewrite of AIX/V.4 calling - sequence support. - (rs6000_sa_size): Ditto. - (rs6000_pushes_stack): Ditto. - (output_toc): Add abort if no toc. - - * rs6000.md (call insns): Add a new argument to flag a V.4 - function needs to set bit 6 of the CR. - (elf_{low,high}): New V.4 functions to create addresses via HIGH - and LO_SUM patterns. - (movsi): Use elf_{low,high} if appropriate. - (mov{si,di}_update): Name these patterns for allocate_stack. - (allocate_stack): Support for V.4 stack layout. - (sync): New pattern for V.4 trampolines to issue the sync - instruction. + * Makefile.in (FLAGS_TO_PASS): Set AR_FLAGS to AR_FOR_TARGET_FLAGS. + +Tue Jun 30 08:59:15 1998 Kaveh R. Ghazi + + * 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. + + * system.h: Immediately after including stdio.h, check for and if + necessary provide a default definition of NULL. + +Tue Jun 30 08:22:05 1998 Michael Meissner + + * reload1.c (reload_cse_simplify_operands): Call + fatal_insn_not_found, not abort. + +Tue Jun 30 02:34:02 1998 Jeffrey A Law (law@cygnus.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. + +Tue Jun 30 00:56:19 1998 Bruno Haible + + * invoke.texi: Document new implicit structure initialization + warning. + +Mon Jun 29 22:12:06 1998 Jeffrey A Law (law@cygnus.com) + + * Merge from gcc2 June 9, 1998 snapshot. See ChangeLog.13 for + details. + + * pa.c, pa.h, pa.md: Convert to gen_rtx_FOO. + +Mon Jun 29 20:12:41 1998 Kaveh R. Ghazi + + * Makefile.in (fix-header): Don't needlessly depend on cpperror.o. + + * alias.c (CHECK_ALIAS_SETS_FOR_CONSISTENCY): Cast expansion to + void since it is evaluated in a comma list. + + * 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. + + * sol2.h (ASM_GENERATE_INTERNAL_LABEL): Likewise. + + * 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'. + + * cpplib.c (cpp_message_from_errno): Remove unneeded argument to + cpp_message. + + * dbxout.c: Fix the comments after an #endif to reflect the actual + condition tested in the preceding #if. + + * except.c (find_all_handler_type_matches): Switch to old-style + function definition. + + * expr.c (expand_builtin): Remove unused variable `type' twice. + + * gbl-ctors.h (DO_GLOBAL_CTORS_BODY): Cast -1 before comparing it + to an unsigned long. + + * haifa-sched.c (print_insn_chain): Remove unused function. + + * objc/objc-act.c (build_msg_pool_reference): Hide prototype and + definition. + + * toplev.c: When testing whether to include dbxout.h, also include + it when XCOFF_DEBUGGING_INFO is defined. + + * unroll.c (unroll_loop): Add parentheses around assignment used + as truth value. + +Mon Jun 29 12:18:00 1998 Catherine Moore + + * config/lb1spc.asm (.div, .udiv): Replace routines. + +Mon Jun 29 09:44:24 1998 Mark Mitchell + + * rtl.h: Update comment about special gen_rtx variants. + * emit-rtl.c (gen_rtx): Handle MEMs using gen_rtx_MEM. + +Sun Jun 28 20:58:51 1998 Jeffrey A Law (law@cygnus.com) + + * 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. + +Sun Jun 28 08:57:09 1998 Kaveh R. Ghazi + + * configure.in (GCC_NEED_DECLARATIONS): Add strerror, getcwd and + getwd. + + * acconfig.m4: Add stubs for NEED_DECLARATION_STRERROR, + NEED_DECLARATION_GETCWD and NEED_DECLARATION_GETWD. + + * cccp.c: Remove strerror()/sys_nerr/sys_errlist decls. + (my_strerror): Add prototype and make it static. + + * collect2.c: Likewise. + + * cpplib.c: Likewise. + + * gcc.c: Likewise, but keep `my_strerror' extern. + + * protoize.c: Likewise. + + * pexecute.c (my_strerror): Add argument to prototype. + + * system.h: Add prototypes for getcwd, getwd and strerror. Add + extern decls for sys_nerr and sys_errlist. Make abort decl + explicitly extern. + + * getpwd.c: Remove decls for getwd and getcwd. + +Sun Jun 28 02:11:16 PDT 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sat Jun 27 23:32:25 1998 Richard Henderson + + * 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 + + * objc/archive.c: Remove 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 + + * 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 + + * 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 + + * alpha.md (negsf, negdf): Revert Jan 22 change. + +Sat Jun 27 07:35:21 1998 Kaveh R. Ghazi + + * 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. + +1998-06-26 Michael Meissner + + * rs6000.md (ne 0, non power case): Add missing & constraint. + Name pattern ne0. + (negative abs insns): Add pattern names. + +Fri Jun 26 17:36:42 1998 Dave Love + + * Makefile.in (install-info): Run install-info program in separate + loop. + +Fri Jun 26 16:03:15 1998 Michael Meissner + + * 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. - * rs6000/sysv4.h (TARGET_SWTICHES): Add -mcall-{aix,sysv}, and - -mprototype. Remove separate flag bit for -mno-toc. - (SUBTARGET_OVERRIDE_OPTIONS): Don't test for -mno-toc. - (FP_ARG_*): Adjust for V.4 calling sequences. - (RS6000_*): Ditto. - (FP_SAVE_INLINE): Ditto. - (toc_section): Eliminate use of AIX style full TOC. - (TRAMPOLINE_{TEMPLATE,SIZE}): Redefine for V.4 support. - (INITIALIZE_TRAMPOLINE): Ditto. +Fri Jun 26 11:54:11 1998 David S. Miller + + * 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 + + * 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'. - * rs6000/eabi.h (CPP_SPEC): Define _CALL_SYSV or _CALL_AIX, - depending on whether -mcall-sysv or -mcall-aix was used. - * rs6000/eabile.h (CPP_SPEC): Ditto. - * rs6000/sysv4le.h (CPP_SPEC): Ditto. - - * rs6000/t-eabigas (MULTILIB_{OPTIONS,DIRNAMES}): Delete no-toc - libraries, explicit big endian libraries. - * rs6000/t-ppcgas (MULTILIB_{OPTIONS,DIRNAMES}): Ditto. + * 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 + + * 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. + +Thu Jun 25 12:47:41 1998 Mark Mitchell + + * fold-const.c (make_range): Don't go looking at TREE_OPERANDs of + nodes that are not expressions. + +Thu Jun 25 15:08:16 1998 Mark Mitchell + + * invoke.texi (-fstrict-aliasing): Document. + * rtl.texi (MEM_ALIAS_SET): Document. + + * 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. + + * 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. + + * 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. + + * 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. - * rs6000/t-eabiaix: New file for eabi, using -mcall-aix as the - default. - * rs6000/eabiaix.h: Ditto. +Thu Jun 25 16:59:18 EDT 1998 Andrew MacLeod + + * 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 + + * 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/t-eabilegas: New file for eabi on little endian systems. - * rs6000/t-ppclegas: New file for V.4 on little endian systems. + * rs6000.h (RTX_COSTS): Add parentheses around & operation. + (toc_section, private_data_section, trap_comparison_operator): Add + prototypes. - * rs6000/t-rs6000 (MULTILIB_{OPTIONS,DIRNAMES}): Build libgcc.a - for -mcpu=common. + * dbxout.h (dbxout_parms, dbxout_reg_parms, dbxout_syms): Add + prototypes. - * configure (powerpc-*-eabiaix): New configuration for defaulting - to old-style AIX calling sequence. - (powerpcle*): Use new t-{eabi,ppc}legas files, to avoid building - explicit little endian multilib libraries. + * xcoffout.c: Include toplev.h, outout.h and dbxout.h. -Fri Jul 21 13:23:06 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.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. - * toplev.c (main): Don't define sbrk #ifdef __alpha__. +Thu Jun 25 09:54:55 1998 Nick Clifton -Tue Jul 18 19:23:44 1995 Paul Eggert + * config/arm/arm.h (REG_ALLOC_ORDER): Add ARG_POINTER_REGNUM, + noticed by grahams@rcp.co.uk. - * cccp.c (do_include): Prefix -H output lines with spaces, not dots. - (output_dots): Remove. +Thu Jun 25 11:12:29 1998 Dave Brolley - * cccp.c (main): cplusplus_comments now defaults to 1. - But clear it if -traditional or the new option -lang-c89 is given. - * gcc.c (default_compilers, cpp): Specify -lang-c89 if -ansi is given. - This turns off C++ comment recognition. + * gcc.c (default_compilers): Use new | syntax to eliminate + string concatenation. -Tue Jul 18 19:16:38 1995 Jim Wilson +Thu Jun 25 01:00:48 1998 Richard Henderson - * va-sparc.h (va_arg): Add support for 128 bit long double type. + * 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. -Tue Jul 18 19:11:18 1995 Jorn Rennecke (amylaar@meolyon.hanse.de) +Thu Jun 25 01:18:47 1998 John Wehle (john@feith.com) - * c-common.c (decl_attributes, case A_ALIGNED): Handle is_type - case properly. + * i386/freebsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Define. -Tue Jul 18 19:03:02 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +1998-06-25 Herman A.J. ten Brugge - * fold-const.c (fold, case CONVERT_EXPR): Don't merge conversions - if outer is to handle a type with differing precision. + * expr.c (expand_assignment): Rework address calculation for structure + field members to expose more invariant computations to the loop + optimizer. + (expand_expr): Likewise. -Mon Jul 17 14:37:35 1995 Pat Rankin (rankin@eql.caltech.edu) +Wed Jun 24 22:44:22 1998 Jeffrey A Law (law@cygnus.com) - * vax/vms.h (HAVE_ATEXIT): Define. - (DO_GLOBAL_CTORS_BODY): Don't call atexit; let __do_global_ctors do it. - * vax/xm-vms.h (HAVE_VPRINTF): Define. + * local-alloc.c (block_alloc): Do not try to avoid false dependencies + when SMALL_REGISTER_CLASSES is nonzero. -Mon Jul 17 06:41:19 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Wed Jun 24 17:55:15 1998 Klaus Kaempf - * c-typeck.c ({unsigned,signed}_type): Handle intXX_type_node types. + * alpha.md (call_vms, call_value_vms): Strip leading * from symbol. - * xm-alpha.h (sbrk): Add declaration. +Wed Jun 24 16:27:23 1998 John Carr - * convert.c (convert_to_integer): If TYPE is a enumeral type or - if its precision is not the same as the size of its mode, - convert in two steps. + * expr.c (get_memory_rtx): New function. + (expand_builtin): Call get_memory_rtx for MEM arguments to builtin + string functions. - * m68k.md (tstdi, cmpdi): Use match_scratch, not match_operand. + * expmed.c (init_expmed): Initialize all elements of *_cost arrays. -Fri Jul 14 19:23:42 1995 Andreas Schwab + * 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. - * c-decl.c (field_decl_cmp): Rewritten to make sure that a null - name always sorts low against other names. - * c-typeck.c (lookup_field): Change name comparison to match what - field_decl_cmp does. +Wed Jun 24 15:13:01 1998 Dave Brolley -Fri Jul 14 18:46:24 1995 Michael Meissner + * README.gnat: Add patch for new lang_decode_options interface. - * rs6000.md (movsi): Convert a CONST_DOUBLE into a CONST_INT of - the low part. +Wed Jun 24 09:14:04 EDT 1998 Andrew MacLeod -Fri Jul 14 18:30:52 1995 Doug Evans + * except.c (start_catch_handler): Do nothing if EH is not on. - * toplev.c (main): Reword dwarf/c++/-g warning. +1998-06-24 Manfred Hollstein -Fri Jul 14 18:19:34 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * configure.in (gxx_include_dir): Initialize default value depending on + new flag --enable-version-specific-runtime-libs; remove superfluous + default initialization afterwards. + * configure: Regenerate. - * expr.h (NO_DEFER_POP): Remove last change. - * expr.c (stor_expr): Force stack adjust before NO_DEFER_POP. - (expand_expr, case COND_EXPR): Likewise. - * stmt.c (expand_start_stmt_expr): Likewise. +Wed Jun 24 01:32:12 1998 David S. Miller -Fri Jul 14 07:58:35 1995 Jim Wilson + * toplev.c (rest_of_compilation): Revert May 15 change. - * function.c (struct temp_slot): New fields base_offset, full_size. - (assign_stack_temp): For !FRAME_GROWS_DOWNWARD, set p->size to size. - Set new fields base_offset and full_size. - (combine_temp_slots): Use new fields base_offset and full_size instead - of slot and size. +Tue Jun 23 21:27:27 1998 Ken Raeburn - * loop.c (loop_number_exit_count): New global variable. - (loop_optimize): Allocate space for it. - (find_and_verify_loops, mark_loop_jump): Set it. - (strength_reduce, check_dbra_loop): Use loop_number_exit_count - instead of loop_number_exit_labels. - * loop.h (loop_number_exit_count): Declare it. - * unroll.c (find_splittable_{regs,givs}, final_[bg]iv_value): Use - loop_number_exit_count instead of loop_number_exit_labels. - (reg_dead_after_loop): Check loop_number_exit_count, and fail - if the count doesn't match loop_number_exit_labels. + * reload.c (find_reloads): Fix check for failure to match any + alternative, to account for Mar 26 change in initial "best" cost. - * cse.c (cse_insn): Ifdef out code that pre-truncates src_folded. +Tue Jun 23 16:44:21 1998 Dave Brolley - * sparc.md (sethi_di_sp64): Return null string at end. + * 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. - * function.h (struct function): Add stdarg field. - * function.c (current_function_stdarg): New global variable. - (push_function_context_to): Save it. - (pop_function_context_from): Restore it. - (assign_parms): Set it. - (init_function_start): Clear it. - * output.h (current_function_stdarg): Declare it. - * i960.md: Modify all patterns which handle stores to memory to also - check current_function_varargs and current_function_stdarg. +Tue Jun 23 13:38:18 EDT 1998 Andrew MacLeod - * reorg.c (fill_simple_delay_slots): When trying to take instruction - from after the branch, don't continue past target label. Local - variables passed_label and target_uses are no longer necessary. + * 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. -Thu Jul 13 19:30:04 1995 Jeff Law (law@snake.cs.utah.edu) +Tue Jun 23 09:30:58 1998 Dave Love - * pa.c (output_bb): Fix error in long backwards branch with - nullified delay slot. + * cpp.texi, gcc.texi: Add @dircategory, @direntry meant to + accompany previous Makefile.in (install-info) change. -Thu Jul 13 19:26:13 1995 Jim Wilson +Tue Jun 23 10:06:07 EDT 1998 Andrew MacLeod - * expmed.c (SHIFT_COUNT_TRUNCATED): Use #ifdef not #if. + * 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. -Mon Jul 10 20:16:44 1995 Paul Eggert +Tue Jun 23 06:45:00 1998 Catherine Moore - * cccp.c (rescan): Don't address outside of array when - preprocessing C++ comments. + * varasm.c (assemble_variable): Remove reference to warn_bss_align. -Mon Jul 10 20:05:46 1995 Michael Meissner +Mon Jun 22 23:57:31 1998 David S. Miller - * rs6000.c (expand_block_move): Remove #if 0 conditionals - against using larger block moves. + * 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 - * t-rs6000 (EXTRA_PARTS): Copy milli.exp to release dir. - (milli.exp): Copy to build dir from machine dependend dir. + * gcc.c (handle_braces): Recognize | between options as an or. -Mon Jul 10 20:03:29 1995 Richard Earnshaw (rearnsha@armltd.co.uk) +Mon Jun 22 23:13:47 1998 John Wehle (john@feith.com) - * arm.md (matcher for (shiftable_op (cond-exp) (reg))): If - shiftable_op is minus, then subtract from zero when cond fails. + * 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. -Mon Jul 10 19:58:26 1995 John F. Carr + * i386.md (exception_receiver): Define. - * sparc.h (SELECT_SECTION): Use TREE_CODE_CLASS instead of directly - referencing tree_code_type. - -Mon Jul 10 19:54:31 1995 Jim Wilson +Mon Jun 22 12:01:48 1998 Jim Wilson + + * Makefile.in (PROTOIZE_INSTALL_NAME, UNPROTOIZE_INSTALL_NAME, + PROTOIZE_CROSS_NAME, UNPROTOIZE_CROSS_NAME): New variables. + (install-common): Use them. + + * 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. + +Mon Jun 22 19:01:14 1998 Dave Love + + * Makefile.in (install-info): Fix typpo in previous change. + +Mon Jun 22 11:10:00 1998 Catherine Moore + + * varasm.c (assemble_variable): Emit alignment warning. - * protoize.c (reverse_def_dec_list): Delete const qualifiers from - local variables, and delete casts which were casting away const. +Mon Jun 22 08:18:46 1998 Kaveh R. Ghazi -Mon Jul 10 19:14:39 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * Makefile.in (varasm.o): Depend on sdbout.h. + (sdbout.o): Depend on toplev.h. - * c-lang.c (finish_file): Add missing parm to start_function call. + * collect2.c (scan_prog_file): Cast fprintf argument to `long' and + use %ld specifier. - * jump.c (jump_optimize): Pass outer_code arg to rtx_cost. + * final.c (shorten_branches): Cast first arg of `bzero' to char *. - * varasm.c (assemble_name, bc_assemble_integer): Call - bc_emit_labelref with proper args. + * genextract.c (main): When creating insn-extract.c, mark variable + `i' with ATTRIBUTE_UNUSED. - * function.c (setjmp_args_warning): Remove bogus arg. + * genpeep.c (main): When creating insn-peep.c, mark variables + `insn', `x' and `pat' with ATTRIBUTE_UNUSED. -Mon Jul 10 18:20:54 1995 Fergus Henderson (fjh@cs.mu.oz.au) + * objc/init.c (__objc_tree_print): Wrap function definition in + macro `DEBUG'. - * gcc.c (p{fatal,error}_with_name, perror_exec): Quote filename. + * objc/objc-act.c (encode_array): Cast sprintf argument to `long' + and use %ld specifier. + (adorn_decl): Likewise, twice. -Mon Jul 10 18:12:51 1995 Gran Uddeborg (uddeborg@carmen.se) + * reload1.c (reload_cse_regs): Cast first arg of `bzero' to char *. - * i386/iscdbx.h (STARTFILE_SPEC): Handle -Xp. + * 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. -Wed Jul 5 02:42:17 1995 Per Bothner (bothner@spiff.gnu.ai.mit.edu) + * sdbout.h (sdbout_mark_begin_function): Add prototype. - * cpphash.h (enum node_type): Remove unneeded and non-standard - forward declaration. + * stmt.c (check_for_full_enumeration_handling): Cast argument of + `warning' to long and use %ld specifier. -Sat Jul 1 20:15:39 1995 Jim Wilson + * toplev.c (main): Likewise for `fprintf'. - * mips/t-mips, mips/t-mips-gas (MULTILIB_*, LIBGCC, INSTALL_LIBGCC): - Delete. + * toplev.h (output_file_directive): Add prototype. - * sparc/sol2.h (LINK_SPEC): Revert March 16 change. Do not add -R - for each -L. + * unroll.c (unroll_loop): Use HOST_WIDE_INT_PRINT_DEC specifier in + call to `fprintf'. + (precondition_loop_p): Likewise. + + * varasm.c Include sdbout.h. + (assemble_static_space): Move sometimes-unused variable `rounded' + into the scope in which it is used. - * collect2.c (libcompare): Verify that file name extensions are valid. - Put files with invalid extensions last in the sort. + * mips.c (gpr_mode): Don't say `static' twice. - * integrate.c (integrate_decl_tree): Set DECL_ABTRACT_ORIGIN before - pushdecl call for local variables. + * cpplib.c (cpp_handle_option): Don't pass unneeded NULL to cpp_fatal. -Sat Jul 1 08:13:38 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + * objc/objc-act.c (init_selector): Hide prototype and definition. - * cpplib.c (output_line_command): If not emitting #line directives - delay returning until after adjust_position has been called. + * optabs.c (gen_cond_trap): Remove unused variable `icode'. + + * regmove.c (copy_src_to_dest): Likewise for `i'. + + * 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 - * arm.md (mov{si,sf,df}cc): Call gen_compare_reg to generate - the condition code register. + * Makefile.in (install-info): Use install-info program if + available, per GNU standard. -Sat Jul 1 06:55:09 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Sun Jun 21 18:56:44 1998 Jeffrey A Law (law@cygnus.com) - * fold-const.c (decode_field_reference): New parm PAND_MASK. - (unextend): New parm MASK. - (fold_truthop): Pass new parms to decode_field_reference and unextend. + * invoke.texi: Document -mrelax for the mn10300 and mn10200. - * va-alpha.h (__va_tsize): Use __extension__ to avoid warning - on use of `long long'. + * basic-block.h (init_regset_vector): Delete declaration. + * flow.c (init_regset_vector): Make it static and add a prototype. - * expr.h (NO_DEFER_POP): Do any pending stack adjusts. + * bitmap.h (debug_bitmap): Declare. - * recog.c (register_operand): Disallow subreg of reg not allowed to - change size. + * haifa-sched.c (debug_ready_list): Make static. -Thu Jun 29 05:51:57 1995 Jeff Law (law@snake.cs.utah.edu) + * toplev.h (fancy_abort): Declare. - * pa.md (reload addsi3): New pattern to avoid reload lossage - with register eliminations. +Sun Jun 21 18:30:13 1998 H.J. Lu (hjl@gnu.org) - * pa.c (output_cbranch): When checking for a jump to the given - insn's delay slot, handle the case where JUMP_LABEL for the - given insn does not point to the first label in a series of - labels. - (output_bb, output_dbra, output_movb): Likewise. + * basic-block.h (init_regset_vector): New declaration. -Wed Jun 28 18:04:56 1995 Jeff Law (law@snake.cs.utah.edu) + * Makefile.in (sdbout.o): Add insn-codes.h to dependency. - * pa.h (PIC_OFFEST_TABLE_REGNUM_SAVED): Define to %r4. - (CONDITIONAL_REGISTER_USAGE): Make it fixed when compiling - PIC code. - (INIT_EXPANDERS): Delete. - * pa.c (hppa_save_pic_table_rtx): Delete variable. - (hppa_expand_prologue): For PIC generation, copy the PIC - register into a fixed callee register at the end of the - prologue of non-leaf functions. - * pa.md (call expanders): Reload the PIC register from the - fixed callee saved register. Don't try to save the PIC - register before the call. + * global.c: Include machmode.h amd move hard-reg-set.h before + rtl.h. -Wed Jun 28 18:01:14 1995 Stan Cox (coxs@dg-rtp.dg.com) + * 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. - * m88k/dguxbcs.h (ASM_SPEC): Removed -h flag. - * m88k/dgux.h (ASM_SPEC): Likewise. + * integrate.c (pushdecl, poplevel): Remove declaration. -Wed Jun 28 17:01:58 1995 David Edelsohn + * rtl.h (expand_expr): Remove declaration. - * rs6000.c (processor_target_table): Remove CPU name synonyms. - * rs6000.h (CPP_SPEC): Likewise. - * rs6000/sysv4.h (CPP_SPEC): Likewise. - (ASM_SPEC): Likewise. - * rs6000/sysv4le.h (CPP_SPEC): Likewise. - * rs6000/eabile.h (CPP_SPEC): Likewise. - * rs6000/powerpc.h (CPP_SPEC): Likewise. - (ASM_SPEC): Set assembler target according to compiler target. - * rs6000/aix3newas.h (CPP_SPEC): Likewise. - (ASM_SPEC): Likewise. - * rs6000/aix41.h (CPP_SPEC): Likewise. - (ASM_SPEC): Likewise. + * loop.c (oballoc): Remove declaration. + (replace_call_address): Add prototype. -Wed Jun 28 16:25:53 1995 Gran Uddeborg (uddeborg@carmen.se) +Sun Jun 21 01:08:17 PDT 1998 Jeff Law (law@cygnus.com) - * i386/x-isc3 (INSTALL_HEADERS_DIR): Delete; done by configure. + * version.c: Bump for snapshot. -Wed Jun 28 16:10:47 1995 Philippe De Muyter (phdm@info.ucl.ac.be) +Sun Jun 21 01:16:38 1998 John Wehle (john@feith.com) - * xm-rs6000.h (alloca): Extern decl added for non-GNU compiler. + * 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. -Wed Jun 28 11:31:30 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * i386.md (nonlocal_goto_receiver): Delete. - * cpplib.c (progname): Remove definition from here. +Sun Jun 21 00:42:20 1998 H.J. Lu (hjl@gnu.org) - * final.c (final_scan_insn): Fix error in last change. + * Makefile.in (crtbeginS.o, crtendS.o): Add -fno-exceptions and + -DCRTSTUFFS_O. + (INSTALL): cd $(srcdir) before make. - * rtlanal.c (reg_set_p_1): Now static; add extra parm. + * flow.c (allocate_for_life_analysis, init_regset_vector): + Remove declaration. - * stmt.c: Delete redundant forward decls. - (expand_anon_union_decl): Correctly call expand_decl. + * function.h (get_first_block_beg): New declaration. - * toplev.c (strip_off_ending): Strip off any ending; don't - pretend we know what valid endings are. + * gbl-ctors.h (__do_global_dtors): Add prototype. - * svr4.h (ASM_OUTPUT_SECTION_NAME): Don't crash if DECL is null. + * gcov-io.h (__fetch_long): New declaration. + (__store_long): Likewise. + (__read_long): Likewise. + (__write_long): Likewise. - * rs6000.md ({load,store}_multiple): Don't use indirect_operand - in define_insn; use explicit MEM of register_operand instead. + * gcov.c (print_usage): New declaration. -Tue Jun 27 11:42:56 1995 Stephen L Moshier + * Makefile.in (c-iterate.o): Depend on insn-codes.h too. - * i386/i386.c (print_operand, case `J'): Use jns for GE and js for - LT. +Sat Jun 20 00:36:16 1998 Jeffrey A Law (law@cygnus.com) -Tue Jun 27 07:58:55 1995 Jason Merrill + * 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. - * expr.c (expand_expr, TARGET_EXPR): Only use original_target - if !ignore. + * c-common.c (check_format_info): Initialize length_char and + fci to keep -Wall quiet. -Tue Jun 27 07:27:26 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * except.c (jumpif_rtx): Put declaration and definition + inside a suitable #ifdef. + (jumpifnot_rtx): Delete dead function. - * fold-const.c (fold_truthop): Commute unextend and convert on - l_const and r_const. + * i386.h (output_int_conditional_move): Declare. + (output_fp_conditional_move): Likewise. + (ix86_can_use_return_insn_p): Likewise. - * c-common.c (decl_attributes, case A_CONSTRUCTOR, A_DESTRUCTOR): - Set TREE_USED. + * optabs.c (init_traps): Put prototype inside a suitable #ifdef. - * final.c (final_scan_insn): Don't call alter_cond unless - condition is on cc0. +Sat Jun 20 00:27:40 1998 Graham - * stmt.c (expand_asm_operands): Handle input operands that may not - be in a register. + * 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. -Mon Jun 26 19:23:05 1995 Richard Earnshaw (rearnsha@armltd.co.uk) +Fri Jun 19 22:40:25 1998 Jason Merrill - * arm/lib1funcs.asm (L_dvmd_tls): Renamed from L_divmodsi_tools. - * arm/t-semi (LIB1ASMFUNCS): Rename _dvmd_tls from _divmodsi_tools. + * regmove.c (copy_src_to_dest): Add decl for loop_depth. -Mon Jun 26 19:18:06 1995 Jim Wilson + * svr4.h (ASM_GENERATE_INTERNAL_LABEL): Cast arg to unsigned. + * dwarf2out.c (ASM_OUTPUT_DWARF_DATA1): Likewise. + Add parens to various macros. - * unroll.c (find_splittable_regs): When completely unrolling loop, - check for non-invariant initial biv values. +Fri Jun 19 23:22:42 1998 Bruno Haible -Mon Jun 26 19:13:54 1995 Gran Uddeborg + * c-typeck.c (pop_init_level): Warn about implicit zero initialization + of struct members. - * configure (i[345]86-*-isc*): Fix misspelled "rfile" to "ifile". +Fri Jun 19 23:06:33 1998 Jason Merrill -Mon Jun 26 18:58:22 1995 Mike Stump + * varasm.c (assemble_start_function): Add weak_global_object_name. + * tree.c (get_file_function_name): Use it. - * expr.c (expand_expr, case COND_EXPR): Protect the condition from - being evaluated more than once. - (do_jump, case TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR): Likewise. +Fri Jun 19 22:55:14 1998 Jeffrey A Law (law@cygnus.com) -Mon Jun 26 18:52:36 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * except.c (jumpif_rtx): Make static and add prototype. + (jumpifnot_rtx): Likewise. - * fixincludes (string.h): Fix return value for mem{ccpy,chr,cpy,set} - and str{len,spn,cspn} on sysV68. + * README.gnat: Add a build patch from Fred Fish. -Mon Jun 26 06:54:50 1995 Michael Meissner (meissner@cygnus.com) + * c-lang.c (GNU_xref_begin, GNU_xref_end): Deleted. - * i386/osfrose.h (LONG_DOUBLE_TYPE_SIZE): Go back to making long - double == double. + * Makefile.in (c-iterate.o): Depend on expr.h. -Thu Jun 22 19:14:41 1995 Pat Rankin (rankin@eql.caltech.edu) +Fri Jun 19 20:38:34 1998 H.J. Lu (hjl@gnu.org) - * make-cc1.com (if DO_LINK): Skip c-parse.* processing when - only relinking. - (gas_message): Update to reflect current version, and give - a different message if/when no version of gas is found.xo + * except.h (emit_unwinder, end_eh_unwinder): Removed. -Thu Jun 22 18:52:37 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + * 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. - * arm/lib1funcs.asm (___modsi3): Correctly set SIGN register for - modulo involving negative numbers. + * expr.c (do_jump_by_parts_greater_rtx): Removed. + (truthvalue_conversion): Likewise. -Thu Jun 22 18:32:27 1995 Uwe Seimet (seimet@chemie.uni-kl.de) + * c-iterate.c: Include "expr.h". + (expand_expr): Use proper values when calling the function. - * xm-atari.h (HZ): Now 100 and don't define if already defined. + * explow.c (emit_stack_save): Add prototype for FCN. + (emit_stack_restore): Likewise. -Thu Jun 22 18:26:12 1995 Jeffrey A Law (law@snake.cs.utah.edu) + * dwarf2out.c (getpwd): Add prototype. - * calls.c (expand_call): Correctly handle returning BLKmode - structures in registers when the size of the structure is not - a multiple of word_size. - * stmt.c (expand_return): Likewise. + * dwarf2out.h (debug_dwarf, debug_dwarf_die): New declarations. - * pa-gux7.h (LIB_SPEC): Undefine before redefining. - * pa-hpux.h (LIB_SPEC): Likewise. - * pa-hpux7.h (LIB_SPEC): Likewise. + * c-typeck.c (c_expand_asm_operands): Use proper values when calling + expand_expr. - * genmultilib: Work around hpux8 /bin/sh case bug. + * c-lex.c (yyprint): Add prototype. + (check_newline, build_objc_string): Remove declaration. - * pa.h (LIB_SPEC): Define to avoid -lg. + * c-tree.h (comptypes_record_hook): Removed. + (finish_incomplete_decl): New prototype. -Thu Jun 22 18:19:09 1995 Jason Merrill + * alias.c (find_base_value): Add prototype. + (true_dependence): Add prototype for function argument. - * expr.c (expand_expr, TARGET_EXPR): Use original_target. + * c-aux-info.c (xmalloc): Remove declaration. - * collect2.c (locatelib): Fix parsing of LD_LIBRARY_PATH. +Fri Jun 19 20:23:05 1998 Robert Lipe -Thu Jun 22 18:15:54 1995 Paul Eggert + * 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. - * configure: Create an empty Makefile.sed first, to work - around a Nextstep 3.3 bug. +1998-06-19 Jim Wilson -Thu Jun 22 18:03:44 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * loop.h (struct induction): Clarify comment for unrolled field. + * unroll.c (find_splittable_givs): Move set of unrolled field + after address validity check. - * Makefile.in (STAGESTUFF): Add stamp-crt. - (crtbegin.o, crtend.o): Now depend on stamp-crt. - (stamp-crt): New rule, to actually build crt{begin,end}.o. - - * collect2.c (main): Unlink export_file before we return. +Fri Jun 19 18:38:04 1998 Michael Meissner + + * config/fp-bit.c (INLINE): Only define if not already defined. -Thu Jun 22 14:25:56 1995 Michael Meissner (meissner@cygnus.com) +1998-06-19 Manfred Hollstein - * rs6000.h (STRIP_NAME_ENCODING): Store NAME and strlen(NAME) into - local variables; cast result of alloca to avoid compiler warnings. + * Makefile.in (installdirs): Loop over directories in $(libsubdir) + creating probably missing ones, instead of single if statements. -Tue Jun 20 18:25:29 1995 Douglas Rupp (drupp@cs.washington.edu) +Fri Jun 19 10:43:52 1998 Andreas Schwab - * alpha/config-nt.sed, i386/config-nt.sed: Edit to add - a missing $(exeext) for CCCP. + * c-common.c (truthvalue_conversion): Protect side effects in the + expression when splitting a complex value. + * fold-const.c (fold): Likewise. -Tue Jun 20 18:18:00 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Fri Jun 19 02:31:16 1998 Klaus Kaempf (kkaempf@progis.de) - * protoize.c (default_include): Use name and two ints to be - compatible with definition of INCLUDE_DEFAULTS. + * cccp.c (hack_vms_include_specification): rewrite to handle + '#include ' correctly. -Mon Jun 19 19:24:29 1995 Ted Lemon +Fri Jun 19 02:24:11 1998 H.J. Lu (hjl@gnu.org) - * mips/netbsd.h (ASM_DECLARE_FUNCTION_NAME): Don't emit function label. + * config/i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Defined. -Mon Jun 19 18:34:55 1995 Jason Merrill +Fri Jun 19 02:10:10 1998 John Wehle (john@feith.com) - * fixincludes: Don't define wchar_t under C++. + * i386.c (notice_update_cc): Integer conditional moves don't + affect cc0. -Mon Jun 19 17:12:41 1995 Paul Eggert + * 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. - * cccp.c (collect_expansion): Work around enum bug in vax - ultrix 4.3 pcc. - * tree.c (simple_cst_equal): Likewise. +Fri Jun 19 02:00:19 1998 Richard Kenner -Mon Jun 19 16:53:00 1995 Douglas Rupp (drupp@cs.washington.edu) + * reload1.c (reload_cse_regno_equal_p): If -ffloat-store, don't + consider a MEM in FP mode as equal. - * winnt/spawnv.c: New file. +Fri Jun 19 01:02:17 1998 Jeffrey A Law (law@cygnus.com) -Mon Jun 19 16:30:29 1995 Glenn Brown + * c-decl.c (duplicate_decls): Avoid setting TREE_ASM_WRITTEN for + duplicate declarations of a function. - * caller-save.c (save_call_clobbered_regs): If AUTO_INC_DEC, mark - register indicated by REG_INC notes as live so they will be saved. +Fri Jun 19 00:33:33 1998 H.J. Lu (hjl@gnu.org) -Mon Jun 19 16:21:12 1995 Jeffrey A Law (law@snake.cs.utah.edu) + * config/float-i386.h: New. - * pa.h (PRINT_OPERAND_ADDRESS, case LOW_SUM): Fix logic bug - in last change. + * configure.in (i[34567]86-*-linux-*): Set float_format to i386. -Mon Jun 19 14:11:49 1995 Jim Wilson +Thu Jun 18 20:11:00 1998 Jim Wilson - * integrate.c (integrate_decl_tree): Only set DECL_ABSTRACT_ORIGIN - if the decl returned by pushdecl is the one we started with. + * 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. - * mips.h (current_function_name): Delete declaration. - (ASM_DECLARE_FUNCTION_NAME): Don't set current_function_name. - * gnu.h (ASM_DECLARE_FUNCTION_NAME): Likewise. - * mips.c (current_function_decl): Delete declaration. - (function_prologue): New variable fnname. Use it instead of - current_function_name. - (function_epilogue): Likewise. +Thu Jun 18 18:16:01 1998 Jim Wilson -Mon Jun 19 13:13:15 1995 Richard Kenner + * dwarf2out.c (size_of_string): Do count backslashes. - * alpha.h (ASM_OUTPUT_ASCII): Always reset line count when - starting new line. +Thu Jun 18 11:43:54 1998 Nick Clifton - * scan-decls.c (scan_decls): Fix typo when resetting PREV_ID_START. + * 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. - * i386/config-nt.sed, alpha/config-nt.sed: Change version to 2.7.1. +Thu Jun 18 17:30:39 1998 J"orn Rennecke -Mon Jun 19 13:06:14 1995 DJ Delorie (dj@delorie.com) + * reload.c (find_reloads): Don't narrow scope of RELOAD_OTHER to + RELOAD_FOR_INSN. - * msdos/top.sed: Support new build variables. - * msdos/configur.bat: Make options.h and specs.h. - Change realclean to maintainer-clean. +Thu Jun 18 09:36:50 1998 Kaveh R. Ghazi -Fri Jun 16 06:54:03 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * Makefile.in (c-lang.o): Depend on output.h. - * Version 2.7.0 Released. + * c-lang.c: Include output.h. - * obstack.c: Always enable this code for now. + * sparc.c (sparc_builtin_saveregs): Remove unused variable `fntype'. - * alpha.c (alpha_builtin_saveregs): Use ptr_mode and conversions - when need so works for both OSF and NT. - * va-alpha.h (__va_tsize): Round to long long not long. + * except.c (expand_builtin_eh_stub): Likewise for variable `jump_to'. -Thu Jun 15 17:54:52 1995 Bdale Garbee + * genrecog.c (write_subroutine): When writing insn-recog.c, mark + variables `insn', `pnum_clobbers', `x[0 .. max_depth]' and `tem' + with ATTRIBUTE_UNUSED. - * configure (a29k-*-coff): Synonym for a29k-*-udi. + * regmove.c (copy_src_to_dest): Make function static to match its + prototype. -Thu Jun 15 17:51:21 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * reload1.c Include hard-reg-set.h before rtl.h to get macro + HARD_CONST. Include machmode.h before hard-reg-set.h. - * function.c (assign_parms): Do all conversions in CONVERSION_INSNS. + * rtl.h: Prototype `retry_global_alloc' and wrap with macro + HARD_CONST to protect usage of typedef HARD_REG_SET. -Thu Jun 15 17:36:49 1995 Michael Meissner + * tree.c: Prototype `_obstack_allocated_p'. - * reg-stack.c (record_reg_life): Call record_reg_life_pat with 0 - for douse argument so that USE's created to mark variables within - blocks don't get marked as set. + * varasm.c: Wrap prototype of `asm_output_aligned_bss' in macro + BSS_SECTION_ASM_OP. -Thu Jun 15 06:28:15 1995 Dennis Glatting (dennisg@CyberSAFE.COM) +Thu Jun 18 09:20:47 1998 Kaveh R. Ghazi - * configure: Change one sed command to work around m68k-next bug. + * 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'. -Wed Jun 14 22:14:39 1995 Jason Merrill + * 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'. - * collect2.c (main): Don't turn off auto_export because of -g. - (main): Ignore the argument to -o. +Wed Jun 17 22:28:48 1998 Jason Merrill - * alpha.h (LINK_SPEC): Don't pass -init __main anymore. - * alpha/osf12.h (LINK_SPEC): Ditto. - * mips/iris5.h (LINK_SPEC): Ditto. + * configure.in: Don't turn on collect2 unconditionally. - * collect2.c (main): Place o_file after an initial .o (like crt0.o). - If we have LD_INIT_SWITCH, use init and fini functions for - executables, too. Specify the unique function names. - (write_c_file_stat): Fix the case of destructors but no constructors. - Don't include the generic-named functions for executables. - (write_c_file): If we have LD_INIT_SWITCH, always use - write_c_file_stat. +Wed Jun 17 20:20:48 1998 Mark Mitchell - * collect2.c (main): Also add _GLOBAL__D? to export list. + * 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. - * ginclude/iso646.h: Do nothing if compiled as C++. +Wed Jun 17 18:30:43 1998 Franz Sirl -Wed Jun 14 17:39:10 1995 Roland McGrath (roland@gnu.ai.mit.edu) + * rs6000/linux.h (JUMP_TABLES_IN_TEXT_SECTION): Define to zero. - * c-common.c (format_char_info, case 'm'): Set type to void. - (check_format_info): If type is void, ignore operand. +Wed Jun 17 19:05:03 1998 John Carr -Wed Jun 14 17:04:10 1995 Paul F. Kunz (Paul_Kunz@SLAC.Stanford.EDU) + * haifa-sched.c (haifa_classify_insn): TRAP_IF is risky. + (sched_analyze_2): Allow scheduling TRAP_IF. - * expr.c (expand_builtin_apply_args): Put back original - register save and restore order. + * reorg.c (mark_referenced_resources): Examine operands of TRAP_IF. -Wed Jun 14 16:56:22 1995 Michael Meissner + * rtl.h (TRAP_CODE): New macro. - * rs6000/eabi.h (INVOKE__main): Define, so __eabi is called after - main's arguments are saved. + * rtl.def (TRAP_IF): Change second operand type to rtx. - * rs6000.c (output_prolog): Don't call __eabi here, let - compiler call it after the arguments to main are saved. - (output_{prolog,epilog}): Don't use functions under V.4 to save - and restore floating point registers. + * optabs.c (gen_cond_trap): New function. + (init_traps): New function. + (init_optabs): Call init_traps. + * expr.h: Declare gen_cond_trap. -Wed Jun 14 16:52:12 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * jump.c (jump_optimize): Optimize jumps to and around traps. - * m68k/mot3300.h (PCC_BITFIELD_TYPE_MATTERS): Defined. + * sparc.md: Define trap instructions. -Wed Jun 14 16:48:53 1995 Jerry Frain (jerry@tivoli.com) + * rs6000.md: Define trap instructions. + * rs6000.c (print_operand): New code 'V' for trap condition. + (trap_comparison_operator): New function. - * Makefile.in (stage[1-4]): Correctly link `as', `ld', and `collect2'. + * m88k.md: Update use of TRAP_IF. -Wed Jun 14 05:52:04 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * objc-act.c (hack_method_prototype): Set DECL_CONTEXT of parms. + * expr.c (expand_builtin): Error if __builtin_longjmp second argument + is not 1. - * expmed.c (emit_store_flag): Always set LAST. +Wed Jun 17 15:20:00 PDT 1998 Catherine Moore - * c-decl.c (start_function): New parameter for attributes. - * c-tree.h (start_function): Likewise. - * c-lang.c (finish_file): Pass extra parm to start_function. - * objc-act.c (build_module_descriptor, really_start_method): Likewise. - * c-parse.in (fndef, nested_function, notype_nested_function): - Likewise. + * 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) - * function.c (assign_parms): Use convert_to_mode instead of - gen_lowpart when converting incoming parm. + * 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. -Tue Jun 13 19:10:32 1995 Richard Kenner +Wed Jun 17 15:57:48 EDT 1998 Andrew MacLeod (amacleod@cygnus.com) - * rs6000.md (decrement_and_branch): Finish last fix; update matching - constraint. + * 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. + +1998-06-17 12:46:56 1998 Jim Wilson + + * mips/iris6.h (LINK_SPEC): Add -woff 131. + +1998-06-17 Jason Merrill + + * dwarf2out.c: Disable EH_FRAME_SECTION if we don't have .init. + + * configure.in: Don't disable collect2 when we have GNU ld. + +Wed Jun 17 08:38:13 1998 Jeffrey A Law (law@cygnus.com) + + * fold-const.c (make_range): Do not widen the type of the expression. + + * 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. + + * configure.in (nm): Make a link to "nm" in the build tree too. + + * mn10300.md (andsi3): Fix typo. + +Tue Jun 16 22:58:40 1998 Richard Henderson + + * reload1.c (reload_cse_regs): Call bzero instead of looping. + +Tue Jun 16 18:30:35 1998 Jim Wilson + + * dwarf2out.c (stripattributes): Prepend '*' to the section name. + +Tue Jun 16 16:49:26 1998 Richard Henderson + + * 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. + +Tue Jun 16 17:36:35 1998 Dave Brolley + + * toplev.c (lang_options): Add -trigraphs option for cpplib. + +Tue Jun 16 23:33:24 1998 J"orn Rennecke + + * 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. + +Tue Jun 16 13:15:16 1998 Jim Wilson + + * libgcc1-test.c (memcpy): Define. + +Tue Jun 16 13:44:02 1998 Michael Meissner + + * 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. + +Mon Jun 15 17:06:43 1998 Michael Meissner + Jim Wilson + + * regmove.c (copy_src_to_dest): Do not copy src to dest if either + the source or destination is special. + +Mon Jun 15 13:20:33 1998 Jim Wilson + + * c-decl.c (shadow_tag_warned): Use specs not declspecs in for loop. + +Mon Jun 15 07:16:29 PDT 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sat Jun 13 13:10:40 1998 Krister Walfridsson + + * config/sparc/netbsd.h (DEFAULT_PCC_STRUCT_RETURN): Undefine before + redefining it. + +Fri Jun 12 18:06:45 1998 Doug Evans + + * m32r/m32r.h (STARTFILE_SPEC): Delete crtsysc.o. + (ENDFILE_SPEC): Add -lgloss. + +Fri Jun 12 14:57:59 1998 Kaveh R. Ghazi + + * 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. + + * mips.md (mul_acc_si): Remove unused variable `macc'. + +Fri Jun 12 09:33:44 1998 Richard Henderson + + * fold-const.c (fold): Revert last change. It breaks constant + expressions somehow. + +Fri Jun 12 10:23:36 1998 Andreas Schwab + + * expr.c (do_jump, case EQ_EXPR, NE_EXPR): When comparing complex + prevent operands from being evaluated twice. + +Fri Jun 12 00:50:27 1998 Sergey Okhapkin + + * toplev.c (lang_options): Add -remap as a preprocessor option. + +Fri Jun 12 00:30:32 1998 John Wehle (john@feith.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. + +Thu Jun 11 17:14:15 1998 Jim Wilson + + * except.c (expand_builtin_eh_stub): Call emit_move_insn rather than + calling gen_rtx_SET. + +Thu Jun 11 18:45:49 1998 David Edelsohn + + * config/rs6000/x-aix43 (AR): Delete. + (AR_FOR_TARGET_FLAGS): Add -X32_64 here. + +Thu Jun 11 16:19:17 1998 David W. Schuler + + * config/i386/aix386ng.h (CPP_SPEC): Remove extraneous quote. + +Thu Jun 11 12:40:27 1998 Jim Wilson + + * mips.c (override_options): Replace word_mode with explicit + TARGET_64BIT check. + +Thu Jun 11 14:50:02 1998 Michael Meissner + + * 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 + + * Makefile.in (regmove.o): Add basic-block.h dependencies. + +Thu Jun 11 10:30:09 1998 Dave Brolley -Tue Jun 13 18:32:51 1995 Torbjorn Granlund + * toplev.c (lang_options): Add missing options (nostdinc, idirafter). - * fold-const.c (fold): When converting a COND_EXPR to an ABS_EXPR, - get the types right for ABS_EXPR to work. +Wed Jun 10 23:39:32 1998 Mark Mitchell -Mon Jun 12 17:09:55 1995 Michael Tiemann (tiemann@axon.cygnus.com) + * rtl.h (rtx_def): Improve documentation. + (MEM_IN_STRUCT_P): Likewise. - * reorg.c (fill_simple_delay_slots): Set MAYBE_NEVER according to - code of TRIAL_DELAY, not TRIAL. +Wed Jun 10 23:23:17 1998 Graham -Mon Jun 12 15:02:37 1995 Doug Evans + * c-decl.c (start_decl): Correct test for -Wmain. - * configure: Restore code to make ld symlink if ! use_collect2. + * c-decl.c (grokdeclarator): Remove unused variable "last". - * gcc.c (link_command_spec): Undo patch of May 11. - -nostdlib implies -nostartfiles again. - * dsp16xx.h (CROSS_LINK_SPEC): Likewise. - * i386/freebsd.h (LINK_SPEC): Undo patch of May 24. - Don't pass "-e start" if nostdlib. - * i386/sun.h (LINK_SPEC): Likewise. - * m68k/sun2o4.h (LINK_SPEC): Likewise. - * m68k/sun3.h (LINK_SPEC): Likewise. - * m68k/vxm68k.h (LINK_SPEC): Likewise. - * mips/netbsd.h (LINK_SPEC): Likewise. - * config/netbsd.h (LINK_SPEC): Likewise. - * rs6000/mach.h (LINK_SPEC): Likewise. - * sparc.h (LINK_SPEC): Likewise. - * sparc/vxsparc.h (LINK_SPEC): Likewise. +Wed Jun 10 14:52:27 1998 Jim Wilson - * gcc.c (link_command_spec): New argument -nodefaultlibs. + * 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. -Sun Jun 11 20:47:53 1995 Stephen L Moshier (moshier@world.std.com) +Wed Jun 10 13:08:41 1998 Mark Mitchell - * Makefile.in (fix-header.o): Depends on xsys-protos.h. + * mips/mips.c: Remove -mabi=o32 and -mabi=n64. -Sun Jun 11 15:07:58 1995 Tim Carver (timc@ibeam.intel.com) +Wed Jun 10 13:41:23 1998 Dave Brolley - * reload1.c (emit_reload_insns): Don't call HARD_REGNO_NREGS - on psuedo when clearing reg_last_reload_reg. + * 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@. -Sun Jun 11 14:07:05 1995 Philippe De Muyter (phdm@info.ucl.ac.be) +Wed Jun 10 13:07:02 1998 Dave Brolley - * m68k.md ({add,sub}di{_mem,3}): Patterns merged. + * 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. -Sun Jun 11 13:43:26 1995 Torbjorn Granlund +Wed Jun 10 09:47:13 1998 Richard Earnshaw (rearnsha@arm.com) - * m68k.md (cmpdi matcher): Set cc_status before returning. + * unroll.c (verify_addresses): Use validate_replace_rtx to undo the + changes. Abort if the undo fails. - * config/xm-freebsd.h (DONT_DECLARE_SYS_SIGLIST): Define. +1998-06-10 Vladimir N. Makarov -Sun Jun 11 13:38:49 1995 Jason Merrill + * config/rs6000/rs6000.c (output_prolog): Change locations and + directions of saving and restoring arguments of main on the stack. - * fixincludes (math.h): Keep declaration of abs on HPUX. +Wed Jun 10 08:56:27 1998 John Carr -Sun Jun 11 12:31:42 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * stor-layout.c (variable_size): Do nothing if SIZE is constant. +Wed Jun 10 02:11:55 1998 Jeffrey A Law (law@cygnus.com) - * stmt.c (expand_asm_operands): See if output operand permits - register. If not, mark output addressable, call expand_operand - on it, and give error if not MEM. + * decl.c (init_decl_processing): Fix typo. - * function.c (assign_parms): Handle promotions of both - passed and nominal modes separately and insert needed conversions. - (promoted_input_arg): Return 0 if nominal and passed modes differ. + * 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. - * stmt.c (all_cases_count, case INTEGER_TYPE): Fix typo in checking - for integer bounds. + * 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. -Sat Jun 10 08:55:25 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Wed Jun 10 01:39:00 1998 Juha Sarlin - * libgcc2.c (_floatdidf): Correctly set float sizes. + * h8300.c (get_shift_alg): Add special cases for shifts of 8 and 24. - * c-decl.c (c_decode_option, case "-Wall"): Don't set extra_warnings. +Tue Jun 9 22:05:34 1998 Richard Henderson - * Makefile.in (cpplib.o, fix-header.o): Update dependencies. - (cpperror.o, cppexp.o, cpphash.o): New rules, to show .h dependencies. + * fold-const.c (fold): Even with otherwise constant trees, look for + opportunities to combine integer constants. -Fri Jun 9 18:06:10 1995 Doug Evans +Wed Jun 3 23:41:24 EDT 1998 John Wehle (john@feith.com) - * cse.c (cse_basic_block): Fix test for whether block ends with a - barrier. Return next insn, not 0, if block ends in a barrier. + * i386.c (notice_update_cc): Clear cc_status.value2 in the + case of UNSPEC 5 (bsf). -Fri Jun 9 17:58:29 1995 Paul Eggert + * i386.md (movsfcc, movdfcc, movxfcc): The floating point + conditional move instructions don't support signed integer + comparisons. - * fold-const.c (lshift_double): Replace `&' with `%' to fix typo. - ([lr]shift_double): Truncate shift count only if SHIFT_COUNT_TRUNCATED. - Remove unnecessary `count >= prec' test. +Tue Jun 9 14:31:19 1998 Nick Clifton - * cexp.y (left_shift): Ignore integer overflow. + * config/v850/t-v850 (TCFLAGS): Add assembler options to warn of + overlfows. - * cexp.y (skip_evaluation): New variable. - (&&, ||, ?:): Increment it in unevaluated subexpressions. - (/, %, integer_overflow): Suppress diagnostics if skip_evaluation != 0. - (yyerror): Clear skip_evaluation. + * config/v850/lib1funcs.asm (__return_interrupt): Use 'addi + 16,sp,sp' ratehr than 'add 16,sp'. Patch courtesy of Biomedin + . -Fri Jun 9 17:49:05 1995 Torbjorn Granlund +Tue Jun 9 16:23:13 EDT 1998 Andrew MacLeod - * m68k.md (tstdi): Rewrite. + * 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. -Fri Jun 9 17:28:55 1995 Per Bothner +Tue Jun 9 12:57:32 1998 Mark Mitchell - * scan-decls.c (scan_decls): Handle declarations with - multiple comma-separated declarators. + * invoke.texi: Add documentation for -mips4 and -mabi=*. -Thu Jun 8 19:16:12 1995 Richard Earnshaw (rearnsha@armltd.co.uk) +Tue Jun 9 12:12:34 1998 Klaus Kaempf (kkaempf@progis.de) - * arm.md (mov[sd]f expands): Don't allow fp constants in pseudos - when TARGET_SOFT_FLOAT. + * 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. -Thu Jun 8 19:11:43 1995 Jim Wilson +Tue Jun 9 12:10:27 1998 John Carr - * expmed.c (store_split_bit_field): When adjust arg in - BYTES_BIT_ENDIAN case, use number of bits in arg for MEM operands - and BITS_PER_WORD for other operands. - (extract_fixed_bit_field): Undo last change. + * haifa-sched.c (update_flow_info): Use UNITS_PER_WORD, not MOVE_MAX, + as the threshold to permit splitting memory operations. - * unroll.c (verify_addresses): New function. - (find_splittable_givs): Use it instead of memory_address_p. +Tue Jun 9 12:36:16 1998 Jeffrey A Law (law@cygnus.com) -Thu Jun 8 18:58:18 1995 Torbjorn Granlund + * 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. - * expmed.c (expand_divmod): Always check result of emit_store_flag. + * 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. -Thu Jun 8 12:02:34 1995 David D Zuhn (zoo@armadillo.com) + * 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. - * cpplib.c (cpp_push_buffer): Include filename in error message. +Tue Jun 9 02:40:49 1998 Richard Henderson -Thu Jun 8 11:53:45 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * mips/elf.h (ASM_DECLARE_OBJECT_NAME): Define. + (ASM_FINISH_DECLARE_OBJECT): Define; + * mips/elf64.h: Likewise. - * function.c (assign_parms): Don't call promote_mode on arg - unless PROMOTE_FUNCTION_ARGS defined. +Tue Jun 9 01:08:47 1998 Richard Henderson - * rs6000.md (decrement_and_branch): Ensure label is operand 0. + * toplev.c (flag_new_exceptions): Remove extraneous `extern'. - * rs6000.md (aux_truncdfsf2): New pattern. - (movsf): Use it instead of invalid SUBREG and truncdfsf2. +Mon Jun 8 23:24:48 PDT 1998 Jeff Law (law@cygnus.com) - * varasm.c (assemble_name): Disable warn_id_clash around - get_identifier call. + * version.c: Bump for snapshot. -Wed Jun 7 17:22:25 1995 Philippe De Muyter (phdm@info.ucl.ac.be) +Mon Jun 8 23:24:58 1998 David Edelsohn - * configure (gdb_needs_out_file_path): New variable. - (m68k-motorola-sysv): Set gdb_needs_out_file_path if not using gas. - (.gdbinit): If gdb_needs_out_file_path is set, add a 'dir' command - for $(out_file). + * rs6000.md (mulsidi3): Add !TARGET_POWERPC64 constraint. + (mulsidi3_ppc64): Delete. -Wed Jun 7 17:17:19 1995 Torbjorn Granlund +Mon Jun 8 20:57:40 1998 Kaveh R. Ghazi - * fold-const.c (fold): When folding `<' type nodes, make true_value - and false_value have correct types. + * Makefile.in (varasm.o): Depend on dbxout.h. + (cse.o): Depend on toplev.h and output.h. + (gcse.o): Depend on output.h. -Wed Jun 7 05:06:42 1995 Jason Merrill + * 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'. - * collect2.c (COFF scan_prog_file): Use the AIX duplicate entry. + * sparc.h: Add prototype for `v8plus_regcmp_op'. -Tue Jun 6 18:43:09 1995 Jeffrey A Law (law@snake.cs.utah.edu) + * 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 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 + + * 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 + Jeff Law + + * 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 + + * 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 + + * 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. + +Mon Jun 8 10:43:15 1998 Richard Henderson + + * expr.c (force_operand): Detect PIC address loads before + splitting arithmetic. - * pa.h (FUNCTION_ARG_CALLEE_COPIES): Define. +Mon Jun 8 09:22:38 PDT 1998 Jeff Law (law@cygnus.com) -Tue Jun 6 18:21:18 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * version.c: Bump for snapshot. - * expr.c (expand_expr, case PLACEHOLDER_EXPR): Consider two types - identical if their TYPE_MAIN_VARIANTs are the same. +Mon Jun 8 02:55:56 1998 Graham - * c-decl.c (start_decl): Set DECL_COMMON before calling - decl_attributes. + * tree.c (tree_class_check): Add braces to eliminate ambigious + else warning. + (tree_check): Likewise. - * a29k.c (print_operands): Cast args to bcopy to char *. +Mon Jun 8 02:49:23 1998 H.J. Lu (hjl@gnu.org) - * c-decl.c (duplicate_decls): Don't clear DECL_CONTEXT of - new decl if it is a function. + * reg-stack.c (subst_stack_regs_pat): Make sure the top of + stack is the destination for conditional move insn. -Tue Jun 6 17:57:44 1995 Eberhard Mattes (mattes@azu.informatik.uni-stuttgart.de) +Mon Jun 8 01:21:13 1998 Jason Merrill - * gcc.c (do_spec_1, case 'g'): Handle %O as suffix if MKTEMP_EACH_FILE. + * tree.h (TREE_VEC_END): Cast unused value to void. -Tue Jun 6 17:53:05 1995 Michael Meissner + * i386.c (print_operand): Use %lx for long operand. - * rs6000.c (expand_block_move): Update source and destination pointers - inside the loop moving the bytes, not outside. +Mon Jun 8 00:04:07 1998 Richard Henderson -Tue Jun 6 14:58:37 1995 Andreas Schwab + * alpha.c (summarize_insn): Ignore rtl slot format 'i'. - * m68k.h (CONDITIONAL_REGISTER_USAGE): Don't mark pic reg as fixed. - * m68k.c (finalize_pic): Emit USE insn at start and end of function. +Sun Jun 7 14:15:45 1998 John Carr -Tue Jun 6 13:46:57 1995 Jim Wilson + * sol2.h (INIT_SUBTARGET_OPTABS): Use Solaris libc float/long long + conversion functions. - * sh.c (print_operand): Check for annulled branches. - (output_movedouble): Handle SUBREG addresses. - (output_branch): Handle annulled branches. - (sh_expand_prologue): Correct number of saved registers for - varargs functions. - * sh.h: Add some comments. - * sh.md: Add some comments. Cleanup formatting. - (type attribute): Add pstore and call. - (return define_delay): Reorganize to make clearer. - (call/sfunc define_delay): Define. - (cbranch define_delay): Define to have annul-true delay slot. - (subsi3): Use arith_reg_operand for operand 2. - (shift patterns): Use const_int_operand instead of immediate_operand - for shift counts. - (push): Add pstore constraint case. - (movsi_i): Move t/z constraint pair to the front of the list. - (calli, call_valuei): Add "call" attribute. +Sun Jun 7 14:02:58 1998 Richard Henderson + + * 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. -Mon Jun 5 19:23:13 1995 Jim Wilson +Sun Jun 7 12:27:30 1998 David Edelsohn + + * 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. + +Sat Jun 6 12:17:12 1998 Kaveh R. Ghazi + + * gencheck.c: Remove redundant stdio.h include. Add a definition + of xmalloc for when we are forced to link with alloca.o. + + * reload1.c (reload_reg_free_for_value_p): Use `(unsigned)1' + instead of `1U'. + + * fold-const.c (constant_boolean_node): Make definition static to + match the prototype. + +Fri Jun 5 15:53:17 1998 Per Bothner + + * 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. + +Fri Jun 5 12:29:28 1998 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (rank_for_schedule): For "equally good insns", prefer + the insn which has the most insns dependent on it. + +Fri Jun 5 09:03:22 1998 John Carr + + * alias.c (find_base_value): Avoid reading past end of reg_base_value. + +Fri Jun 5 03:05:34 1998 Richard Henderson + + * alpha.md (insxh-1): New insxl pattern for combine. + +Fri Jun 5 01:12:15 1998 H.J. Lu (hjl@gnu.org) + + * 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. + + * 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. + + * 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 + + * dbxout.c (dbxout_type): Output arrays of bits as if + they were bitstrings for Chill + +Thu Jun 4 14:35:27 1998 David Edelsohn + + * 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. - * sched.c (attach_deaths): In last change, use find_reg_note instead - of find_regno_note. +Thu Jun 4 01:26:57 1998 Craig Burley -Mon Jun 5 19:17:31 1995 Tom Quiggle (quiggle@lovelace.engr.sgi.com) + * expr.c (safe_from_p): Avoid combinatorial explosion + over duplicate SAVE_EXPRs by ensuring we never recurse + on one that has already been visited. - * mips/iris5.h (MACHINE_TYPE): Say "IRIX 5.x", not "5.0". - (NO_DOLLAR_IN_LABEL): Undefine. - * mips.h (sdb_begin_function_line): New declaration. - (PUT_SDB_FUNCTION_END): New definition. +Thu Jun 4 00:54:21 1998 Graham -Mon Jun 5 18:56:10 1995 Michael Meissner + * loop.c (check_dbra_loop): Initialise final_value before + normalizing the loop. - * rs6000.c (expand_block_move): Don't do block moves where we clobber - fixed numbers of regs, instead move just 1-8 bytes at a time. +Wed Jun 3 20:00:04 1998 J"orn Rennecke - * Makefile.in (STAGESTUFF): Copy files produced by -da and - -save-temps to the stage subdirectories. + * reload1.c (reload_reg_free_for_value_p): New arguments out and + reloadnum. Changed all callers. -Mon Jun 5 08:18:46 1995 Torbjorn Granlund +1998-06-03 Ulrich Drepper - * combine.c (reg_dead_at_p): When scanning backwards, stop at BARRIER. + * system.h: Add _() and N_() macros in preparation for gettext. - * m68k.c (print_operand): Handle 'R' for registers. - * m68k.md (cmpdi): Rewrite to avoid bogus matching constraints. +Wed Jun 3 11:02:24 1998 Andreas Schwab - * optabs.c (expand_binop): In last change, don't defererence TARGET - if it is 0. + * 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. - * pa.md (movsicc): Use MATCH_DUP for operand 4 and 5. + * 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. -Mon Jun 5 08:14:56 1995 Jeffrey A Law (law@cs.utah.edu) +Tue Jun 2 23:14:01 1998 Richard Henderson - * pa.c (hppa_encode_label): Allocate stuff on permanent_obstack - rather than via malloc. + * jump.c (jump_optimize): Remove debug messages accidentally left in + with the previous change. - * c-common.c (decl_attributes): Fix typo in size passed to alloca. +Tue Jun 2 22:46:08 1998 Richard Henderson -Mon Jun 5 08:10:55 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * expr.c (store_expr): Revert stray patch associated with + 1998-05-23 commit. - * alpha.md: Use "some_operand" for patterns valid only during - reload and meant to handle adding more PLUS operators during - register elimination. +Tue Jun 2 21:59:01 1998 Richard Henderson -Mon Jun 5 07:31:53 1995 Stephen L Moshier (moshier@world.std.com) + * jump.c (rtx_unsafe_p): New function. + (jump_optimize): Use it on if/then/else transformations and + conditional move transformations. - * cse.c (simplify_unary_operation, case FLOAT, UNSIGNED_FLOAT): - Truncate to requested mode. +Tue Jun 2 22:50:10 1998 Andreas Schwab -Sat Jun 3 22:08:51 1995 Jim Wilson + * 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. - * sched.c (attach_deaths): Don't add a REG_DEAD note if a REG_UNUSED - note is already present. +Tue Jun 2 22:28:31 1998 Bernd Schmidt -Sat Jun 3 18:36:57 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * expr.c (emit_move_insn_1): When moving complex values in several + steps, emit a CLOBBER to show the destination dies. - * pa.h (hppa_builtin_saveregs): Add declaration. +Tue Jun 2 22:17:26 1998 Jeffrey A Law (law@cygnus.com) -Sat Jun 3 18:11:26 1995 Jason Merrill + * Makefile.in (site.exp): Use the object testsuite directory as + the temporary directory. - * Makefile.in (scan-decls.o): Depends on cpplib.h. + * expr.c (expand_expr, case ADDR_EXPR): Handle taking the + address of an ADDRESSOF rtx. -Fri Jun 2 19:23:47 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +1998-06-02 Mike Stump - * optabs.c (expand_binop): Don't use non-REG TARGET in 2-word case. + * 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. -Thu Jun 1 19:30:30 1995 Tor Egge (tegge@flipper.pvv.unit.no) +Tue Jun 2 14:02:38 1998 Richard Henderson - * m88k.h (RETURN_POPS_ARGS): New argument. - * m88k/dolphin.ld: Added start of comment. + * alpha.md (divsi3, udivsi3, modsi3, umodsi3): Enable, and work + around an OSF/1 library bug wrt sign-extension of inputs. -Thu Jun 1 19:12:28 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue Jun 2 13:02:44 1998 Richard Henderson - * configure (a29k-*-bsd*): Fix typo in last change. + * vax/netbsd.h (DWARF2_UNWIND_INFO): Must be undef, not defined 0. -Thu Jun 1 18:51:53 1995 Jim Wilson +Mon Jun 1 03:44:03 1998 Catherine Moore - * expmed.c (extract_fixed_bit_field): For REG case, compute total_bits - from mode instead of assuming BITS_PER_WORD. + * config/sh/sh.h (MAX_OFILE_ALIGNMENT): Define. -Thu Jun 1 18:34:31 1995 Michael Meissner + * varasm.c (assemble_variable): Augment alignment warning. - * rs6000.h (FIXED_R13): Default to 0. - ({FIXED,CALL_USED}_REGISTERS): Use FIXED_R13 for register 13. - * sysv4.h (FIXED_R13): Define to be 1. +Mon Jun 1 12:14:28 1998 Michael Meissner -Wed May 31 20:57:26 1995 Torbjorn Granlund + * config/fp-bit.c (_fp{add,div}_parts): Return correct IEEE result + in the presence of IEEE negative 0's. - * m68k.md ([su]mulsi3_highpart): Pass correct number of arguments to - const_uint32_operand. - * m68k.c (const_uint32_operand): Reject negative numbers. +Sun May 31 16:11:41 1998 John Wehle (john@feith.com) - * expmed.c (expand_mult_highpart): Use wide_op1 for all multiplies. - (expand_divmod): Undo Nov 12 change. Instead, add special case - for division by MIN_INT in signed TRUNC_DIV_EXPR case. + * 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. -Wed May 31 20:44:21 1995 Philippe De Muyter (phdm@info.ucl.ac.be) +Sun May 31 00:44:02 PDT 1998 Jeff Law (law@cygnus.com) - * m68k.md (one_cmpldi2): New pattern. - ({a,l}shrdi{3,_const}): Allow 63 as shift count. + * version.c: Bump for snapshot. -Wed May 31 14:56:31 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Sun May 31 00:34:17 1998 Bruce Korb - * varasm.c (assemble_start_function, assemble_variable): - Make sure first_global_object_name is in permanent obstack. + * Makefile.in (fixinc.sh): Update rules again. - * reload1.c (alter_reg): Clean up setting of RTX_UNCHANGING_P - when making a MEM. +Sun May 31 00:27:47 1998 Jeffrey A Law (law@cygnus.com) - * reorg.c (struct resources): New field unch_memory. - (CLEAR_RESOURCES, mark_target_live_regs, dbr_schedule): Clear it. - (mark_{referenced,set}_resources, redundant_insn): Set it. - (fill_simple_delay_slots): Likewise. - (resource_conflicts_p): Test it. + * extend.texi: Bring back reference to trampoline paper. - * unroll.c (copy_loop_body): Fix typo in call to sets_cc0_p. +Sun May 31 00:22:34 1998 Ulrich Drepper - * integrate.c (output_inline_function): Don't call expand_function_end. + * Makefile.in (USER_H): Add stdbool.h. + * ginclude/stdbool.h: New file. - * calls.c (prepare_call_address): Only call use_reg on - static_chain_rtx if it is a REG. +Fri May 29 01:48:25 1998 Jeffrey A Law (law@cygnus.com) - * configure (a29k-*-bsd*): Use t-a29k. - * t-a29k: New file. - * a29k/t-a29kbare (LIBGCC1_TEST): New null definition. - * a29k/t-vx29k (LIBGCC1_TEST): Likewise. + * jump.c (thread_jumps): Do not look at the NOTE_LINE_NUMBER + of a non-note insn. -Wed May 31 14:17:42 1995 Jeffrey A Law (law@snake.cs.utah.edu) + * gcse.c (pre_delete): Fix code to determine the mode of + the reaching pseudo register. - * configure (hppa*-*-bsd*): Do not run fixincludes. - (hppa*-*-osf*): Likewise. - (hppa*-*-lites*): Likewise. +Fri May 29 01:07:28 1998 Bernd Schmidt - * pa.h (PRINT_OPERAND_ADDRESS): Use "RR'" rather than "R'" for - symbolic addresses. - * pa.md (symbolic HIGH patterns): Likewise. - (symbolic LO_SUM pattern): Likewise. + * Makefile.in (GEN): Add gencheck + (STAGESTUFF): Add tree-check.h and gencheck. -Wed May 31 14:11:53 1995 Michael Meissner +Fri May 29 00:57:37 1998 Bruce Korb - * rs6000.md (all movstri recognizers): Eliminate updating the pointers. - * rs6000.c (expand_block_move): Don't pass argument of # bytes to - increment pointers by to movstrsi expanders. + * Makefile.in (cstamp-h.in): Remove before trying to recreate. + (fixinc.sh): Set some additional environment variables before + calling mkfixinc.sh. - * rs6000.c (rs6000_override_options): Fix typo with -mstring handling. +Thu May 28 12:57:05 1998 Jeffrey A Law (law@cygnus.com) - * rs6000.h (TARGET_SWITCHES): Set MASK_STRING_SET explicitly - if -mno-string, so that it can override the processor default. + * reload.c (find_reloads): Do not force a reloads of match_operators. -Wed May 31 07:31:53 1995 Jason Merrill +Thu May 28 10:22:22 EDT 1998 Andrew MacLeod - * c-common.c (truthvalue_conversion, BIT_AND_EXPR): Make sure that - the result has boolean_type_node. + * 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. -Tue May 30 19:03:21 1995 J.T. Conklin +Thu May 28 09:36:39 1998 Michael Meissner - * stddef.h: Undefine _BSD_XXX_T_ if _GCC_XXX_T is defined on BSD - Net/2 derived systems. + * except.h (rtx): Define rtx type correctly if needed. + * function.h (rtx): Ditto. + (tree): Define tree type correctly if needed. -Tue May 30 08:17:37 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * c-pragma.c (toplevel): Include rtl.h. - * m68k.md (decrement_and_branch_until_zero): Operand 0 constraint - changed from "+g" to "+d*am". - (similar anonymous HImode pattern): Likewise. + * stor-layout.c (toplevel): Move include of rtl.h before + except.h. - * m68k.md (tstdi): Use tst/subx #0 instead of neg/negx. - Allow "a" and ">" for operand 0. + * Makefile.in (c-pragma.o): Add except.h, rtl.h dependencies. + (tree.o): Add except.h dependency. -Mon May 29 19:24:43 1995 Niklas Hallqvist (niklas@appli.se) +Wed May 27 22:02:40 1998 Jeffrey A Law (law@cygnus.com) - * m68k.md (addsi_lshrsi_31): Use match_dup, not constraint "1", - for matching inputs. + * reload1.c: Revert accidental checkin. -Mon May 29 12:39:58 1995 Allen Briggs + * configure.lang: Fix thinko when adding a definition for + target_alias to the Makefile. - * i386/isc.h ({STARTFILE,LIB,CPP}_SPEC): Handle -Xp like -posix. - * i386/x-isc3 (X_CFLAGS): Add -Xp. - -Mon May 29 12:28:41 1995 J.T. Conklin (jtc@cygnus.com) +Wed May 27 02:50:00 1998 Catherine Moore (clm@cygnus.com) - * configure (sparc-*-netbsd): Add missing asterisk at end. + * config/sparc/lb1spc.asm (.rem and .urem): Replace + routines. -Mon May 29 08:55:48 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Wed May 27 02:48:31 1998 Richard Earnshaw (rearnsha@arm.com) - * combine.c (recog_for_combine): New parm PADDED_SCRATCHES; set it. - (try_combine): Accumulate number of scratches and update max_scratch. - (simplify_set): Add extra parm to recog_for_combine. + * 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. - * romp.md (call): Put USE for r0 in CALL_INSN; call call_internal - to emit insn. - (call_internal): New name for anonymous call. - (call_value, call_value_internal): Likewise. +1998-05-27 Manfred Hollstein - * winnt/xm-winnt.h: Protect most definitions with #ifndef. - * alpha/xm-winnt.h: Include alpha/xm-alpha.h, then winnt/xm-winnt.h. - (POSIX): Undefine. - * xm-alpha.h: Don't include alloca.h for winnt. + * toplev.h (rtx_def): Provide global declaration to avoid + `limited scope' warnings. -Sun May 28 18:34:01 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue May 26 23:47:52 1998 Mumit Khan - * configure: Make sed commands more uniform. + * Makefile.in (gencheck.o): Use HOST_CC. + * i386/t-mingw32: New file. + * configure.in (i386-*-mingw32*): Use. - * Makefile.in: Properly use $(srcdir) for files that have it - in their reference as a target of a rule. - (libgcc1.a): Add missing RANLIB_TEST use. +Tue May 26 07:31:04 1998 Richard Earnshaw (rearnsha@arm.com) - * stmt.c (expand_computed_goto): Call do_pending_stack_adjust. + * 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. -Sun May 28 18:08:41 1995 Torbjorn Granlund + * 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. - * m68k.md (divmodhi4, udivmodhi4): Use "dmsK" for operand 2. +Mon May 25 22:49:56 PDT 1998 Jeff Law (law@cygnus.com) -Fri May 26 17:01:22 1995 Paul Eggert + * version.c: Bump for snapshot. - * fixincludes: Fix bogus recursive in NEWS-OS 4.0C. +Mon May 25 11:56:24 PDT 1998 Jeff Law (law@cygnus.com) -Fri May 26 08:02:14 1995 Michael Meissner (meissner@cygnus.com) + * version.c: Bump for snapshot. - * c-typeck.c (initializer_constant_valid_p): For the CONSTRUCTOR - case, if the type is a record, recurse, just like for unions. +Mon May 25 14:00:13 1998 Dave Brolley -Thu May 25 07:56:14 1995 Paul Eggert + * 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. - * fixincludes: Add `sel', `tahoe', `r3000', `r4000' to the - list of pre-ANSI symbols that need to be surrounded with __ __. - Allow white space between `#' and `if' when looking for lines to patch. +Sun May 24 20:36:15 PDT 1998 Jeff Law (law@cygnus.com) - * objc/sarray.h (PRECOMPUTE_SELECTORS, struct soffset): - Use #ifdef __sparc__, not sparc. + * version.c: Bump for snapshot. - * m68k.md (addsi_lshrsi_31, ashldi_const, ashrdi_const, lshrdi_const): - Replace `mov' with `move'. +Sun May 24 02:08:57 PDT 1998 Jeff Law (law@cygnus.com) -Thu May 25 07:35:37 1995 Allen Briggs + * version.c: Bump for snapshot. - * libgcc2.c (L_eh, i386): Remove in-line comments in assembly - code--the '#' character is not valid for the SYSV as. - -Thu May 25 07:28:54 1995 Pat Rankin (rankin@eql.caltech.edu) +1998-05-24 Andreas Schwab - * Makefile.in (BC_ALL): Restore it from May 22 change; vms uses it. - (STAGESTUFF): Use it. + * 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. -Thu May 25 07:11:56 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - * alpha.c (alpha_emit_set_const): Don't call expand_binop for - other than add if SImode and can't create pseudos. +Sat May 23 23:44:53 1998 Alexandre Oliva -Wed May 24 21:38:24 1995 Jim Wilson + * Makefile.in (boostrap2-lean, bootstrap3-lean, + bootstrap4-lean): New targets. - * sched.c (reemit_notes): New function. - (schedule_block): Call reemit_notes twice. Reorganize code for - handling SCHED_GROUP_P insns, so that reemit_notes works. +Sat May 23 23:35:14 1998 Jeffrey A Law (law@cygnus.com) - * sh/sh.c (shiftcosts, genshifty_op): Add SH3 support. - * sh/sh.md (ashlsi3, lshrsi3): Add SH3 support. - (ashlsi3_d, ashrsi3_d, lshrsi3_d): New patterns for SH3. - (ashrsi2_31): Remove r/!r constraint. + * warn_summary, test_summary: Moved into the contrib directory. -Wed May 24 17:00:47 1995 Jason Merrill +1998-05-23 Manfred Hollstein - * tree.c (type_list_equal): Call simple_cst_equal before checking - types. + * 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. -Wed May 24 16:49:49 1995 Douglas Rupp (drupp@cs.washington.edu) + * Makefile.in (all.cross): Swap $(LIBGCC) and $(STMP_FIXPROTO). + (rest.encap): Likewise. + (libgcc2.ready): Depend upon $(STMP_FIXPROTO) - * Makefile.in (libgcc2.a): Handle case of separate srcdir. + * toplev.h (tree_node): Provide global declaration to avoid + `limited scope' warnings. -Wed May 24 16:22:01 1995 Paul Eggert +Sat May 23 23:23:35 1998 Robert Lipe - * configure: Define $(MAKE) if `make' doesn't. + * test_summary: Display section breaks for each entry + in a multilibbed target's output. -Wed May 24 15:50:51 1995 Doug Evans +1998-05-23 Richard Henderson - * dsp16xx.h (CROSS_LINK_SPEC): ENDFILE_SPEC moved to -nostartfiles. - * i386/freebsd.h (LINK_SPEC): Don't pass "-e start" if nostartfiles - rather than nostdlib. - * i386/sun.h (LINK_SPEC): Likewise. - * m68k/sun2o4.h (LINK_SPEC): Likewise. - * m68k/sun3.h (LINK_SPEC): Likewise. - * m68k/vxm68k.h (LINK_SPEC): Likewise. - * mips/netbsd.h (LINK_SPEC): Likewise. - * config/netbsd.h (LINK_SPEC): Likewise. - * rs6000/mach.h (LINK_SPEC): Likewise. - * sparc.h (LINK_SPEC): Likewise. - * sparc/vxsparc.h (LINK_SPEC): Likewise. + * expr.c (expand_expr): For {BITFIELD,COMPONENT,ARRAY}_REF, if the + offset's mode is not ptr_mode, convert it. - * m88k/m88k.h (FUNCTION_ARG_BOUNDARY): Use GET_MODE_BITSIZE. +1998-05-22 Jason Merrill -Wed May 24 15:44:04 1995 Jason Merrill + * fold-const.c (ssize_binop): New fn. + * tree.h: Declare it. - * fold-const.c (fold): Make sure that a folded TRUTH_NOT_EXPR - retains the same type. +Fri May 22 03:42:05 1998 Richard Earnshaw (rearnsha@arm.com) - * c-common.c (truthvalue_conversion): Also accept TRUTH_NOT_EXPR. + * genextract.c (print_path): Handle zero-length path as a special + case. -Wed May 24 15:41:51 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Fri May 22 01:38:07 1998 Hans-Peter Nilsson - * cplus-dem.c (strstr, strncmp, strlen): Remove declarations. + * cplus-dem.c (MBUF_SIZE): Bumped from 512 to 32767. - * tree.c (type_list_equal, simple_cst_list_equal, index_type_equal): - Check for simple_cst_equal return value of -1. +Fri May 22 00:57:00 1998 Bernd Schmidt (crux@pool.informatik.rwth-aachen.de> -Wed May 24 10:05:24 1995 Michael Meissner + * 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). - * libgcc1-test.c (start, _start): Provide declarations, so that - the GNU linker doesn't give a warning message about defaulting the - start address. +Thu May 21 19:50:13 1998 J"orn Rennecke - * rs6000/sysv4.h (STRIP_NAME_ENCODING): Redefine back to the - original defination, rather than the defination used in rs6000.h. - (ASM_OUTPUT_SOURCE_LINE): Use STRIP_NAME_ENCODING. - * rs6000.h (STRIP_NAME_ENCODING): Skip leading '*'. + * regmove.c (gen_add3_insn): New function. + (fixup_match_2): Use it instead of calling gen_addsi3. - * rs6000.h (MASK_STRING_SET, TARGET_STRING_SET): Add target - flags bit for whether -mstring was actually used. - (TARGET_SWITCHES): Add MASK_STRING to all power targets. Set - MASK_STRING_SET for -mstring and -mno-string. - (TARGET_DEFAULT): Add MASK_STRING. +Thu May 21 23:09:50 1998 Jeffrey A Law (law@cygnus.com) - * rs6000.c (rs6000_override_options): Add MASK_STRING to - all power targets. Make an explicit -mstring/-mno-string override - the -mcpu=processor default. + * Makefile.in (gencheck): Depend on HOST_LIBDEPS. - * rs6000/eabile.h (CPP_SPEC): Copy from sysvle.h to provide the - appropriate little endian defaults. + * alias.c (rtx_equal_for_memref_p): Handle SCRATCH as a memory + address. - * rs6000/sysv4.h (ASM_OUTPUT_SOURCE_LINE): Use assemble_name to - output the canonical name. +Thu May 21 20:18:13 1998 Martin von Loewis -Wed May 24 01:21:15 1995 Jason Merrill + * 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. - * rs6000.h (STRIP_NAME_ENCODING): Define. - (RS6000_OUTPUT_BASENAME): Use it. +Wed May 20 23:44:28 EDT 1998 John Wehle (john@feith.com) -Tue May 23 19:54:21 1995 Doug Evans + * 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. - * gcc.c (link_command_spec): Move ENDFILE_SPEC from -nostdlib - to -nostartfiles. +1998-05-21 Mark Mitchell -Tue May 23 17:01:50 1995 Jim Wilson + * cplus-dem.c (do_type): Handle volatile qualification. - * alpha.md (negsi2-2): Change output pattern to #. +Thu May 21 12:23:17 1998 Per Bothner - * mips.c (embedded_pic_offset): Output RTL to initialize - embedded_pic_fnaddr_rtx. - (mips_finalize_pic): Delete. - * mips.h (mips_finalize_pic): Delete declaration. - (FINALIZE_PIC): Delete. - (INIT_EXPANDERS): Clear embedded_pic_fnaddr_rtx. - * mips.md (get_fnaddr): Add = to output contraint. + * function.c (init_function_start): Don't call emit_line_note if + lineno is 0. (Can happen when compiling Java .class files.) - * sh.c (shift_amounts): Correct entry for shifts by 29. - * sh.md (sett): New pattern. - (movsi_i): Change source constraint for move to T reg to be 'z'. - - * mips/ecoff.h (STARTFILE_SPEC): Define to null string. - * mips/elfl.h, mips/elfl64.h: Correct typo in comment. - - * mips/elflorion.h, mips/elforion.h (MIPS_CPU_DEFAULT): Delete. - * mips.c (override_options): Delete #ifdef MIPS_CPU_DEFAULT code. - Add #ifdef MIPS_CPU_DEFAULT_STRING code before the first - mips_cpu_string test. - -Tue May 23 07:22:36 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * romp.c (hash_rtx): Avoid warning on int-to-pointer conversion. - (output_fpops): Cast args to bcopy to char *. - - * cpplib.c (initialize_builtins): Add missing parm to timestamp call. - - * Makefile.in (install-libobjc): Don't depend on libobjc.a. - - * c-parse.in: Objc shift/reduce conflicts now 48. - (parm): Use setspecs/restore here. - (parmlist_or_identifiers): Not here. - -Mon May 22 19:30:30 1995 Doug Evans - - * h8300.md (movsf_h8300h): Add missing post-inc case to constraints. - -Mon May 22 14:38:36 1995 Michael Meissner - - * rs6000.c (rs6000_override_options): Do SUBTARGET_OVERRIDE_OPTIONS - here. - * rs6000.h (OVERRIDE_OPTIONS): Not here. - - * rs6000.c (expand_block_move): Handle moves without string - instructions by generating a series of loads and stores. - (output_prolog): Support -mno-toc on V.4 and eabi systems. - - * rs6000/sysv4.h (TARGET_SWITCHES): Add -mtoc and -mno-toc. - (SUBTARGET_OVERRIDE_OPTIONS): Add some warnings for incompatible - switches. - (TOC_SECTION_FUNCTION): Make -mno-toc like -mrelocatable in that - we don't put the minimal toc pointer in the global toc section. - (LINK_SPEC): Use -oformat to set link output format, not -m. - - * rs6000/t-eabigas (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Build - libgcc.a variants with -mno-toc support. - * rs6000/t-ppcgas (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Ditto. - -Mon May 22 07:10:52 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * cplus-dem.c (mystrstr): Replacement for strstr. - - * configure: Split up long sed command. - * Makefile.in (SYMLINK): Deleted; unused. - (oldobjext): Deleted; no longer used. - (FLAGS_TO_PASS): Include objext and exeext. - (STAGESTUFF, protoize.o, unprotoize.o): Use $(objext), not .o. - (test_protoize_simple, compare{,3}, gnucompare{,3}): Likewise. - (STAGESTUFF, specs, gcc-cross, collect2): Add missing $(exeext). - (libgcc1.null, libgcc[12].a, stage[1-4]): Likewise. - (xgcc, cc1, cc1obj, enquire): Use $@ instead of filename for -o value. - (collect2, mips-tfile, mips-tdump, gen*): Likewise. - (bi-arity, bi-opcode, bi-opname, cccp, cppmain): Likewise. - (protoize, unprotoize, gen-protos, fix-header): Likewise. - (crtbegin.o, crtend.o): Don't use -o; move output to proper - filename (using objext) instead. - (BI_ALL, BC_ALL, bytecode): Deleted; unused. - (bi-*.o, cexp.o, stamp-{proto,fixinc}): Remove unneeded $(srcdir). - (getopt{,1}.o, SYSCALLS.c.X): Likewise. - (install-driver): New target. - (install-normal): Depend on it. - (install-common): Don't depend on xgcc. - (maketest): Deleted; no longer used. - (stage[1-4]): Use name collect-ld, not real-ld. - (risky-stage[1-4]): Use stage[1-4] as dependencies; don't copy. - * alpha/config-nt.bat, i386/config-nt.bat: Make {,h,t}config.h - and tm.h by writing a single #include line. - Update way specs.h and options.h are written. - * alpha/config-nt.sed, i386/config-nt.sed: Set new variables - into Makefile. - Build winnt.obj. - Edit CCCP definition. - * alpha/x-winnt, i386/x-winnt (oldobjext): Deleted. - Add rules for .c.obj, .adb.obj, and .ads.obj. - (LIB2FUNCS_EXTRA, spawnv.o): New rules. - * i386/x-winnt (objext): Now .obj, not .o. - - * gcc.c (HAVE_OBJECT_SUFFIX): New macro. - (process_command): Convert x.o to x.foo for OBJECT_SUFFIX of ".foo". - (do_spec_1): Avoid shadow variable "i" and always use for loop var. - - * c-decl.c (finish_decl_top_level): Removed; no longer used. - * objc-act.c: Numerous formatting changes. - (NULLT): Deleted; all uses changed to NULL_TREE. - (get_{static,object}_reference, objc_add_static_instance): - Use push_obstacks instead of saving obstacks manually. - (build_{selector,class}_reference_decl): Likewise. - (build_objc_string_decl, build_protocol_reference): Likewise. - (comp_{method,proto}_with_proto): Likewise. - (create_builtin_decl, synth_module_prologue): Set DECL_ARTIFICIAL - for internal objects. - (build_{selector,class}_reference_decl, add_objc_decls): Likewise. - (generate_objc_symtab_decl, build_module_descriptor): Likewise. - (build_protocol_reference): Likewise. - (build_objc_string_decl, synch_forward_declarations): Likewise. - Delete call to end_temporary_allocation. - (generate_static_references, generate_strings): Likewise. - (build_selector_translation_table, generate_category): Likewise. - (generate_{ivars,protocol}_list, build_protocol_reference): Likewise. - (build_objc_string_object): If next_runtime, put everything in - permanent obstack. - (objc_add_static_instance): Use build_decl instead of start_decl - and finish_decl_top_level. - (build_{class_reference,objc_string}_decl): Clear DECL_CONTEXT. - (start_class): Exit with FATAL_EXIT_CODE, not 1. - (add_objc_decls): Don't set DECL_IN_SYSTEM_HEADER. - - * tree.c (valid_machine_attribute): Handle attribute on - pointer-to-function types. - -Sun May 21 17:16:37 1995 J. T. Conklin - - * mips/netbsd.h (HAVE_STRERROR): Remove. - * mips/xm-netbsd.h: New file. - * mips/t-mips-netbsd: Deleted. - * configure (mips-dec-netbsd): Use xm-netbsd.h and t-libc-ok. - -Sun May 21 17:16:37 1995 Arne H. Juul (arnej@pvv.unit.no) - - * mips/netbsd.h: Use __start as entry point. Ifdef some - paths on CROSS_COMPILE. - -Sun May 21 08:39:26 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * c-parse.in (datadef, fndef, ivar_decl, mydecls): - Restore declspec_stack since setspecs is used. - (parmlist_or_identifiers): Use setspecs before parsing parms - and restore after parsing parms. - -Sun May 21 01:04:52 1995 Jeffrey A. Law - - * pa.c (hppa_encode_label): New variable "permanent" to - where/how memory is allocated for the new label. All - callers changed. - -Sat May 20 16:53:30 1995 Mike Meissner - - * rs6000.md (insv, extz): Fail if the structure is QI or HI reg to - avoid paradoxical subreg's being created in RTL phase, which uses - SImode to load from memory if structure is later moved to stack. - -Sat May 20 06:44:59 1995 Philippe De Muyter (phdm@info.ucl.ac.be) - - * m68k.md (udivmodhi4): Output "divu" instead of "divs". - -Sat May 20 06:11:32 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * reload.c (push_reload): Don't reload inside a SUBREG - when SUBREG_WORD is nonzero. - - * c-decl.c (shadow_tag_warned): Don't warn about useless keyword - if in system header file. - - * tree.c (simple_cst_equal): Don't look at language-specific - nodes since we don't know what's in them. - - * cpperror.c: #include config.h before any other .h file. - * collect2.c: Likewise. +Thu May 21 19:50:13 1998 J"orn Rennecke - * i386/config-nt.bat: Add missing ^M on two lines. - Add case for Fortran; fix typo in Ada case. - * alpha/config-nt.bat: Add case for Fortran; fix typo in Ada case. + * reload1.c (reload_reg_free_for_value_p): Fix RELOAD_FOR_INPUT + end of lifetime and RELOAD_FOR_OUTPUT start of lifetime. - * m68k/t-next (LIBGCC1, CROSS_LIBGCC1): Make not, not "libgcc1.null". - (OTHER_FIXINCLUDES_DIRS, LIMITS_H_TEST): Delete from here. - * m68k/x-next (OTHER_FIXINCLUDES_DIR, LIMITS_H_TEST): Move to here. +Thu May 21 19:32:27 1998 J"orn Rennecke -Fri May 19 19:30:20 1995 Stan Cox (gcc@dg-rtp.dg.com) + * combine.c (nonzero_bits): For paradoxical subregs, take + LOAD_EXTENDED_OP into account. - * crtstuff.c: Added reference to INIT_SECTION_PREAMBLE for systems that - do something which must be undone prior to __do_global_ctors. +Thu May 21 11:51:15 1998 Dave Brolley -Fri May 19 19:27:08 1995 Alan Modra + * configure.in (extra_c_objs): add prefix.o. + (extra_cxx_objs): extra objects for C++ with cpplib. + * configure: Regenerate. - * i386/linux-aout.h (CPP_SPEC): Add defines for -fPIC. - * i386/linux-oldld.h (CPP_SPEC): Likewise. + * c-tree.h: (get_directive_line): Different prototype for cpplib. + (GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line. -Fri May 19 17:46:28 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * c-lex.h: (get_directive_line): Not needed here for cpplib. - * collect2.c (strstr): Deleted. - * cplus-dem.c (strstr): Define ifndef POSIX. + * 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 May 19 11:16:51 1995 Per Bothner + * 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 - * cpplib.c (collect_expansion): Don't escape '@' inside string. +Thu May 21 09:04:42 1998 Kaveh R. Ghazi -Fri May 19 06:59:21 1995 Pat Rankin (rankin@eql.caltech.edu) + * gengenrtl.c (type_from_format, accessor_from_format): Change + type of parameter `c' from `char' to `int'. - * vmsconfig.com (process_objc_lib, configure_makefile): New routines. - (bc_all.list, ./vax.md, objc-objs.opt, objc-hdrs.list): New files - created at config time. - (bc_all.opt, ./md.): No longer created. - * make-cc1.com: Handle revised filenames from vmsconfig.com; - (DO_OBJCLIB): New variable, plus code to compile objc/*.{c,m}. +Wed May 20 22:28:34 1998 Jeffrey A Law (law@cygnus.com) -Wed May 17 16:15:31 1995 Torbjorn Granlund + * warn_summary, test_summary: New scripts from + Kaveh Ghazi and Alexandre Oliva respectively. - * i960.c (i960_output_ldconst): New code for XFmode. - Also, move SFmode code to immediately after DFmode code. - (S_MODES, D_MODES): Handle XFmode. - (XF_MODES): Was TF_MODES, handle XFmode instead of TFmode. - (hard_regno_mode_ok): Replace TFmode with XFmode. - (i960_output_long_double): New function. + * gcse.c (current_function_calls_longjmp): Declare. - * i960.h (DATA_ALIGNMENT): Define. - (ROUND_TYPE_ALIGN): Align XFmode scalars at 128 bit boundaries. - (ROUND_TYPE_SIZE): Round up the size of XFmode objects to 128 bits. - (CONST_DOUBLE_OK_FOR_LETTER_P): Use CONST0_RTX and CONST1_RTX - so that all FP modes are recognized. - (ASM_OUTPUT_LONG_DOUBLE): Define. +1998-05-20 Jason Merrill - * i960.md: Change all TFmode patterns to have XFmode. - (movxf recognizer, frame version): Use movt, ldt, and stt. - (movxf recognizer, non-frame version): Delete. - (extenddfxf2): Delete * before f constraint. - (extendsfxf2): Likewise. + * dwarf2out.c (base_type_die): Use int_size_in_bytes. -Wed May 17 17:53:35 1995 Jim Wilson +Wed May 20 01:11:02 1998 Doug Evans (devans@cygnus.com) + Jeff Law (law@cygnus.com) - * unroll.c (unroll_loop): Increment copy_start_luid if copy_start - is loop_start. + * 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. -Wed May 17 17:44:57 1995 Lee Iverson +Tue May 19 22:31:20 1998 Jeffrey A Law (law@cygnus.com) - * fold-const.c (invert_truthvalue, case CLEANUP_POINT_EXPR): New case. + * 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. -Tue May 16 18:51:16 1995 Michael Meissner +Tue May 19 19:08:52 1998 Jim Wilson - * rs6000/rs6000.h (TARGET_SWITCHES): Add -mstring to enable string - instructions, and -mno-string to disable them. - (MOVE_MAX): Don't test TARGET_MULTIPLE anymore. - (MAX_MOVE_MAX): Set to 8, not 16. - (expand_block_move): Add declaration. + * config/mips/mips.c (double_memory_operand): Accept any MEM during + reload when TARGET_64BIT. - * rs6000/rs6000.c (expand_block_move): New function to expand - block moves when -mstring is used. +Tue May 19 18:21:25 1998 Jim Wilson - * rs6000/rs6000.md (movti): Use TARGET_STRING, not TARGET_MULTIPLE. - (load_multiple, store_multiple): Ditto. - (string insns): Add 8, 6, 4, 2, and 1 register variants for using - the native string instructions if -mstring. + 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. - * rs6000/sysv4.h (CPP_SPEC): If little endian, define - _LITTLE_ENDIAN and set littleendian assertion. If big endian, - define _BIG_ENDIAN and set bigendian assertion. - * rs6000/sysv4le.h (CPP_SPEC): Copy from sysv4.h, and change - default to little endian. +1998-05-19 Jim Wilson - * rs6000/rs6000.c (override_options): Check for -mmultiple and - -mstring on little endian systems here. - * rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Don't do the check - here. + * dwarfout.c (dwarfout_file_scope_decl, case TYPE_DECL): Ignore + LANG_TYPE trees with DECL_SOURCE_LINE of 0. -Tue May 16 18:36:41 1995 Douglas Rupp (drupp@cs.washington.edu) +Tue May 19 15:07:54 1998 Todd Vierling - * alpha.c: Changed WINNT to _WIN32. - * alpha/config-nt.bat, i386/config-nt.bat: Added commands to - generate specs.h and options.h. - * i386/config-nt.sed: Changed link32 to link. - * winnt/ld.c (main): Removed call to free. - * configure.bat: Added line to echo usage on invalid input. - * gcc.c (fix_argv): Removed call to free. - * gcc.c, getpwd.c, protoize.c, sdbout.c: Changed WINNT to _WIN32. - * toplev.c: Likewise. + * arm/netbsd.h: Ensure DWARF2_UNWIND_INFO is undefined. -Tue May 16 18:04:47 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue May 19 17:19:16 1998 J"orn Rennecke - * toplev.c (pfatal_with_name, fatal_io_error, vfatal): - Use FATAL_EXIT_CODE instead of magic number. - * cccp.c, cpplib.c, cpplib.h: Use FATAL_EXIT_CODE instead - of FAILURE_EXIT_CODE. - * fix-header.c, gen-protos.c: Likewise. - * cpperror.c, cppmain.c: Likewise. - Include config.h #ifndef EMACS. - * xm-alpha.h, xm-rs6000.h, xm-vms.h (FAILURE_EXIT_CODE): Remove. + * reload1.c (reload_reg_free_for_value_p): New function. + (allocate_reload_reg, choose_reload_regs): Use it. -Tue May 16 17:46:57 1995 Adam Fedor +Tue May 19 11:51:00 EDT 1998 Andrew MacLeod (amacleod@cygnus.com) - * objc/archive.c (__objc_write_class): Write class version. - (__objc_write_selector, objc_{write,read}_selector): Handle null - selector. + * except.c (expand_start_catch): Correct logic for when to + generate a new handler label, and when to use the old one. - * objc/sarray.h (struct sarray): Make capacity size_t. - * objc/sarray.c (sarray_realloc): Make array index variables size_t. +Tue May 19 11:08:52 1998 Kaveh R. Ghazi -Tue May 16 06:59:08 1995 Paul Eggert + * 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. + + * basic-block.h (free_regset_vector): Add prototype. + + * 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. - * dsp16xx.c (print_operand_address): Fix misspellings in messages. - * i370/mvs.h (FUNCTION_PROFILER): Likewise. - * mips-tdump.c (type_to_string): Likewise. - * print-tree.c (print_node): 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'. + + * sparc.h (order_regs_for_local_alloc, eligible_for_return_delay, + sparc_issue_rate, v8plus_regcmp_p): Add prototypes. + + * sparc.md (cmpdi_v8plus): Add abort for default case in switch. + + * cppalloc.c: Include gansidecl.h. + + * 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'. + + * 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. + + * except.c (output_exception_table_entry): Remove unused variable + `eh_entry'. - * protoize.c (edit_fn_definition): Fix mispelled local `have_flotsam'. + * except.h (expand_fixup_region_start, expand_fixup_region_end): + Add prototypes. + + * expr.c (do_jump_by_parts_equality_rtx): Remove prototype. + + * expr.h (do_jump_by_parts_equality_rtx): Add prototype. + + * 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'. + + * flow.c (free_regset_vector): Remove redundant prototype. + + * 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). + + * gansidecl.h (ATTRIBUTE_PRINTF_4, ATTRIBUTE_PRINTF_5): New macros. + + * gen-protos.c: Include gansidecl.h. + (hashf): Don't make it static, constify parameter `name'. + + * genattrtab.c (check_attr_test): Change XEXP() to XSTR() to match + specifier %s in calls to function `fatal'. + + * haifa-sched.c: Include toplev.h. + (find_rgns): Remove unused variable `j'. + + * integrate.c (note_modified_parmregs): Mark parameter `x' with + ATTRIBUTE_UNUSED. + (mark_stores): Likewise. + + * jump.c (mark_modified_reg): Likewise. + + * output.h (insn_current_reference_address): Add prototype. + (eh_frame_section): Likewise. + + * print-rtl.c: Include bitmap.h. + + * 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. - * objc/sendmsg.c (__objc_init_install_dtable): Fix misspelling - in name of local label `already_initialized'. + * rtl.h (expand_null_return, reg_classes_intersect_p): Add prototype. + (mark_elimination): Fix typo in prototype. - * winnt/winnt.h (STDC_VALUE): Was misspelled. + * scan-decls.c: Include gansidecl.h. - * m68k/ccur-GAS.h (FUNCTION_BOUNDARY): Was misspelled. + * tree.h (using_eh_for_cleanups, supports_one_only): Add prototype. - * 1750a.h (DEFAULT_PCC_STRUCT_RETURN): Was misspelled. +Mon May 18 22:37:33 1998 Jeffrey A Law (law@cygnus.com) -Mon May 15 23:41:25 1995 Jeffrey A. Law + * function.c (identify_blocks): Fix thinko when setting the + block number for NOTE_INSN_BLOCK_END. - * pa.h (ASM_OUTPUT_EXTERNAL_LIBCALL): Make sure to encode section - info for all libcalls. +Mon May 18 15:30:42 1998 Nick Clifton -Mon May 15 20:58:00 1995 Jason Merrill + * config/v850/lib1funcs.asm: Add .text pseudo op to start of + ___udivsi3. - * collect2.c (strstr): Define ifndef POSIX. + * config/v850/lib1funcs.asm: Fix .size pseudo ops to use three + underscores for the prefixes to the names of the maths functions. - * defaults.h (SUPPORTS_WEAK): Provide default. - * aoutos.h, sparc/sunos4.h: Don't support weak symbols. - * netbsd.h, svr4.h, i386/freebsd.h, i386/osfrose.h, - m88k/m88k.h: Define ASM_WEAKEN_LABEL instead of WEAK_ASM_OP. - * c-pragma.h: Check ASM_WEAKEN_LABEL instead of WEAK_ASM_OP. - HANDLE_PRAGMA_WEAK is never defined in a tm.h file. - * c-decl.c (duplicate_decls): Propagate DECL_WEAK. - * tree.h (DECL_WEAK): New macro. - (tree_decl): Add weak_flag. - * varasm.c (assemble_start_function): Declare the symbol weak if - appropriate. - (assemble_variable): Ditto. - (assemble_alias): Ditto. Mark the decl as written. - (declare_weak): Check for weak declaration after definition. - Set DECL_WEAK. - (weak_finish): Use ASM_WEAKEN_LABEL. - * libgcc2.c: The C++ free-store management functions are weak - aliases on targets that always support them. + * dbxout.c (dbxout_parms): Revert to using DECL_ARG_TYPE. Add + comment explaining why. -Mon May 15 19:01:43 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Mon May 18 13:20:23 1998 Richard Henderson - * configure (out_object_file): New variable; put value in Makefile. - * Makefile.in (out_object_file): Use in place of aux-output.o. + * 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. - * fold-const.c (const_binop): Don't pass OVERFLOW to force_fit_type - if type is unsigned. +Mon May 18 12:07:37 1998 Richard Earnshaw (rearnsha@arm.com) -Mon May 15 18:48:26 1995 Paul Eggert + * stor-layout.c (layout_record): Fix off-by-one error when checking + length of the TYPE_BINFO vector. - * install.sh (transformbasename): Fix misspelling. +Mon May 18 10:59:23 1998 Nick Clifton - * tahoe.h (CHECK_FLOAT_VALUE): Fix misspelling of OVERFLOW parameter. + * dbxout.c (dbxout_parms): Use TREE_ARG to compute the type of a + function parameter passed in memory. - * i386.h (VALID_MACHINE_{DECL,TYPE_ATTRIBUTE): Fix typo. +Mon May 18 09:02:09 1998 Robert Lipe - * fx80.h (CHECK_FLOAT_VALUE): Fix misspelled use of parameter. + * 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. - * a29k.c (spec_reg_operand): Fix misspelling of `default:'. +Mon May 18 01:23:33 1998 Jeffrey A Law (law@cygnus.com) -Mon May 15 18:36:41 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * 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. - * m68k.md (b{eq,ne,ge,lt}0_di): Fixed for non-MOTOROLA syntax. - * m68k/xm-mot3300.h (alloca): Extern decl added for non-GNU compiler. + * 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. -Mon May 15 13:14:29 1995 Per Bothner + * output.h (find_basic_blocks): Declare. + (free_basic_block_vars, set_block_num, life_analysis): Likewise. - * cppexp.c (cpp_reader): Test for '#' (start of assertion) *after* - skipping hspace, not before. + * Makefile.in (BISON): Use bison from the build tree if it exists. + (FLEX): Similarly. -Mon May 15 08:13:54 1995 Pat Rankin (rankin@eql.caltech.edu) +Mon May 18 00:08:19 1998 Nick Clifton - * vmsconfig.com: Construct options.h and specs.h to #include - all "*/lang-{options|specs}.h" files found. + * 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. -Sun May 14 21:32:49 1995 Doug Evans + * tm.texi (SWITCH_CURTAILS_COMPILATION): Add description of new + driver macro. - * alpha/alpha.md (movsicc, case NE): Don't generate unrecognizable - insn. - (movdicc, case NE): Likewise. +Sun May 17 23:59:45 1998 John Wehle (john@feith.com) -Sun May 14 15:44:54 1995 Jim Wilson + * i386.h (ALIGN_DFmode): Delete. + (CONSTANT_ALIGNMENT): Define. + * varasm.c (force_const_mem): Use it. - * unroll.c (unroll_loop): Make local_regno have size - max_reg_before_loop. Don't do local register optimization if - copy_end has no INSN_LUID. +Sun May 17 19:31:05 1998 Richard Henderson -Sun May 14 10:38:23 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * alpha.c (alpha_emit_conditional_branch): Clear cmp_code after + using it with swap_condition, not before. - * objc-act.c (start_method_def): Mark _self as possibly unused. +Sun May 17 13:44:32 1998 Jim Wilson - * configure: Create specs.h and options.h from */lang-specs.h - and */lang-options.h. - Set lang_specs_files and lang_options_file variables in Makefile. - * Makefile.in (lang_{specs,options}_files): New variables. - (gcc.o): Depends on $(lang_specs_files). - (toplev.o): Depends on $(lang_options_file); merge two dep lists. - (distclean): Remove spes.h and options. - * gcc.c (default_compilers): Remove entries for Ada, C++, Chill, - and Fortran; #include specs.h instead. - * toplev.c (lang_options): Remove entries for Ada, C++, and Fortran; - include options.h instead. + * alias.c (mode_alias_check): Delete. + (true_dependence, anti_dependence, output_dependence): Revert April 21 + change. -Sat May 13 23:11:21 1995 DJ Delorie +Sun May 17 08:45:21 1998 Krister Walfridsson - * configure (i[345]86-go32-msdos, i[345]86-*-go32): New targets. + * toplev.c (output_lang_identify): Enable prototype and definition. -Sat May 13 10:58:38 1995 Jim Wilson +Sun May 17 01:12:27 PDT 1998 Jeff Law (law@cygnus.com) - * loop.c (record_giv): When computing replaceable, use - back_branch_in_range_p instead of looking for branches to named - labels. - * loop.h (back_branch_in_range_p): Declare. - * unroll.c (back_branch_in_range_p): No longer static. + * version.c: Bump for snapshot. -Sat May 13 06:47:11 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Sat May 16 23:20:32 1998 Richard Henderson - * combine.c (simplify_shift_count, case LSHIFTRT): Don't merge - shifts of different modes if first is any right shift. + * 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 . -Sat May 13 05:39:09 1995 Richard Earnshaw (rearnsha@armltd.co.uk) + * configure.in (alpha*-*-linux-*): Kill xm_defines. + (alpha*-*-linux-gnulibc1*) [fixincludes]: Define. + * alpha/xm-linux.h: Remove file. - * configure (arm-semi-aout): New configuration. - * config.sub: Add support for semi-hosted ARM. - * arm/t-semi, arm/semi.h: New files. +Sat May 16 18:32:45 1998 Doug Evans -Fri May 12 21:51:22 1995 Doug Evans + * dbxout.c (dbxout_parms): If mode of type of parameter living + in memory doesn't match mode of DECL_RTL, make big endian correction. - * flow.c (find_basic_blocks): Only perform n_basic_blocks sanity - check on first pass, and on second pass ensure it has the correct - value. +Fri May 15 21:40:06 1998 John Wehle (john@feith.com) -Fri May 12 19:23:11 1995 Jim Wilson - - * c-typeck.c (build_binary_op): Warn when ~unsigned is compared - against unsigned, and type promotions result in an unexpected - answer. - -Fri May 12 19:10:21 1995 Roland McGrath - - * configure (*-*-gnu*): Always use ELF; set tm_file=${cpu_type}/gnu.h. - * config/i386/gnu.h: Contents replaced with old i386/gnuelf.h. - * config/i386/gnuelf.h: File removed. - -Fri May 12 17:29:57 1995 Ken Raeburn (raeburn@cygnus.com) - - * m68k/lb1sf68.asm (__IMMEDIATE_PREFIX__): Default to #. - (IMM): New macro. - (all code): Use IMM macro instead of hardcoding # for immediate - operands. - -Fri May 12 16:52:10 1995 Philippe De Muyter (phdm@info.ucl.ac.be) - - * m68k.c (output_scc_di): New function. - (extend_operator) : Allow DImode target. - * m68k.h (HARD_REGNO_MODE_OK): Don't allow d7/a0 as DImode reg pair. - * m68k.md (tstdi, cmpdi, addsi_lshrsi_31, ashldi_extsi): New patterns. - (extendqidi2, extendhidi2, extendsidi2): Allow "general_operand" - instead of "register_operand" 0. - (adddid_sexthishl32, subdid_sexthishl32, subdi_dishl32): Likewise. - (adddi_dilshr32): Operand 0 constraint changed from "ro" to "do"; - Code generation fixed. - (adddi_mem, subdi_mem): Fixed for "<" and ">" operand 0. - (adddi3, subdi3): Operand 2 constraint changed from "ao" to "*ao" - (ashldi_sexthi, ashrdi_const32): Allow only "register_operand" - instead of "general_operand" 0. - (ash[lr]di_const, ash[lr]di3): Allow also 8 and 16 as shift count. - (subreg1ashrdi_const32): Pattern deleted. - (subreghi1ashrdi_const32, subregsi1ashrdi_const32): New pattern. - (lshrsi_31): New implementation. - (scc0_di, scc_di, beq0_di, bne0_di, bge0_di, blt0_di): New patterns. - -Fri May 12 16:50:49 1995 Jeffrey A. Law - - * pa.md (bb patterns): Fix bugs in length computation exposed by - recent branch shortening and genattrtab changes. - -Fri May 12 16:22:27 1995 Ken Raeburn - - * cccp.c (enum node_type): Add T_IMMEDIATE_PREFIX_TYPE. - (special_symbol): Handle it; emit value of IMMEDIATE_PREFIX. - (IMMEDIATE_PREFIX): Default to empty string. - (initialize_builtins): Install __IMMEDIATE_PREFIX__ builtin, - parallel to __REGISTER_PREFIX__. - -Fri May 12 14:40:03 1995 Pat Rankin (rankin@eql.caltech.edu) - - * cccp.c: #if VMS, don't define `stat' macro to be VMS_stat. - Compare enums explicitly to 0 to work around VAX C bug. - (do_include): Cast alloca's value. - - * make-cc1.com (bc_loop): Process comma-separated list rather - than space-separated one; restore .h suffix stripped by vmsconfig; - (loop1): More robust handling of directory prefix on file names. - * vmsconfig.com (TPU makefile.in): Reorganize and reformat code. - Make generated .opt files have more consistent format (all comma - separated, excess whitespace eliminated); - (additional_compiler): New routine. - (process_makefile): Use it to handle cc1plus via cp/Make-lang.in. - -Fri May 12 13:35:07 1995 Doug Evans - - * arm.h: Replace ARM_REG_PREFIX with REGISTER_PREFIX. - Replace ARM_COMMENT_CHAR with ASM_COMMENT_START. - (REGISTER_PREFIX): Define. - (USER_LABEL_PREFIX, LOCAL_LABEL_PREFIX): Define. - (SECONDARY_OUTPUT_RELOAD_CLASS): Handle DFmodes only if - TARGET_HARD_FLOAT. - (PREDICATE_CODES): Add soft_df_operand. - * arm.c: Replace ARM_REG_PREFIX with REGISTER_PREFIX. - Replace ARM_COMMENT_CHAR with ASM_COMMENT_START. - (arm_asm_output_label): Use USER_LABEL_PREFIX. - (soft_df_operand): New function. - * arm.md (movsicc): New pattern. - (movsfcc, movdfcc, *movsicc_insn, *movsfcc_hard_insn): Likewise. - (*movsfcc_soft_insn, *movdfcc_insn): Likewise. - (*movdf_soft_insn): Rewrite. - (movsi matcher): Fix typo in type attribute. - -Fri May 12 10:25:40 1995 Michael Meissner (meissner@cygnus.com) - - * i386.h (TARGET_RTD): Use MASK_RTD, not MASK_REGPARM. - (TARGET_SWITCHES): Add -m{,no-}align-double switch. - (TARGET_OPTIONS): Add -mregparm= switch to set number of registers - to use for passing arguments. Add -malign-loops= switch to set - the alignment for loops. Add -malign-jumps= switch to set the - alignment for code that is jumped to. Add -malign-functions= - switch to set the initial alignment of functions. - (TARGET_REGPARM): Delete, in favor of -mregparm= - (TARGET_SWITCHES): Delete -mregparm, add -mdebug-arg switches. - (RETURN_POPS_ARGS): Call i386_return_pops_args to do the real work. - (VALID_MACHINE_DECL_ATTRIBUTE): Define as function call. - (VALID_MACHINE_TYPE_ATTRIBUTE): Define as function call. - (COMP_TYPE_ATTRIBUTES): Define as function call. - (REGPARM_MAX): Maximum number of regs to use for passing arguments. - (CUMULATIVE_ARGS): Make this a structure, not an int. - (INIT_CUMULATIVE_ARGS, FUNCTION_ARG{,_ADVANCE}): Call function. - (FUNCTION_ARG_PARTIAL_NREGS): Likewise. - (MAX_CODE_ALIGN): Maximum value to align loops/jumps to. - (BIGGEST_ALIGNMENT): Return 64 if -malign-double, 32 otherwise. - (ASM_OUTPUT_ALIGN_CODE): Use value of -malign-jumps= switch. - (ASM_OUTPUT_LOOP_ALIGN): Use value of -malign-loops= switch. - (toplevel): Declare all new functions and external variables added - in i386.c. - - * i386.c (i386_regparm_string, i386_regparm): New variables - for -mregparm= switch to set the number of registers to use for - passing arguments. - (i386_align_loops_string, i386_align_loops): New variables for - -malign-loops= switch to set alignment to use for loops. - (i386_align_jumps_string, i386_align_jumps): New variables for - -malign-jumps= switch to set alignment to use for labels that are - jumped to. - (override_options): Support new switches. - (i386_valid_decl_attribute_p): New function to validate decl - specific attributes. Presently returns 0. - (i386_valid_type_attribute_p): New function to validate type - specific attributes. Recognize "stdcall", which says function - with fixed numbers of arguments is responsible for popping stack, - "cdecl", which says to use the normal C calling sequence, even if - -mrtd is used, and "regparm", which specifies the number of - registers to use for passing arguments. - (i386_comp_type_attributes): New function, to validate whether - attributes are compatible. - (i386_return_pops_args): New function, to return whether or not - the function pops its argument list or not, taking into account - -mrtd, and the stdcall/cdecl attributes. - (init_cumulative_args): Rewrite as a function, taking variable - argument functions, and regparm support into account. - (function_arg{,_advance,_partial_nreg}): Likewise. - (print_operand): Support %J, to print appropriate jump insn. - - * i386.md (decrement_and_branch_until_zero): Define pattern, - so that loops that count down to zero, don't have an unneeded - compare after the decrement. Add a general insn recognizer for - add to a value and compare against zero. - - * i386/go32.h, i386/winnt.h (VALID_MACHINE_DECL_ATTRIBUTE): - Delete, code folded into the mainline. - (RETURN_POPS_ARGS): Likewise. - - * i386/winnt.h (ENCODE_SECTION_INFO): The stdcall attribute is now - stored on the type field, rather than the decl. - - * i386/gas.h (ASM_OUTPUT_ALIGN_CODE, ASM_OUTPUT_LOOP_ALIGN): Use - i386_align_{loops,jumps} variables to do alignment. - * i386/osfrose.h, i386/svr3dbx.h: Likewise. - -Fri May 12 12:48:19 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * stor-layout.c (layout_type, case ARRAY_TYPE): Compute length using - MAX of length and zero if sizetype signed and neither bound constant. - - * i386/gnuelf.h, i386/linux-oldld.h, i386/lynx-ng.h, i386/v3gas.h: - Use <...> in #include instead of "...". - * m68k/lynx-ng.h, sparc/lynx-ng.h: Likewise. - - * c-parse.in (myparm): Handle attributes. - * objc-act.c (unused_list): New variable. - (build_tmp_function_decl): Call push_parm_decl with new format. - (start_class): Initialize unused_list. - (start_method_def): Call push_parm_decl with new format and - mark _cmp as possibly unused. - - * combine.c (simplify_shift_const): Don't change SHIFT_MODE - for LSHIFTRT either. - - * unroll.c (unroll_loop): Don't move reg if used in copy_end and - that is a JUMP_INSN. - -Fri May 12 12:31:37 1995 Doug Evans - - * arm/lib1funcs.asm: New file. - -Fri May 12 11:52:03 1995 Kung Hsu - - * configure (a29k-*-vxworks*): New target. - * config.sub (vxworks29k): New alias. - * a29k/t-vx29k: New file. - * a29k/vx29k.h: New file. + * i386.md (movdi-1, movdi): Rewrite based on SI move patterns. -Fri May 12 11:17:28 1995 Jim Wilson +Fri May 15 18:55:22 1998 Jason Merrill - * loop.c (check_dbra_loop): When reversing loop when - no_use_except_counting is false, there must be only one biv. + * tree.h (BINFO_SIZE, TYPE_BINFO_SIZE): New macros. + * stor-layout.c (layout_record): Set it. -Fri May 12 07:10:00 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Fri May 15 18:49:30 1998 Mark Mitchell - * unroll.c (unroll_loop): Only use local_regno for pseudos. + * toplev.c (rest_of_compilation): Don't defer nested functions. - * genattrtab.c (write_test_expr, case MATCH_DUP): Use operands[N] - instead of JUMP_LABEL (which may not be set). - (walk_attr_value, case MATCH_DUP): Set must_extract. +Fri May 15 17:42:52 1998 Bob Manson - * c-parse.in: Adjust number of shift/reduce conflicts. - (parm): Support attributes. - * c-decl.c (push_parm_decl): Pass any attributes to decl_attributes. + * config/rs6000/rs6000.c (rs6000_stack_info): Align the stack bottom + to an 8-byte boundary if info_ptr->fpmem_p. -Fri May 12 00:36:26 1995 Per Bothner +Fri May 15 17:36:11 1998 Bill Moyer - * cpplib.c (skip_quoted_string): Removed - no longer needed. - (skip_if_group): Use cpp_get_token instead of skip_quoted_string. + * loop.c (basic_induction_var): Added test preventing + CCmode parameter passed to convert_modes(). - * cpplib.h (struct cpp_reader): Remove start_line field. - Add multiline_string_line field. +Fri May 15 17:26:18 1998 Alexandre Petit-Bianco - * cpplib.c (cpp_error_with_line, cpp_warning_with_line, - cpp_pedwarn_with_line): Take extra column number parameter. - (macroexpand, cpp_get_token): Fix reporting of unterminated strings. - (line_for_error): Removed - no longer needed. + * 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. -Fri May 12 02:21:34 1995 Jim Wilson +Fri May 15 12:44:57 1998 Benjamin Kosnik - * mips/svr4-t.h (MD_STARTFILE_PREFIX, MD_EXEC_PREFIX, - STARTFILE_SPEC, LINK_SPEC): Define. - * configure (mips-tandem-sysv4): Use t-mips not t-svr4. + * stor-layout.c (set_sizetype): Set TYPE_NAME on bitsizetype. -Thu May 11 19:18:54 1995 Per Bothner +Fri May 15 07:20:03 1998 Mark Mitchell - * cpplib.c (line_for_error): Make it work; add extra parameter. - (skip_quoted_string, cpp_get_token): Update calls to line_for_error. - (macroexpand): Remember initial line so we can report it if the - call is unterminated. Also, simplify error logic slightly. - (do_include): Cast alloca return value, to avoid pcc warning. + * fold-const.c (constant_boolean_node): New function. + (fold): Use it. - * cppexp.c (parse_number): Cleanup some Cygnus crud for MPW. +Fri May 15 11:21:16 1998 J"orn Rennecke -Thu May 11 21:35:23 1995 Torbjorn Granlund + * 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. - From Moshier: - * i960.c (i960_output_ldconst): Let split_double handle DImode. - (i960_print_operand): Use REAL_VALUE_TO_DECIMAL for decimal strings. - (i960_output_double, i960_output_float): Likewise; also change arg - VALUE from `double' to `REAL_VALUE_TYPE'. +Fri May 15 01:47:37 1998 Jeffrey A Law (law@cygnus.com) -Thu May 11 21:09:25 1995 Per Bothner (bothner@wombat.gnu.ai.mit.edu) + * mips.c (print_operand, case 'x'): Use HOST_WIDE_INT_PRINT_HEX. - * cpperror.c (cpp_print_containing_files): Remove some - Cygnus-local stuff. +Fri May 15 01:42:45 1998 Mumit Khan -Thu May 11 21:06:47 1995 Doug Evans + * objc/Make-lang.in (OBJC_O): Add missing exeext. + (libobjc.a, runtime-info.h): Likewise. - * gcc.c (link_command_spec): Make -nostdlib no longer imply - -nostartfiles. +Fri May 15 01:29:39 1998 John Wehle (john@feith.com) -Thu May 11 18:48:57 1995 Paul Eggert + * i386.h (DATA_ALIGNMENT): Define. - * c-common.c (convert_and_check): Don't diagnose overflow in constant - expression merely because conversion overflowed. +Fri May 15 05:35:37 1998 J"orn Rennecke -Thu May 11 18:43:59 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * c-decl.c (grokdeclarator): Use PARM_FLAG to see if should - make PARM_DECL. - * c-parse.in (nested_function, notype_nested_function): - Allow old-style arg definitions (use xdecls). +Thu May 14 18:38:50 1998 Jim Wilson - * c-decl.c (finish_struct): Properly update DECL_PACKED. + * reload.c (find_reloads): Don't penalize SCRATCH output reload. -Thu May 11 15:24:15 1995 Jason Merrill +Thu May 14 15:10:30 1998 Jeffrey A Law (law@cygnus.com) - * fold-const.c (fold): Also fold CLEANUP_POINT_EXPRs into - TRUTH_*_EXPRs and into the first operand. - (operand_equal_for_comparison_p): Also make sure the second operand - is integral. + * Makefile.in (expr.o): Remove dependency on deleted modemap.def file. -Thu May 11 14:22:03 1995 Ted Lemon +Thu May 14 16:30:47 EDT 1998 Andrew MacLeod - * config/mips/netbsd.h: New file. - * config/mips/t-mips-netbsd: New file. - * config/mips/x-netbsd: New file. + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * i386.c (notice_update_cc, output_float_compare): Disable + TARGET_CMOVE support. + +Wed May 13 15:28:59 1998 Michael Meissner + Jeff Law + + * 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 + + * 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. + + * calls.c: Include output.h. + + * cccp.c (pipe_closed): Mark parameter `signo' with + ATTRIBUTE_UNUSED. + + * combine.c: Move inclusion of expr.h to after insn-config.h. + + * iris6.h (ASM_IDENTIFY_GCC, ASM_IDENTIFY_LANGUAGE): Don't define + as empty, rather define as ((void)0). + + * sparc.c (sparc_check_64): Add braces around ambiguous `else'. + Add parentheses around assignment used as truth value. + + * 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. + + * cppexp.c (right_shift): Mark parameter `pfile' with + ATTRIBUTE_UNUSED. - * configure (mips-dec-netbsd*): Add entry. + * cpphash.c (cpp_lookup): Likewise. + (cpp_hash_cleanup): Likewise. - * mips.h (LOCAL_LABEL_PREFIX, USER_LABEL_PREFIX): Define. - (PUT_SDB_BLOCK_START, PUT_SDB_BLOCK_END, ASM_OUTPUT_LABEL_REF, - ASM_OUTPUT_INTERNAL_LABEL, ASM_GENERATE_INTERNAL_LABEL, - ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT): Use them. + * 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. - * mips.c (mips_output_lineno): Use LOCAL_LABEL_PREFIX. + * cpplib.h (cpp_reader_init, cpp_options_init, cpp_start_read, + cpp_read_check_assertion, skip_rest_of_line): Add prototypes. -Thu May 11 14:22:03 1995 Stan Cox (gcc@dg-rtp.dg.com) + * crtstuff.c (force_to_data, __CTOR_LIST__, force_to_data, + __DTOR_END__, __FRAME_END__): Mark with ATTRIBUTE_UNUSED. - * dwarfout.c (output_decl): Don't output DIE for struct or union type - with no name or with ERROR_MARK for the fields. + * cse.c (cse_check_loop_start): Mark parameter `set' with + ATTRIBUTE_UNUSED. -Thu May 11 06:36:34 1995 Michael Meissner (meissner@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). - * flow.c (mark_used_regs): If a SUBREG does not have a REG in the - SUBREG_REG position, recursively call mark_used_regs, instead of - segfaulting. + * dwarf2out.c (gen_entry_point_die): Hide prototype and definition. -Thu May 11 06:44:34 1995 Pat Rankin (rankin@eql.caltech.edu) + * except.h (doing_eh): Provide prototype. - * expr.c (do_jump, case EQ_EXPR, NE_EXPR): Fix typo for complex. + * expr.c: Move inclusion of expr.h to after insn-config.h. -Wed May 10 12:34:46 1995 Michael Meissner + * final.c: Include reload.h. + (shorten_branches): Cast the first argument of bzero to char *. - * configure: Add support for the little endian variant of the - PowerPC System V.4 and Eabi targets. If the GNU assembler was not - specified, don't build libgcc.a variants on the PowerPC systems - that use -mrelocatable, -mlittle, and -mbig. + * fix-header.c (cpp_print_containing_files): Mark parameter + `pfile' with ATTRIBUTE_UNUSED. + (cpp_fatal): Likewise. - * genmultilib: For MULTILIB_MATCHES arguments, map question marks - into equal signs after spliting the left and right side of - equivalent options, to all support for options like: -mcpu=403. + * flow.c (find_basic_blocks_1): Cast the first argument of bzero + to char *. - * rs6000/rs6000.md (rs6000_immed_double_const): New function that - is like immed_double_const, except that it reverses the two words - in the constant if the target is little endian. + * 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. - * rs6000/rs6000.md (floatsidf2): Use rs6000_immed_double_const, - not immed_double_const. - (floatunssidf2): Ditto. + * genextract.c (main): When generating insn-extract.c, mark + variable `junk' with ATTRIBUTE_UNUSED. - * rs6000/rs6000.h: Add declarations for all functions in rs6000.c. + * gengenrtl.c (gencode): When generating genrtl.c, cast the first + argument of bzero to char*. - * rs6000/sysv4.h (TARGET_SWITCHES): Add -mlittle, -mlittle-endian, - -mbig, and -mbig-endian for bi-endian support. - (ASM_SPEC): Pass -mlittle/-mbig to the assembler if it was passed - to us. - (LINK_SPEC): If explicit little or big endian support was - requested, tell the GNU linker to use the appropriate target - format. + * integrate.c: Include toplev.h. - * rs6000/t-eabi (MULTILIB_*): Build libgcc.a variants for software - floating point. Remove mrelocatable libgcc.a variant. + * libgcc2.c: Wrap `struct exception_table' and + `find_exception_handler' in macro DWARF2_UNWIND_INFO. - * rs6000/t-eabigas: New file, cloned from t-eabi. Build - mrelocatable libgcc.a variant in addition to the other variants. + * objc/Make-lang.in (objc-act.o): Depend on toplev.h. - * rs6000/t-ppc: New file, for PowerPC System V.4 support without - the GNU assembler. + * 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'. - * rs6000/t-ppcgas: New file, for PowerPC System V.4 support with - the GNU assembler. + * output.h (declare_weak): Add prototype. + (decode_reg_name): Don't wrap with TREE_CODE macro. + (assemble_alias): Add prototype. - * rs6000/eabile.h: New file, little endian eabi config file. - * rs6000/sysv4le.h: New file, little endian V.4 config file. + * regclass.c: Include output.h. -Wed May 10 14:22:28 1995 Doug Evans + * reload.h (reloads_conflict): Add prototype. - * libgcc1-test.c (main_without__main): Renamed from `main'. - * Makefile.in (libgcc1-test): Tell the user to ignore warnings. + * rtl.h (print_rtl_single, mark_elimiation, reg_class_subset_p, + output_func_start_profiler): Add prototypes. - * configure: Support --enable-foo, --disable-foo. + * rtlanal.c (reg_set_p_1): Mark parameters `x' and `pat' with + ATTRIBUTE_UNUSED. -Wed May 10 10:34:00 1995 Lee Iverson + * scan-decls.c: Include scan.h. - * unroll.c: Add declarations of static functions. - (unroll_loop): Renumber regs local to loop for each unrolled iteration. + * scan.h (recognized_function, recognized_extern): Add prototypes. -Wed May 10 08:27:03 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * stmt.c: Include output.h. - * alpha.c (alpha_set_emit_const): Cleanups to work properly - when run on 32-bit host. + * 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. - * configure: Instead of symlinking tm.h and {h,t,}config.h, - make them files that #include the proper file; pass to Makefile. - Pass out_file and md_file to Makefile instead of making symlinks. - * Makefile.in (out_file, md_file, tm_file, {build,host}_xm_file): - New symbols, to be overridden by configure. - (insn-*): Use $(md_file), not md. - (aux-output.o): Use $(out_file), not aux-output.c. - ($(MD_FILE)): Rework to use new conventions. - (gen*.o, bi-*.o): Depend on $(build_xm_file), not hconfig.h. - (scan.o, fix-header.o, scan-decls.o): Likewise. - (distclean): Adjust files removed for new convention. + * toplev.h (count_error, strip_off_ending, error_for_asm, + warning_for_asm): Add prototypes. -Tue May 9 19:26:42 1995 Jason Merrill +Wed May 13 12:54:19 1998 Michael Meissner - * rs6000/rs6000.h (LIBGCC_SPEC): Do link with libgcc when -shared. + * toplev.c (rest_of_compilation): "Charge" final for any time + doing various cleanup operations after finishing compilation + of a function. - * Makefile.in (STAGESTUFF): Add underscore.c. - (underscore.c): Rename temporary files to begin with 'tmp-' so that - they will be removed by 'make mostlyclean'. + * flow.c (dump_flow_info): Also print number of sets and + whether or not the pseudo is a user variable. -Tue May 9 19:19:55 1995 Mike Stump + * 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. - * toplev.c (lang_options): Add new flag -ffor-scope. +Wed May 13 12:54:19 1998 Martin von Loewis -Tue May 9 19:11:47 1995 Lee Iverson (leei@ai.sri.com) + * acconfig.h (ENABLE_CHECKING): Undefine. + * configure.in (--enable-checking): New option. - * objc/init.c (objc_init_statics): Fix missing part of last change. +Wed May 13 08:52:08 1998 J"orn Rennecke -Tue May 9 18:25:34 1995 Richard Kenner + * 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. - * i386/gnu.h, i386/linux.h, i386/linux-aout.h, i386/lynx.h: - Use <...> in #include instead of "..." to avoid recursion. - * i386/netbsd.h, i386/xm-gnu.h, i386/xm-linux.h: Likewise. - * i386/xm-lynx.h, i386/xm-freebsd.h, i386/xm-netbsd.h: Likewise. - * m68k/lynx.h, m68k/netbsd.h, m68k/xm-lynx.h: Likewise. - * m68k/xm-netbsd.h, mips/gnu.h, ns32k/netbsd.h: Likewise. - * ns32k/xm-netbsd.h, rs6000/lynx.h, rs6000/xm-lynx.h: Likewise. - * sparc/lynx.h, sparc/netbsd.h, sparc/xm-lynx.h: Likewise. - * sparc/xm-netbsd.h, vax/netbsd.h, vax/xm-netbsd.h: Likewise. +Tue May 12 20:05:57 1998 Jim Wilson -Tue May 9 15:52:05 1995 Michael Meissner + * collect2.c (main): Ignore do_collecting when COLLECT_EXPORT_LIST. - * config.sub: Recognize powerpcle as the little endian varient of - the PowerPC. Recgonize ppc as a PowerPC variant, and ppcle as a - powerpcle variant. Convert pentium into i586, not i486. Add p5 - alias for i586. Map new x86 variants p6, k5, nexgen into i586 - temporarily. +Wed May 13 03:23:45 1998 J"orn Rennecke -Tue May 9 15:43:27 1995 Jason Merrill + * reload1.c (gen_reload): Create REG_EQUIV notes. - * rs6000/rs6000.h (LINK_SPEC, LIB_SPEC): Don't mess with libg - if -shared. - * rs6000/aix41ppc.h (LINK_SPEC): Ditto. +Tue May 12 22:21:07 1998 J"orn Rennecke - * rs6000/powerpc.h: Don't emit .extern directives. + * reload1.c (reload): Fix check for USEs to use code of pattern. + (choose_reload_regs): Remove dead variable use_insn. -Tue May 9 14:08:09 1995 Jim Wilson +Tue May 12 14:04:49 1998 Jeffrey A Law (law@cygnus.com) - * sh/lib1funcs.asm (__ashrsi3, __ashlsi3, __lshrsi3): Use .byte - instead of .word offsets in switch table. + * pa.h (DBX_CONTIN_LENGTH): Reduce to 3000 bytes. -Tue May 9 11:44:47 1995 Jeremy Bettis +Tue May 12 15:16:02 1998 Michael Meissner - * objc/sendmsg.c (__objc_send_initialize): Call superclass if object - does not implement +initialize. - -Tue May 9 02:44:16 1995 Jason Merrill + * 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. - * rs6000/xm-rs6000.h (COLLECT_EXPORT_LIST): Define if not - cross-compiling. - * rs6000/xm-mach.h: #undef COLLECT_EXPORT_LIST. - * rs6000/rs6000.h (COLLECT_SCAN_OBJECTS): Lose. +Tue May 12 10:27:54 1998 Klaus Kaempf - * collect2.c (collect_exit): Unlink export_file. - (prefix_from_string): Broken out from prefix_from_env. - (prefix_from_env): Call it. - (main): Under AIX, recognize -bE: and -bexport:, and don't - automatically export everything if we see one. Otherwise, scan the - objects individually and add all their symbols to an export file to be - passed to the linker. - (write_export_file): New function. - (scan_prog_file): Ignore symbols starting with '.' + * alpha/vms.h (COMMON_ASM_OP, ASM_OUTPUT_ALIGNED_COMMON): Define. - * c-common.c (declare_hidden_char_array): Mark decl artificial. +Tue May 12 11:44:14 1998 Gavin Koch -Mon May 8 18:13:57 1995 Adam Fedor + * config/mips/mips.h (ASM_OUTPUT_ALIGN): Remove trailing semi-colon. - * objc/init.c (_objc_load_callback): Add declaration. - (__objc_exec_class): Call _objc_load_callback after every Class - or Category is added. - * objc/objc-api.h (_objc_load_callback): Add declaration. +Tue May 12 11:38:31 1998 Gavin Koch -Mon May 8 17:56:28 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * config/mips/mips.md (dslot): Move after definition of "cpu" + attribute. Handle r3900 case. - * expr.c (expand_expr, case INDIRECT_REF): Set RTX_UNCHANGING_P - if both TREE_READONLY and TREE_STATIC set. +Tue May 12 10:21:36 1998 Kaveh R. Ghazi - * c-typeck.c (convert_for_assignment): Don't give errors about - adding const or volatile unless both sides point to functions. + * system.h: Define the STRINGIFY macro here. + * protoize.c: Not here. + * gengenrtl.c (DEF_RTL_EXPR): Use the STRINGIFY macro. -Mon May 8 11:48:23 1995 Michael Meissner +Tue May 12 00:47:33 1998 John Wehle (john@feith.com) - * configure: If ../ld/Makefile, symlink ../ld/ld.new to collect-ld, - not real-ld. Don't test for $use_collect2 any more. + * 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. -Sun May 7 17:52:23 1995 Jason Merrill +Mon May 11 19:57:58 1998 Jeffrey A Law (law@cygnus.com) - * calls.c (expand_call): Improve -Winline warnings. + * mips.c: Prototype static functions. -Sun May 7 17:28:27 1995 DJ Delorie (dj@delorie.com) +Mon May 11 17:43:03 1998 Jim Wilson - * configure.bat: Use "go32" instead of "msdos" for future expansion. + * regmove.c (fixup_match_2, find_matches, regmove_profitable): + Add explanatory comments. - * i386/go32.h: Add support for win32's stdcall functions. + * sparc.h (SPARC_INCOMING_INT_ARG_FIRST): Support TARGET_FLAT. - * configure.bat: Add ^M to end of each line. - * i386/config-nt.bat, alpha/config-nt.bat: Likewise. +Mon May 11 17:24:27 1998 Richard Henderson -Sun May 7 02:12:26 1995 Jason Merrill + * sparc.md (ffsdi2): Disable. Simplify the expression as well. - * tree.h (DECL_ARTIFICIAL): New macro. +Mon May 11 13:30:44 1998 Jim Wilson - * function.c (expand_function_end): Don't warn about unused - anonymous or artificial parms. + * varasm.c (make_decl_rtl): Disable April 1 change. -Fri May 5 18:41:22 1995 Jim Meyering (meyering@comco.com) +Mon May 11 09:14:41 1998 Richard Henderson - * configure: Fix typo in name of "maintainer-clean". + * configure.in (alpha-*-linux-gnu): Undo lossage from gcc2 merge. -Fri May 5 14:58:01 1995 Jeffrey A. Law +Mon May 11 08:24:18 1998 Richard Henderson - * pa.c (emit_move_sequence): Force problematical constants - into memory during the reload pass when generating PIC. + * 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. -Fri May 5 13:30:33 1995 Doug Evans +Mon May 11 09:33:10 1998 Kaveh R. Ghazi - * objc/NXConstStr.m: NXConstantString.h renamed to NXConststr.h. + * 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. -Fri May 5 07:10:15 1995 Stephen L Moshier (moshier@world.std.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'. - * real.c (emdnorm, toe64, etoe64): Significand of Intel long double - denormals is shifted down one bit. +Sun May 10 02:27:03 1998 Kaveh R. Ghazi -Fri May 5 07:04:12 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.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. - * c-typeck.c (process_init_element): Don't clear_momentary if - constructor_stack is not empty. +Sun May 10 01:21:43 1998 Jeffrey A Law (law@cygnus.com) - * objc/Makefile (SHELL): Now /bin/sh. + * genemit.c (output_add_clobbers): Removed unused variable 'i' from + generated fucntion. - * c-typeck.c (build_binary_op): Also warn about ordered - comparison of pointer with zero if -Wall. +Sat May 9 02:02:15 1998 Richard Henderson - * expr.c (do_jump, case EQ_EXPR, NE_EXPR): Properly compare complex. + * 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. -Thu May 4 18:01:25 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * machmode.h (COMPLEX_MODE_P): New macro. - * objc/Makefile: NXConstantString renamed to NXConstStr. - * objc/NXConstStr.m: Renamed from objc/NXConstantString.m. - * objc/NXConstStr.h: Renamed from objc/NXConstantString.h. +Sat May 9 01:53:23 1998 Richard Henderson -Thu May 4 17:38:21 1995 J.T. Conklin + * haifa-sched.c (print_exp): Fix typo. - * configure (vax-*-netbsd*): New configuration. - * vax/netbsd.h, vax/xm-netbsd.h: New files. +Fri May 8 21:48:50 PDT 1998 Jeff Law (law@cygnus.com) -Thu May 4 16:39:05 1995 Jason Merrill + * version.c: Bump for snapshot. - * collect2.c (main): Add check for 'collect-ld', just like - 'real-ld', except that old versions won't be looking for it in the - path. Don't look for 'real-ld' in the path anymore. Sigh. +Fri May 8 18:23:08 1998 Michael Meissner - * collect2.c: #include demangle.h and obstack.h. - (obstack_chunk_alloc): Define. - (obstack_chunk_free): Define. - (generic): Don't define. Don't use. - (main): Initialize obstacks and demangling. + * final.c (final_scan_insn): Call fatal_insn instead of abort if + we could not split an insn when required to. - * collect2.c (dump_file): Adjust space padding in output to - maintain tabulation with Solaris ld. Don't demangle if the - environment variable COLLECT_NO_DEMANGLE is set. + * 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. - * collect2.c (main): Redirect the output of the first link and - demangle it. Don't collect static c/dtors unless USE_COLLECT2 is - defined. Null-terminate the list of objects. - (dump_file): New function. - (file_exists): New function. - (collect_exit): Renamed from my_exit. Dump and remove the temporary - ld output file. - (collect_execute): Break out from fork_execute. Support redirection. - (fork_execute): Call it. - (fatal_perror, fatal, error): Make non-static. - (xcalloc, xmalloc): Don't use generic. - (xrealloc): Define. - (collect_wait): Break out for do_wait. Just return the exit status. - (do_wait): Call it. + * 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 + + * Makefile.in (genrtl.o): Depend on system.h. + * gengenrtl.c (gencode): When creating genrtl.c, have it + include system.h. - * collect2.c: Check SUNOS4_SHARED_LIBRARIES using #if, not #ifdef. +Fri May 8 10:57:33 1998 Andreas Schwab - * Makefile.in (collect2): Now uses cplus-dem.o and underscore.o. - (collect2.o): Pass MAYBE_USE_COLLECT2 to compile. - (underscore.c): Rules for creation. + * config/m68k/t-linux: Remove extra stuff already included in + config/t-linux. + +Fri May 8 09:53:24 Paul Eggert + + * fixinc.wrap: Renamed from fixinc.math. Put wrapper around + curses.h if it contains `typedef char bool;', as suggested by + Manfred Hollstein . + + * configure.in: Rename fixinc.math to fixinc.wrap. + +Thu May 7 19:26:34 1998 Jim Wilson + + * 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 + + * 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 + + * r6000/eabi.asm (__eabi): Restore LR in case __eabi is called + multiple times. + +Thu May 7 14:26:05 1998 Kaveh R. Ghazi + + * 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. - * cplus-dem.c, demangle.h: Copy from libiberty. + * vfprintf.c: New file. + * doprint.c: New file. -Thu May 4 14:12:35 1995 Jim Wilson +Thu May 7 10:18:41 1998 Jeffrey A Law (law@cygnus.com) - * sdbout.c (plain_type): Pass additional argument to plain_type_1. - (plain_type_1): New parameter level. Increment it when making - recursive calls. Force the type to void_type_mode before starting - a 7th level of recursion. + * 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. - * sh.c (general_movsrc_operand, general_movdst_operand): Delete - references to POST_DEC and PRE_INC. - * sh.h: Clean up whitespace, comments, etc. - (TARGET_SH, RTL_BIT, DT_BIT, C_BIT, R_BIT, TARGET_DUMP_RTL, - TARGET_DUMP_R, TARGET_CDUMP): Delete. - (TARGET_SWITCHES): Delete -mR, -mc, -mr options. - (CONST_DOUBLE_OK_FOR_LETTER_P): Delete 'G' contraint. - (FUNCTION_VALUE): Simplify. - (REG_OK_FOR_PRE_POST_P, IS_INDEX): Delete. - (BASE_REGISTER_RTX_P, INDEX_REGISTER_RTX_P): Rewrite to allow - SUBREGs. - (GO_IF_LEGITIMATE_INDEX): Delete unused REGNO argument. - (GO_IF_LEGITIMATE_ADDRESS): Use BASE_REGISTER_RTX_P instead of - REG_OK_FOR_PRE_POST_P. Don't accept PRE_INC or POST_DEC addresses. - (PREDICATE_CODES, PROMOTE_MODE): Define. +Thu May 7 10:55:59 1998 Andreas Schwab -Wed May 3 09:57:55 1995 Michael Meissner + * config/m68k/m68k.md (adddi3, subdi3): Properly negate the DImode + constant. - * rs6000/rs6000.md (non power abs insns): If not powerpc, use - sf/subfc instructions, not subf. +Wed May 6 22:32:37 CDT 1998 Robert Lipe -Wed May 3 08:49:06 1995 Alan Modra + * Makefile.in (dwarfout.o) Add toplev.h dependency. + * dwarfout.c, i386.c: Include toplev.h + * toplev.h: (pfatal_with_name) Add prototype. - * protoize.c (gen_aux_info_file): Use strerror #ifdef HAVE_STRERROR. +Wed May 6 19:02:29 1998 Jason Merrill -Wed May 3 01:06:01 1995 Jeffrey A. Law + * Makefile.in: Fix .SUFFIXES. - * pa.c (output_call): Fix typo/thinko in last change. - (output_function_epilogue): Align the data section before - emitting deferred plabels. +Wed May 6 19:31:32 1998 Alan Modra - From Torbjorn: - * pa.c (before functions): Declare deferred_plabels and - n_deferred_plabels. - (output_call): When generating pic, don't use LP and RP. Use 32 bit - plabel instead. - (output_function_epilogue): Output plabels accumulated in output_call. + * config/linux.h (ASM_COMMENT_START): Define as "#". + * config/linux-aout.h (ASM_COMMENT_START): Likewise. -Tue May 2 17:15:08 1995 Jeffrey A. Law +Wed May 6 15:51:39 1998 Jim Wilson - * pa.c (hppa_expand_epilogue): Fix thinko in last change. + * objc/Make-lang.h (objc-parse.o): Add toplev.h dependency. + * objc/objc-parse.y, objc/objc-parse.c: Regenerate. -Tue May 2 16:54:35 1995 Doug Evans + * 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. - * jump.c (jump_optimize, can_reach_end determination): A barrier can - follow the return insn. + * mips/mips.c (save_restore_insns): Change FRAME_POINTER_REGNUM to + HARD_FRAME_POINTER_REGNUM. -Tue May 2 12:39:55 1995 Mike Stump + * expr.c (target_temp_slot_level): Delete duplicate definition. - * fold-const.c (fold): Ensure that we don't alter the expression's - type when folding CLEANUP_POINT_EXPRs. +Wed May 6 16:46:01 1998 Jeffrey A Law (law@cygnus.com) -Tue May 2 13:36:08 1995 Michael Meissner + * 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. - * expmed.c (emit_store_flag): When creating store flag - instructions from simpler parts, such as XOR, ABS, etc. do not - reuse pseudo registers if expensive optimizations, instead create new - pseudos for each insn result. + * haifa-sched.c (print_value, case SUBREG): Fix typo. -Tue May 2 01:25:29 1995 Jeffrey A. Law + * i386.c (output_387_binary_op): Add some braces to avoid warnings. + * i386.h (REG_CLASS_CONTENTS): Similarly. - * pa.c (hppa_expand_epilogue): Correctly handle restore of %rp - for functions with a stack size of exactly 8kbytes and no frame - pointer. + * 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. -Mon May 1 19:27:08 1995 Jim Wilson + * haifa-sched.c (find_rgns): Correctly handle reducible loops with + inner loops which are not reducible. - * sdbout.c (sdbout_one_type): Don't switch to text section if - in function with section attribute. + * loop.c (regs_match_p): Fix typo in prototype. - * combine.c (combine_instrutions): Set subst_prev_insn to zero. - (try_combine, undo_all): Likewise. - (get_last_value): Return zero if subst_prev_insn set. + * regmove.c (try_auto_increment): Wrap declaration inside an + #ifdef AUTO_INC_DEC. - * sparc.h (INIT_TARGET_OPTABS): Move INIT_SUBTARGET_OPTABS to end. +Wed May 6 17:07:47 1998 Michael Meissner - * Makefile.in (install-dir): chmod a+rx all newly created directories. + * final.c (output_operand_lossage): Call fatal with the operand + lossage message instead of calling abort. - * expr.c (expand_expr, case SAVE_EXPR): Handle the case where - mode is VOIDmode. +Wed May 6 15:37:27 1998 Kaveh R. Ghazi -Fri Apr 28 15:39:38 1995 Per Bothner + * 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. - * cpplib.h (cpp_buffer): Note new escape combination "@ ". - * cpplib.c (macroexpand): Delete "@ " if stringifying. - (cpp_skip_hspace): Also skip "@ " if input buffer has_escapes. - (collect_expansion): Cleanup white-space handling. - (create_definition): Remove all leading spaces, not just first one. - (cpp_expand_to_buffer): Set has_escapes on resulting input buffer. - (macroexpand): Set output_escapes during whole function (and - specifically during calls of macarg). - (macroexpand): Set "@ " before and after expansion result. - (push_macro_expansion): Remove unneeded initial "@ ", not " ". - (cpp_get_token): Remove unneeded "@ " (not " ") at end of expansion. - (cpp_get_token): Handle "@ ". +Wed May 6 14:44:14 1998 Gavin Koch - * cpplib.c (read_name_map): Add cpp_reader parameter. Access - map_list from former (instead of having it be static). - (open_include_file): Extra parameter (because of above changes). - (do_include, lookup_import): Update calls of open_include_file. + * config/mips/r3900.h (SUBTARGET_ASM_DEBUGGING_SPEC) : + Replace -gdwarf-2 with -g0. - * cpplib.c (do_include): Fix memory leak. +Wed May 6 11:43:18 1998 Kaveh R. Ghazi - * cpplib.c (delete_assertion): Also delete tokenlist. - (do_unassert): Don't delete tokenlist (handled by delete_assertion). - (cpp_cleanup): New function. Frees resources used by a cpp_reader. - * cpphash.c (cpp_hash_cleanup): New function. - (delete_macro): Enable commented-out code. - (file_cleanup): Free actual buffer. + * 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. - * cpplib.c (cpp_options): Add map_list. + * objc/Make-lang.in (objc-act.o): Depend on system.h. + * objc/objc-act.c: Include system.h, remove redundant headers. - * cpplib.h (PARSE_GETC): Removed. Bogus and unused. - * cppmain.c (main): Remove commented-out code that used PARSE_GETC. +Wed May 6 11:21:06 1998 Kaveh R. Ghazi - * cpplib.c: Don't #include . Causes clashes - on Nextstep (when index/rindex are macros). - (cpp_grow_buffer, int_parse_file): Cast to U_CHAR*, rather than char*. + * configure.in (AC_CHECK_FUNCS): Add isascii. + (GCC_NEED_DECLARATIONS): Add atof. -Sun Apr 30 08:11:23 1995 Alan Modra (alan@spri.levels.unisa.edu.au) + * system.h: Provide prototypes for abort, atof, atol and sbrk here. + * rtl.c, rtl.h, toplev.c, tree.h: Not here. - * stdarg.h, varargs.h (va_arg): Don't assume __va_rounded_size (char) - has the value of 4. +Wed May 6 10:52:49 1998 Kaveh R. Ghazi -Sun Apr 30 07:13:43 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * system.h: Wrap time.h and sys/file.h in autoconf checks. + Provide default definitions for O_RDONLY and O_WRONLY here. - * vax.h (NOTICE_UPDATE_CC): Correctly handle aob insns. + * cccp.c, cpplib.c, fix-header.c, gcc.c, protoize.c: Not here. - * expr.c (expand_expr, case CONSTRUCTOR): Don't set target to - zero if more then one word. - Pass size and alignment to move_by_pieces_ninsns in bytes, not bits. +1998-05-06 Mark Mitchell - * cse.c (cse_insn): Properly set IN_MEMORY for SET_DEST. + * tree.h (IS_EXPR_CODE_CLASS): Remove bogus '3'. - * tree.c (substitute_in_expr): Preserve TREE_READONLY. +Wed May 6 06:35:38 1998 Robert Lipe - * c-common.c (enum attrs): Add A_UNUSED. - (init_attributes): Initialize it. - (decl_attributes, case A_UNUSED): New case. + * 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. -Sat Apr 29 15:42:03 1995 Paul Eggert +Wed May 6 01:09:01 1998 Jeffrey A Law (law@cygnus.com) + Jim Wilson (wilson@cygnus.com) - * cccp.c (do_include): Re-fix minor memory leak by using - alloca instead of xmalloc and free. + * haifa-sched.c (find_rgns): In no_loops case, fix test for leaf + blocks. Check for 1 successor which is the EXIT_BLOCK. - * cccp.c (macarg): Except for reporting error, treat unterminated - macro call as if it were terminated, since `macroexpand' relies - on *argptr being filled in. + * haifa-sched.c (find_rgns): Detect unreachable blocks, including + unreachable loops with more than one block. -Sat Apr 29 06:09:35 1995 Torbjorn Granlund +Wed May 6 08:22:24 1998 Manfred Hollstein - * pa.c (output_mul_insn): Simplify, it is never called with - UNSIGNEDP set. + * fix-header.c (write_rbrac): Add "abort" to functions which need to + be protected. - * pa.md (divsi3, udivsi3, modsi3, umodsi3): Simplify. - (ashlsi3): Clean up indentation and commentary. +Wed May 6 00:09:36 1998 Jeffrey A Law (law@cygnus.com) -Fri Apr 28 12:48:01 1995 Jason Merrill + * Check in merge from gcc2. See ChangeLog.12 for details. - * integrate.c (expand_inline_function): Don't emit any notes until - after we've expanded the actual parameters. +Tue May 5 14:33:49 1998 Jim Wilson -Fri Apr 28 11:51:06 1995 Stan Cox (gcc@dg-rtp.dg.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. - * m88k/dgux.h: (ENDFILE_SPEC, LIB_SPEC) Fix crtbegin and crtend - (SELECT_RTX_SECTION) Put relocatable pic constants in data section + * elf64.h (MULTILIB_DEFAULTS): Move definition after mips.h include. - * m88k/dguxbcs.h: (LIB_SPEC) Likewise +Tue May 5 10:50:39 1998 Andreas Schwab - * m88k/m88k.c: (symbolic_operand) Put relocatable pic constants in data + * 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. - * m88k/m88k.h: (FRAME_POINTER_REQUIRED) Add -momit-leaf-frame-pointer +Tue May 5 01:28:12 1998 Jason Merrill - * m88k/m88k.md: (umulsidi3) Doesn't work for 88110 with mod/div changes + * 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. - * m88k/x-dgux: (GCC_FOR_TARGET) tdesc gets mixed up for crtbegin/crtend +Tue May 5 01:43:16 1998 Jim Wilson -Fri Apr 28 06:36:47 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * i386.c (output_fix_trunc): Add code to emulate non-popping DImode + case. - * c-typeck.c (pop_init_level, output_init_element): Pass - require_constant_* to digest_init. +Tue May 5 01:15:06 1998 Jeffrey A Law (law@cygnus.com) - * alpha.c (alpha_emit_set_const): Now returns rtx and take MODE arg. - Rework to use a new pseudo for intermediate values if high opt level. - Also use expand_{bin,un}op. - * alpha.h (alpha_emit_set_const): Add declaration. - * alpha.md (mov[sd]i and splits): Change call to alpha_emit_set_const. + * h8300.h (ADDITIONAL_REGISTER_NAMES): Add "er" registers. - * reg-stack.c (stack_result): Fix bug in last change. + * 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. -Fri Apr 28 01:08:43 1995 Doug Evans +Mon May 4 20:23:51 1998 Jim Wilson - * objc-act.c: Update calls to start_decl, finish_struct, - pass NULLs for attributes. + * alpha.h (DBX_CONTIN_LENGTH): Decrease to 3000. -Thu Apr 27 21:13:14 1995 Doug Evans +1998-05-04 Ulrich Drepper - * sparc.md (tablejump): Only if ! TARGET_MEDANY. - (casesi): New pattern for TARGET_MEDANY case. + * 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. - * c-common.c (decl_attributes): Always continue if attribute not found. - * c-typeck.c (common_type): Call lookup_attribute instead of - value_member. - * tree.c (attribute_hash_list): New function. - (build_type_attribute_variant): Call it. - (valid_machine_attribute): Handle attributes with arguments. - (is_attribute_p): New function. - (lookup_attribute): New function. - (attribute_in_list): Deleted. - (attribute_list_contained): Check TREE_PURPOSE and TREE_VALUE. - * tree.h (valid_machine_attribute): Add prototype. - (is_attribute_p, lookup_attribute): Likewise. - * i386/winnt.h (RETURN_POPS_ARGS): Call lookup_attribute. - (ENCODE_SECTION_INFO): Likewise. - (CPP_PREDEFINES): Use __stdcall__, __cdecl__. - (VALID_MACHINE_DECL_ATTRIBUTE): Call is_attribute_p. - `args' must be NULL. +Mon May 4 19:15:29 1998 Jim Wilson -Thu Apr 27 21:10:41 1995 David Edelsohn + * expr.c (expand_expr, case INDIRECT_REF): Don't optimize string + reference if this is a store. - * rs6000.md (insv): New anonymous patterns to combine insert with - arbitrary ashift, ashiftrt, lshiftrt, or zero_extract. (Based on - patch from John Brooks .) - (ashlsi3): Remove extraneous operand processing. +Mon May 4 17:25:17 1998 Richard Henderson -Thu Apr 27 18:47:24 1995 Jim Wilson + * sparc.c (output_move_quad): Fix typo in mov_by_64 argument. - * sh/ashlsi3.c, sh/ashrsi3.c, sh/lshrsi3.c: Delete. - * sh/lib1funcs.asm (ashiftrt_r4_*): Rewrite for efficiency. - (ashrsi3, lshrsi3, lshrsi3): Add. - * t-sh (LIB1ASMFUNCS): Add new functions. - (LIBGCC2_CFLAGS): Delete. - (LIB2FUNCS_EXTRA): Remove deleted files. - (ashlsi3.c, ashrsi3.c, lshrsi3.c): Remove rules for deleted files. +Sun May 3 23:57:25 1998 Robert Lipe - * stmt.c (expand_return): When returning BLKmode structure, use - operand_subword instead of doing arithmetic on the register number. - Also, for structures smaller than word_mode, copy it into a word_mode - temporary and then subreg it. + 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. - * sparc.md: Delete two define_peepholes which print `bad peephole'. +Sun May 3 13:51:34 PDT 1998 Richard Henderson -Thu Apr 27 16:17:01 1995 Torbjorn Granlund + 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. - * toplev.c (rest_of_compilation): Call shorten_branches even when - !optimize. - * final.c (shorten_branches): For non-optimizing compiles, break - after first pass. +Sat May 2 17:47:17 PDT 1998 Jeff Law (law@cygnus.com) -Thu Apr 27 14:22:50 1995 Michael Meissner + * version.c: Bump for snapshot. - * i386/linux-oldld.h: New file, that is cloned from linux-aout.h, - except that it does not pass -m i386linux to the linker. This is - to support the original Linux ld that is on most distributions. +Sat May 2 01:37:29 1998 J"orn Rennecke + + * 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. + +Thu Apr 30 18:59:03 1998 Jim Wilson - * configure (i[345]86-*-linux*oldld*): Use i386/linux-oldld.h as - the target file. + * Makefile.in (cpp.info, gcc.info): Put -o option before input file. -Thu Apr 27 08:56:50 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Thu Apr 30 16:57:34 1998 Michael Meissner - * tree.c (valid_machine_attribute): Update last change. + * 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. + +Thu Apr 30 16:57:34 1998 Kaveh R. Ghazi + + * haifa-sched.c (alloc_{INSN,EXPR}_LIST): Make static to agree + with the prototype. + +Wed Apr 29 21:45:16 1998 J"orn Rennecke + + * sched.c (new_insn_dead_notes): Check if the register was + used in the original instruction. + * haifa-sched.c (new_insn_dead_notes): Likewise. + +Wed Apr 29 13:46:03 1998 Jim Wilson + + * dwarf2out.c (scope_die_for): If could not find proper scope, + check for and handle tagged type with incorrect TYPE_CONTEXT. + +Wed Apr 29 15:34:40 1998 John Carr + + * calls.c (expand_call): Fix recognition of C++ operator new. + + * alias.c (mode_alias_check): Disable type based alias detection. + +Wed Apr 29 15:06:42 1998 Gavin Koch + + * 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. + +Wed Apr 29 10:53:29 1998 Andreas Schwab + + * calls.c (expand_call): Bump the length limit on the specially + recognized function names to 17. + +Tue Apr 28 17:53:33 1998 Jim Wilson + + * ginclude/stddef.h: Add check for _MACHINE_ANSI_H_ for BSD/OS + when undefining macros at the end. + + * expr.c (expand_builtin, case BUILT_IN_MEMSET): Break if either + val or len has TREE_SIDE_EFFECTS set. -Thu Apr 27 08:06:33 1995 Philippe De Muyter (phdm@info.ucl.ac.be) + * 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. - * fix-header.c, cpplib.c: Don't include twice. - * cpplib.c (cpp_grow_buffer, init_parse_file): Cast {xmalloc,xrealloc} - for token_buffer to U_CHAR* instead of char*. +Tue Apr 28 08:55:26 1998 Michael Meissner - * m68k/x-mot3300: New file. - * configure (m68k-motorola-sysv*): Use x-mot3300 instead of x-alloca. + * 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. -Thu Apr 27 07:04:09 1995 Paul Eggert + * m32r.h: Prototype all functions in m32r.c. + (FIRST_INSN_ADDRESS): Declare, returning prologue size. - * cccp.c (do_include): Fix minor memory leak. + * m32r.md (bcc functions): Cast enum's to int. - * cccp.c (struct argdata): Remove unused `comments' member. - (macarg): Don't set `comments' member. + * m32r.c (conditional_move_operand): Silence a debug message. + ({small,long}_insn): New predicates. - * cccp.c (collect_expansion): Assume leading white space - already removed. - Don't allocate unnecessary space for expansion. + * 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. - * cccp.c (deps_output): Don't generate overly long output lines. - Do not invoke self recursively with spacer == 0; this simplifies - the code a bit. + * m32r.md (insn_size): New attribute. + ({,rev_}branch_insn): Add .s qualifier to branches believed to be + short. + (m32r): New attribute. -Wed Apr 26 19:20:02 1995 Andrew McCallum + * configure.in (enable_haifa): Switch m32r to Haifa by default. + * configure: Regenerate. - * objc/Object.h: Changed Class * to Class in order to match NEXTSTEP - and OpenStep runtime. - * objc/Object.m, objc/Object.h, objc/archive.c, objc/class.c: Likewise. - * objc/encoding.c, objc/init.c, objc/objc-api.h, objc/objc.h: Likewise. - * objc/objects.c, objc/runtime.h, objc/selector.c: Likewise. - * objc/sendmsg.c, objc/typedstream.h: Likewise. + (Changes from Nick Clifton ) + * 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. -Wed Apr 26 19:18:52 1995 Pieter Schoenmakers + * 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. - * objc/objc-api.h (objc_static_instances): New struct to record - static instances of a certain class. - (objc_module): New tag STATICS to point to the table of - objc_statics_instances. - - * objc/init.c (OBJC_VERSION): Version 7. - (objc_init_statics): New function. - (__objc_exec_class): Invoke objc_init_statics if needed. - - * objc/NXConstantString.m, objc/NXConstantString.h: New files. - * objc/Makefile (OBJC_O): Added bare-bones implementation of - NXConstantString. - - * objc-act.c (OBJC_VERSION): Version 7. - (build_objc_string_object): Build a full declaration if not using - the next runtime. - (objc_add_static_instance): New function. - (init_module_descriptor): Add reference to static instances table. - (build_module_descriptor): Add field for static instances table. - (get_objc_string_decl): New function. - (generate_static_references): New function. - (finish_objc): Call generate_static_references if needed. - - * c-tree.h (finish_decl_top_level): New declaration. - * c-decl.c (finish_decl_top_level): New function. - -Wed Apr 26 18:04:32 1995 Dirk Steinberg (Dirk.Steinberg@gmd.de) - - * stddef.h: Treat _MACHINE_ANSI_H_ like _ANSI_H_. - -Wed Apr 26 14:09:59 1995 Jim Wilson - - * sparc.h (NEGTF2_LIBCALL): Define. - (INIT_TARGET_OPTABS): Add support for all TFmode *_LIBCALL macros. - * optabs.c (init_optabs): Delete all uses of undocumented TImode and - TFmode *_LIBCALL macros. - - * combine.c (simplify_rtx, case TRUNCATE): Add. Use force_to_mode. - (force_to_mode, case AND): Allow some simplifications when GET_MODE (x) - has more bits than HOST_BITS_PER_WIDE_INT. - * mips/mips.md (truncdiqi2+[456]): Add patterns to simplify ZERO_EXTEND - of a TRUNCATE. - -Wed Apr 26 13:01:22 1995 Doug Evans - - * sparc.md (memop define_splits): Rewrite to not use memop. - Preserve MEM_IN_STRUCT_P, MEM_VOLATILE_P, RTX_UNCHANGING_P bits. - * sparc.c (memop): Deleted. - (splittable_symbolic_memory_operand): New function. - (splittable_immediate_memory_operand): New function. - -Wed Apr 26 12:54:26 1995 Jeffrey A. Law - - * configure: Add hppa1.1-hp-lites support. - -Wed Apr 26 08:04:46 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * sh.md (ashrsi2_31): Don't use dead_or_set_p after reload. - * pyr.md: Remove bad peepholes that improperly use dead_or_set_p. - - * function.c (expand_function_end): Warn about unused parms - if both -Wunused and -W. - - * tree.h (TYPE_PARSE_INFO): Delete unused field. - (TYPE_PACKED): Add new macro. - (struct tree_type): Delete unused field `parse_info'. - Add new field `packed_flag'. - * c-tree.h (finish_enum, finish_struct): Add ATTRIBUTES argument. - * c-common.c (init_attributes): Don't require decl for A_PACKED. - (decl_attributes, case A_PACKED): Set TYPE_PACKED for type. - * c-parse.in: Update number of shift/reduce conflicts. - (structsp): Pass attribute arg to finish_struct. - Support attributes on enums and pass to finish_enum. - * c-decl.c (finish_struct): Add ATTRIBUTES argument, call - decl_attributes and set DECL_PACKED from TYPE_PACKED. - (finish_enum): Add ATTRIBUTES argument, call decl_attributes, - and make enum narrow if TYPE_PACKED. - * print-tree.c (print_node): Print TYPE_PACKED. - - * c-decl.c (init_decl_processing): Don't give builtin__constant_p an - argument type. - * expr.c (expand_builtin, case BUILT_IN_CONSTANT_P): A pointer to a - string constant is a constant. - - * c-typeck.c (output_init_element): Constructor is not simple if - a bitfield is being assigned a non-integer. - - * c-typeck.c (push_init_level): Update constructor_depth when we - push spelling level. - -Tue Apr 25 19:50:06 1995 Jeffrey A. Law - - * pa.c (emit_move_sequence): Handle function label arithmetic for - PIC code generation too. - -Tue Apr 25 18:52:43 1995 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) - - * reg-stack.c (current_function_returns_real): Deleted (unused). - (FP_mode_reg): Trimmed to a smaller size, less overhead. - (FP_MODE_REG): New macro over which FP_mode_reg will be accessed. - (mark_regs_pat, straighten_stack): New functions. - (reg_to_stack): Amend initialisation of FP_mode_reg. - Mark FP registers mentioned in USE insns before NOTE_INSN_FUNCTION_BEG. - (get_true_reg): Eliminate FP subreg accesses in favour of the - actual FP register in use. - (record_reg_life_pat): Make it work on SUBREGs as well. Make use of - the new mark_regs_pat function. Handle USE insns if called unnested. - (record_reg_life): Don't check for QImode again, we know that it - is there. Process CALL_INSNs like all other insns, they might `use' - some FP argument registers if register passing. - (stack_result_p): Changed in stack_result and returning an rtx. - (stack_reg_life_analysis): Take a new stackentry state argument. - Use stack_result and the rtx to mark using mark_regs_pat. This ensures - that types that need multiple FP registers are handled correctly. - Delete the no_live_regs shortcut to save space. - Use stackentry state to determine filled registers. - (replace_reg): Accept COMPLEX_FLOAT as well. - (move_for_stack_reg): Optimise away some pointer dereferencing. - (subst_stack_regs): Make sure the stack is in the right order - and of the right size for register passing. - (goto_block_pat): Make sure the stack is in the right order - to return possible multi-register values from the function. - (convert_regs): Fix comment about CALL_INSN, it's no longer valid. - Make sure the stack is of the right size and in the right order - to return possible multi-register values from the function. - - * function.c (assign_parms): If STACK_REGS is defined, generate USE - insns before the function body, thus showing which registers are filled - with parameters. - * expr.c (expand_builtin_apply_args): Likewise. - Reverse order of saving registers, more compact code for i387. - (expand_builtin_apply): Likewise. - * emit-rtl.c (gen_highpart): Add comment about broken implementation. - * i386.md (untyped_call): Make it return a complex double. - - * c-parse.in (attrib): Permit null-length argument list to attributes. - - * tree.c (valid_machine_attribute): Use new function attribute_in_list, - makes sure type_attribute_variants are reused even when attributes have - parameters. - Assign any new type to TREE_TYPE (decl). - (attribute_in_list): New function. - (attribute_list_contained): Use it. - * tree.h (attribute_in_list): New declaration. - -Tue Apr 25 18:25:53 1995 Jim Wilson - - * expr.c (struct move_by_pieces): Add to_struct and from_struct fields. - (move_by_pieces): Set to_struct and from_struct fields. - (move_by_pieces_1): Set MEM_IN_STRUCT_P of to1 and from1. - (expand_builtin, case BUILT_IN_MEMCPY): New variable type. - Set MEM_IN_STRUCT_P of src_mem and dest_mem. - - * Makefile.in (clean): Delete libgcc1-asm.a. - - * m68k/vxm68k.h (CPP_SPEC): Define. - - * c-decl.c (pushdecl): Don't test DECL_EXTERNAL when deciding whether - to register a duplicate decl in the current block. - - * cross64.h (INIT_ENVIRONMENT): Define as string not putenv call. - * gcc.c (main): Pass INIT_ENVIRONMENT to putenv. - - * stmt.c (expand_return): When returning BLKmode structure in - registers, copy it to a psuedo-reg instead of to hard registers. - -Tue Apr 25 15:14:58 1995 Michael Meissner - - * rs6000.h (LEGITIMIZE_ADDRESS): Don't create a DF address using two - regs if -msoft-float or -mcpu=403. - -Tue Apr 25 15:45:44 1995 Richard Henderson (richard@atheist.tamu.edu) - - * m68k.md (divhi3, udivhi3, modhi3, umodhi3): Deleted - these insns plus some surrounding trash. - (divmodhi4, udivmodhi4): Added these insns. - -Tue Apr 25 10:12:40 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * alpha.c (alpha_builtin_saveregs): Refine last change to work - for both stdarg and varargs. - - * tree.c (chain_member_purpose): Make similar to chain_member_value. - - * Makefile.in, configure: Change "realclean" to "maintainer-clean". - - * protoize.c: Removed __NetBSD__ from conditional. - Declare strerror if HAVE_STRERROR is defined; otherwise - declare sys_errlist and sys_nerr. - (my_strerror): New function. - (errno): Don't define if already defined as a macro. - - * alpha.c (current_file_function_operand): Return false if profiling. + * m32r.c zero_and_one, emit_cond_move): Add support for MVFC. + * m32r.h: Ditto. + * m32r.md: Ditto. - * expr.c (convert_move): Don't access a hard reg in an invalid - mode when doing a truncation. + * m32r.h (PREDICATE_CODES): Add declaration of machine specific + predicates. - * alpha.c (add_operand): Test for exactly the constants allowed by - the constraints. - * alpha.h (CONST_OK_FOR_LETTER_P, case 'L'): Reject 0x80000000. +Tue Apr 28 07:25:53 1998 Manfred Hollstein - * c-parse.in (initdcl, notype_initdcl): Pass attributes to - start_decl; delete call to decl_attributes. - * c-tree.h (start_decl): Two new tree parameters. - * c-decl.c (start_decl): New args for attributes; call decl_attributes. + * Makefile.in (libgcc2.ready): Revert last patch (Apr 24). - * c-decl.c (duplicate_decls): Don't look at TYPE_ACTUAL_ARG_TYPES - if it is not set. +Mon Apr 27 18:39:47 1998 Nick Clifton - * xm-1750a.h: New file. + * config/arm/thumb.h (GO_IF_LEGITIMATE_ADDRESS): Check against + frame_pointer_rtx not FRAME_POINTER_REGNUM. - * alpha.c (alpha_builtin_saveregs): Add to incoming args addr - if less than 6 named args, not less than or equal to. +Mon Apr 27 18:36:28 1998 Jim Wilson -Mon Apr 24 15:25:19 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * reg-stack.c: Revert last patch (Apr 20). + (convert_regs): Set insn to PREV_INSN (next) after do while loop. - * mips-tfile.c (fatal, error): Make first arg const to avoid warning. + * m68k/lb1sf68.asm (Laddsf$3): Fix typos in mcf5200 exg code. - * stmt.c (expand_end_bindings): Write a BARRIER after call - to abort in nonlocal handler. + * 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. - * stmt.c (expand_decl_init): Call preserve_temp_slots to keep - around any temp whose address was taken. +Mon Apr 27 15:53:30 EDT 1998 Andrew MacLeod -Fri Apr 21 16:26:15 1995 Torbjorn Granlund + * cplus-dem.c (demangle_qualified): Replace missing else. - * pa.md (call_internal_reg): Fix typos in length calculation. - (call_value_internal_reg): Likewise. +Mon Apr 27 20:22:08 1998 J"orn Rennecke -Fri Apr 21 13:17:15 1995 Roland McGrath + * sh.c (gen_ashift_hi): Don't make SUBREG of a SUBREG. - * config/gnu.h (STANDARD_INCLUDE_DIR): New macro. - * config/mips/gnu.h (STANDARD_INCLUDE_DIR): Macro moved there. +Mon Apr 27 18:23:51 1998 J"orn Rennecke -Fri Apr 21 08:23:58 1995 Tom Quiggle (quiggle@lovelace.engr.sgi.com) + * sh.c (sh_expand_prologue, sh_expand_epilogue): + If TARGET_DOUBLE_ALIGN, preserve 64 bit stack alignment. + * sh.h (STACK_BOUNDARY): Likewise. - * toplev.c (lang_options): Add -I for GNAT. - * gcc.c (default_compilers): Pass -I to gnat1. +Mon Apr 27 17:22:48 1998 J"orn Rennecke -Fri Apr 21 07:58:06 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * sh.h (LEGITIMIZE_RELOAD_ADDRESS): Define. - * tree.c (integer_all_onesp): Test to size of mode, not TYPE_PRECISION. +Mon Apr 27 08:55:23 1998 Michael Meissner - * toplev.c (main): Turn on -fforce-mem for -O2. + * 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. - * fold-const.c ([lr]rotate_double): Replace; old versions were bogus. - (fold, shift and rotate): Don't call tree_int_cst_sgn on non-integer. - (fold, case LROTATE_EXPR): If constant count, convert to RROTATE_EXPR. - (fold, case RROTATE_EXPR): Sometimes commute logical op with rotate. - Delete pair of counteracting shifts. + * .gdbinit: Add breakpoints on exit and fancy_abort. - * combine.c (simplify_logical, case AND): If still an AND, get - new values for op0 and op1. + * final.c (split_double): Avoid a compiler warning if + BITS_PER_WORD is less than or equal to HOST_BIT_PER_WIDE_INT. -Thu Apr 20 17:52:10 1995 Jim Wilson + * rtl.h (JUMP_{CROSS_JUMP,NOOP_MOVES,AFTER_REGSCAN}): New macros + for calling jump_optimize. - * sh.c: Completely rewritten. - * sh.h (FAST_BIT, CONSTLEN_2_BIT, CONSTLEN_3_BIT, CONSTLEN_0_BIT, - TARGET_FASTCODE, TARGET_CLEN3, TARGET_CLEN0, TARGET_OPTIONS): Delete. - (TARGET_SWITCHES): Delete -mclen3 and -mclen0 options. - (TARGET_DEFAULT): Is zero. - (OVERRIDE_OPTIONS): Delete code to set max_count_si and max_count_hi. - (SPECIAL_REG): New macro. - (HARD_REGNO_MODE_OK): Allow any mode in any general register. - (GO_IF_LEGITIMATE_ADDRESS): Delete constant + reg address case. - (MOVE_RATIO): Define to 2 when TARGET_SMALLCODE. - (max_si, max_hi, max_count_si, max_count_hi): Delete. - * sh.md: Delete spurious constraints from all define_expands. - (rotlsi3_1): Set T reg instead of clobbering it. - (ashrsi3): Use expand_ashiftrt instead of gen_shifty_op. - (movsi_i, movhi_i, movsf_i): Add conditions to reject patterns - needing a reload. - (movdi-2, movdf_k): Correct conditions to reject patterns needing - a reload. - ([inverse_]branch_{true,false}): Pass operands to output_branch. - (jump): Delete unnecessary braces. - (call, call_value): Don't use expand_acall. Force operand0 into - a register. + * toplev.c (rest_of_compilation): Call jump_optimize using JUMP_* + macros, rather than 0/1's. -Thu Apr 20 12:57:16 1995 Jason Merrill +Sun Apr 26 23:19:10 1998 Richard Henderson - * function.c (assign_parms): Use TREE_ADDRESSABLE rather than - TYPE_NEEDS_CONSTRUCTING to decide whether a parameter needs to be - passed by invisible reference. + * alpha.h (CONST_COSTS): Zero is always free. + (RTX_COSTS): Add EV6 costs. Abort if alpha_cpu is unknown. - * calls.c (expand_call): Ditto. Abort if we try to pre-evaluate a - parameter of TREE_ADDRESSABLE type. +Sun Apr 26 15:38:50 1998 Andreas Schwab -Wed Apr 19 17:50:24 1995 Torbjorn Granlund + * cplus-dem.c (gnu_special): Fix off-by-one bug when checking the + length in the name of a virtual table. - * pa.h (TARGET_SWITCHES): Fix typo. +Sun Apr 26 01:21:06 1998 Richard Henderson -Tue Apr 18 18:06:03 1995 Per Bothner + * alpha.c (print_operand): Don't add 'v' suffix for ALPHA_FPTM_N. - * expr.c (store_constructor): Use BYTES_BIG_ENDIAN rather - than BITS_BIG_ENDIAN to layout bits within bitstring. - * tree.c (get_set_constructor_bytes): Likewise. +Sat Apr 25 22:11:38 PDT 1998 Jeff Law (law@cygnus.com) -Tue Apr 18 17:22:46 1995 Per Bothner (bothner@wombat.gnu.ai.mit.edu) + * version.c: Bump for snapshot. - * config/m68k/{x-hp320,x-hp320g} (FIXPROTO_DEFINES): - Define _HPUX_SOURCE so putenv and other functions get seen. +Sat Apr 25 17:17:15 1998 Jeffrey A Law (law@cygnus.com) -Tue Apr 18 03:57:35 1995 Michael Meissner (meissner@cygnus.com) + * fold-const.c (fold_convert): Fix typo. - * varasm.c (weak_decls): Make this a unique structure, instead of - a tree structure. - (handle_pragma_weak): Don't redeclare asm_out_file. Use new weak - structure to copy name and value to. Protect name and value by - copying them to the permanent obstack. - (declare_weak): Call handle_pragma_weak, instead of duplicating - the code. - (finish_weak): Rewrite to use new weak symbols list structure. +Sat Apr 25 17:55:54 1998 John Carr - * c-pragma.h: New file to define the c-pragma.c interfaces. - * c-pragma.c: Include it. - * varasm.c: Include it. - * c-lex.c: Include it. - * cp/lex.c: Include it. + * 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. - * varasm.c (handle_pragma_weak): No longer pass output file - stream, since weak pragmas are delayed until the end of the - compilation. - * c-pragma.c (handle_pragma_token): Call handle_pragma_weak - without file stream argument. + * rtl.h: Declare record_base_value. - * Makefile.in (varasm.o, c-lex.o, c-pragma.o): Add dependencies on - c-pragma.h. + * loop.c, unroll.c: Update callers of record_base_value. - * config/rs6000.md (movdf): If -msoft-float, do not generate - memory to memory references, like is already done for the - -mhard-float case. Remove an extra test for -mhard-float inside - of -mhard-float code. + * alias.c (find_base_value, find_base_term): SIGN_EXTEND and + ZERO_EXTEND do not affect base values. -Tue Apr 18 06:19:50 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Fri Apr 24 15:57:02 1998 Jeffrey A Law (law@cygnus.com) - * fold-const.c (size_int): Arg is unsigned HOST_WIDE_INT. - * tree.h (size_int): Likewise. + * dbxout.c (dbxout_type): Fix typo. + (dbxout_range_type): Another HOST_WIDE_INT_PRINT_DEC fix. -Mon Apr 17 23:36:57 1995 Jason Merrill + * configure.in: Use CC_FOR_BUILD, not BUILD_CC. - * rs6000/aix41.h: Restore March 11th changes, plus - (ASM_OUTPUT_EXTERNAL): Do add [DS] or [RW], just don't emit - anything. - * rs6000/aix3newas.h (ASM_OUTPUT_EXTERNAL): Ditto. +Fri Apr 24 16:11:47 1998 John Carr -Mon Apr 17 15:58:52 1995 Per Bothner + * expr.c (expand_builtin, case MEMSET): Set MEM_IN_STRUCT_P + if the argument is the address of a structure or array. - * config/mips/x-iris (FIXPROTO_DEFINES): Add -D_LANGUAGE_C_PLUS_PLUS. - * config/mips/x-iris6: Likewise. + * configure.in: Enable Haifa scheduler by default for SPARC. - * cpplib.c: Rename make_definition to cpp_define. - * cpplib.h (cpp_define): New declaration. +Fri Apr 24 20:55:47 1998 J"orn Rennecke - * cpplib.c (special_symbol): For T_SPECLINE, calculate __LINE__ - in enclosing file buffer, not current buffer (if macro expanding). - (cpp_get_token): Fix thinko (in code for chopping unneeded space). + * cse.c (cse_set_around_loop): Don't do optimization when + new pseudos are created. -Mon Apr 17 11:36:07 1995 Jim Wilson +Fri Apr 24 11:00:18 1998 Jeffrey A Law (law@cygnus.com) - * abi64.h (CPP_SPECS): Define and use _ABI64 instead of - _MIPS_SIM_ABI64. - (SETUP_INCOMING_VARARGS): Set MEM_IN_STRUCT_P if big endian target. - * iris6.h (ASM_IDENTIFY_GCC, ASM_IDENTIFY_LANGUAGE): Define. + * 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. - * combine.c (get_last_value): Ignore BARRIER when scanning backwards. - (move_deaths): New variables before_dead and after_dead. Set them - to instructions that have valid INSN_CUID values and use in test. +Fri Apr 24 16:45:03 1998 J"orn Rennecke - * combine.c (subst_prev_insn): New variable. - (try_combine): Set it. - (get_last_value): Use it. + * (gen_shl_and, in case 1): Fix comparison with mask. - * reload.c (find_reloads): Recompute reg_equiv_address from - reg_equiv_memory_loc before using it. - (find_reloads_toplev, make_memloc): Likewise. +Fri Apr 24 06:46:40 1998 Nick Clifton - * expr.c (expand_builtin, case BUILT_IN_MEMCPY): Call force_operand - on dest_rtx before returning it. + * config/arm/thumb.h (GO_IF_LEGITIMATE_ADDRESS): Disallow frame + pointer as second register in REG+REG pair. - * function.c (instantiate_decls): Use temporary allocation if - DECL_DEFER_OUTPUT is set. +Fri Apr 24 09:22:23 1998 Kaveh R. Ghazi -Sat Apr 15 23:19:03 1995 Jason Merrill + * c-common.c (check_format_info): Don't check for the 'x' format + character twice, instead check for 'x' and 'X' - * aoutos.h (ASM_OUTPUT_DEF): Define instead of SET_ASM_OP. - * sparc/sunos4.h (ASM_OUTPUT_DEF): Ditto. +Fri Apr 24 08:02:30 1998 Manfred Hollstein - * varasm.c (weak_finish): Don't handle aliases. - (declare_weak): Ditto. - (assemble_alias): Handle aliases. + * 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. - * c-common.c (enum attrs): Add A_ALIAS. - (init_attributes): Ditto. - (decl_attributes): Ditto. +Fri Apr 24 04:42:35 1998 J"orn Rennecke -Sat Apr 15 13:26:34 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * calls.c (expand_call): Call preserve_temp_slots on temps - made for BLKmode args returned in registers. +1998-04-23 Jim Wilson - * pa.c (override_options): Fix typo. + * frame.c, libgcc2.c (stdlib.h, unistd.h): Don't include when + inhibit_libc is defined. -Sat Apr 15 12:11:46 1995 Brendan Kehoe + * c-aux-info.c (gen_type): Use DECL_NAME only for TYPE_DECL. - * alpha/alpha.c (output_epilog): Initialize fp_offset to 0, and - make sure it's non-zero before we try to use it to restore the - frame pointer. +Thu Apr 23 19:09:33 1998 Jim Wilson -Fri Apr 14 19:45:05 1995 Jason Merrill + * 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. - * ginclude/va-{clipper,pa,pyr,sparc,spur}.h (va_arg): Reorganize - to avoid BIND_EXPRs and COND_EXPRs of aggregate type. +Thu Apr 23 15:01:13 1998 Nick Clifton -Fri Apr 14 19:31:14 1995 Roland McGrath + * 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. - * config/svr4.h (ASM_OUTPUT_SECTION_NAME): Make the section - read-only executable "ax" if DECL is a FUNCTION_DECL; read-only - "a" (previously the case always) if DECL is TREE_READONLY; - otherwise writable "aw". +Thu Apr 23 20:21:06 1997 J"orn Rennecke -Fri Apr 14 18:49:11 1995 Linus Torvalds + * sh.c (gen_ashift_hi): Implement right shifts via gen_ashift. + * sh.md (ashrhi3_k, lshrhi3_k, lshrhi3_m, lshrhi3, lshrhi3+1): Delete. - * alpha.md (probe_stack): Probe with write, not read. - (allocate_stack): Update and correct stack probe code. - * alpha.c (output_prolog): Changed stack probe at function entry. +Wed Apr 22 17:07:35 1998 Michael Meissner -Fri Apr 14 18:42:34 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * loop.c (note_addr_stored): Correct function to take 2 arguments, + instead of 1. - * jump.c (delete_insn): When deleting after label, delete - a BARRIER as well. + * rtl.def (MATCH_INSN2): Add new matching pattern. + * genrecog.c (add_to_sequence): Support MATCH_INSN2. -Fri Apr 14 14:40:48 1995 Jason Merrill +Wed Apr 22 15:52:22 1998 John Carr - * toplev.c (compile_file): Call weak_finish. + * 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. - * c-common.c (enum attrs): Add A_WEAK. - (init_attributes): Ditto. - (decl_attributes): Support __attribute__ ((weak)) by - calling declare_weak. + * final.c (split_double): Sign extend both halves of a split CONST_INT. - * sparc/sunos4.h (HANDLE_PRAGMA_WEAK, WEAK_ASM_OP, SET_ASM_OP): - Define to support weak symbols with -fgnu-linker. - * aoutos.h: Ditto. +Wed Apr 22 10:42:45 1998 Jeffrey A Law (law@cygnus.com) - * varasm.c (handle_pragma_weak): Add declared weak symbols to - weak_decls rather than emitting them immediately. - (declare_weak): Add the indicated declaration to weak_decls. - (weak_finish): Emit .weak directives for any weak symbols. + * mips.c (compute_frame_size): Change only argument to a HOST_WIDE_INT. - * libgcc2.c: The C++ free-store management functions are weak. +Wed Apr 22 10:53:49 EDT 1998 Andrew MacLeod -Fri Apr 14 13:00:29 1995 Michael Meissner (meissner@cygnus.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. - * rs6000/rs6000.c (output_prolog): For eabi systems, emit main's - call to __eabi before setting up the minimal TOC used with the - -mrelocatable support. +1998-04-21 Jim Wilson - * rs6000/eabi.h (INVOKE__main): Don't define any more, - output_prolog will emit the call. + * stmt.c (check_seenlabel): When search for line number note for + warning, handle case where there is no such note. -Fri Apr 14 09:09:03 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue Apr 21 20:48:37 1998 John Carr - * alpha.c (call_operand): Any reg is valid for NT. - (output_prologue): Never need GP for Windows/NT. - Set SYMBOL_REF_FLAG in current function decl. + * genemit.c (gen_exp): Allow machine description to set mode of + MATCH_OP_DUP. -Thu Apr 13 20:19:30 1995 Jason Merrill +Tue Apr 21 16:36:01 1998 John Carr - * alpha/xm-alpha.h (HAVE_VPRINTF): Define. - (HAVE_PUTENV): Define. - (POSIX): Define. + * alias.c (mode_alias_check): New function. + (true_dependence, anti_dependence, output_dependence): Call + mode_alias_check. -Thu Apr 13 19:57:44 1995 Doug Evans +Tue Apr 21 12:05:32 1998 Jeffrey A Law (law@cygnus.com) - * emit-rtl.c (gen_sequence): If the insn has a non-null - CALL_INSN_FUNCTION_USAGE field, output it as a sequence so the - latter isn't discarded. + * mips.h (STACK_BOUNDARY): Allow specific targets to override. + (MIPS_STACK_ALIGN): Similarly. - * c-parse.in: Update expected conflict count. + * 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. -Thu Apr 13 08:10:20 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * configure.bat: Arg 2 is which machine (i386 or alpha). - * configure (alpha-*-winnt3*): New configuration. - * alpha.c: Don't #include stamp.h for WINNT. - (input_operand, case CONST): Allow ptr_mode and DImode. - * alpha.h (WINDOWS_NT): Provide default definition. - (ASM_OUTPUT_INT): Use output_addr_const. - (ASM_OUTPUT_ADDR_DIFF_ELT): Use .long for NT. - * alpha.md (calll, tablejump, movsi): New variants for NT. - * alpha/winnt.h, alpha/xm-winnt.h, alpha/x-winnt: New files. - * alpha/config-nt.bat, alpha/config-nt.sed: New files. - * i386/config-nt.bat: Add Ada fragments to Makefile. - * i386/config-nt.sed: Adjust for deletion of config.run in Makefile.in - Change version to 2.6.3. - Add some missing tabs. - * winnt/winnt.h (TARGET_MEM_FUNCTIONS): Define. - (LINK_SPEC): Delete "align:0x1000". - * winnt/xm-winnt.h (OBJECT_SUFFIX): Define. - * ginclude/stdarg.h, ginclude/varargs.h: Clean up code that - defines *DEFINED* symbols. +Tue Apr 21 09:43:55 1998 Kaveh R. Ghazi - * configure (a29k-*-sym1*): Same as a29k-*-bsd*. - * a29k.h (ASM_OUTPUT_SECTION_NAME): New macro. + * objc/sendmsg.c: Define gen_rtx_MEM() to 1, as is already done + for gen_rtx(MEM, ...). -Wed Apr 12 14:36:03 1995 Jim Wilson +Tue Apr 21 02:15:36 1998 Richard Henderson - * dbxout.c (dbxout_type_fields): Correct arguments to CHARS macro - in flag_minimal_debug case. - (dbxout_symbol_name): Use DECL_ASSEMBLER_NAME unconditionally. - * sdbout.c (sdbout_record_type_name): Correct indentation. - (sdbout_symbol): Use DECL_ASSEMBLER_NAME unconditionally. - (sdbout_one_type): Likewise. + * sparc.h (MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): Rewrite + to not be so gross, and to properly function with PIC. -Tue Apr 11 13:24:13 1995 Per Bothner +Mon Apr 20 20:44:25 1998 Jim Wilson - * fix-header.c (main): Fix loop over required_functions_list. - (fatal): Also print inc_filename. + * frame.c (heapsort): Rename to frame_heapsort. - * cpplib.c (cpp_push_buffer): Added missing initializatuon of buf. - (cpp_file_buffer): Compare against CPP_NULL_BUFFER, not NULL. - (finclude): No longer call cpp_push_buffer - let callers do it. - (do_include): Add call to cpp_push_buffer. - (push_parse_file): Call cpp_push_buffer early, so initial - defines can use file and line from a valid cpp_buffer. - (nreverse_pending): New function. - (push_parse_file): Use nreverse_pending. - (push_parse_file): For -include files, just push them in reverse - order - we don't need to scan them now. - (cpp_error_from_errno, cpp_perror_with_name): Don't emit extra '\n'. + * gcc.c (do_spec_1, case '['): Move flag out of loop and initialize it. -Tue Apr 11 13:36:44 1995 Jim Wilson - - * configure (mips-dec-mach3): Add. - - * sh.c (shiftby_operand): Delete. - * sh.h (TARGET_SWITCHES): -m3 and -m3l also set SH2_BIT. - (OVERRIDE_OPTIONS): Don't add CPU_SH2 to CPU_SH3 when TARGET_SH3. - * sh.md (ashlsi3): Use nonmemory_operand as a predicate instead of - shiftby_operand. Don't use shiftby_operand in the output statement. - (lshrsi3): Likewise. +Mon Apr 20 12:43:09 1998 Doug Evans - * c-decl.c (poplevel): Do output inline function if - DECL_ABSTRACT_ORIGIN points to itself. + * flow.c (sbitmap_vector_alloc): Ensure sbitmaps properly aligned. - * varasm.c (output_constant): Cast assemble_string argument to char *. +Mon Apr 20 15:04:14 1998 John Wehle (john@feith.com) -Mon Apr 10 14:29:28 1995 Torbjorn Granlund + * i386.md (movsf_push, movdf_push, movxf_push): Allow memory + operands during and after reload. - * recog.c (constrain_operands, case 'E'): Make this work like - constraint character `F' when REAL_ARITHMETIC is defined. - * regclass.c (record_reg_classes, case 'E'): Likewise. - * reload.c (find_reloads, case 'E'): Likewise. +Mon Apr 20 22:37:50 1998 J"orn Rennecke -Mon Apr 10 14:30:31 1995 Michael Meissner + * 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. - * rs6000/aix3newas.h, rs6000/aix41.h: Eliminate March 11th changes - to undefine ASM_OUTPUT_EXTERNAL{,_LIBCALL}, since this causes the - compiler not to bootstrap. +Mon Apr 20 14:48:29 1998 Michael Meissner -Mon Apr 10 07:17:39 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * gcc.c (lang_specific_driver): Declare prototype properly so + fatal can be passed to it without error. - * cppalloc.c: #include config.h. - * cppexp.c: Add declarations of xmalloc and xrealloc. - (cpp_parse_expr): Cast args to bcopy to char *. - * cpphash.c: Add declaration of xmalloc. - * cpplib.c (init_parse_options, cpp_reader): Cast args to bcopy, - bcmp, and bzero to char *. - (add_import, push_parse_file, init_parse_file): Likewise. + * configure.in (AC_CHECK_FUNCS): Check for strchr and strrchr. + * configure: Regenerate. + * config.in: Add #undef's for strchr and strrchr. - * c-common.c (enum attrs): New attribute, A_NOCOMMON. - (init_attribute): Initialize it. - (decl_attributes): Implement it. - * varasm.c (make_decl_rtl): Allow section attribute if -fno-common - or variable is not to be placed in common for some other reason. + * 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. - * combine.c (simplify_set): Don't move a SUBREG to dest if it - is changing the size of a hard reg in CLASS_CANNOT_CHANGE_SIZE. + * 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. - * reload.c (find_equiv_reg): If goal is a pseudo that got memory, - a store into memory makes it invalid. - * reload1.c (reload_as_needed): Call forget_old_reloads_1 on - pattern before reg elimination. +Mon Apr 20 18:19:40 1998 J"orn Rennecke -Mon Apr 10 00:26:14 1995 Jeffrey A. Law + * sh.c (find_barrier): Fix bug in ADDR_DIFF_VEC handling. + (split_branches): Call init_insn_lengths. - * pa.c (pa_reorg): Bump label use count for each entry in an - exploded ADDR_VEC. +Mon Apr 20 07:37:49 1998 Michael Meissner -Sun Apr 9 09:22:51 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * i386.c: Include expr.h to get the change_address prototype + declared. - * i386.md (adddi3, subdi3): Need scratch reg whenever operand 0 in - mem and operands 1 not '0'. - (subdi3): Don't treat two non-equal MEMs as non-aliasing. +Mon Apr 20 01:00:05 1998 H.J. Lu (hjl@gnu.org) -Sat Apr 8 22:53:38 1995 Jeffrey A. Law + * 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. - * pa.c (pa_reorg): Fix typo. +Sun Apr 19 15:41:24 1998 Manfred Hollstein -Sat Apr 8 19:36:36 1995 Michael Meissner + * 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. - * rs6000/rs6000.h (SELECT_SECTION): TREE_CODE_CLASS must be called - with a tree code, not a tree value. +Sun Apr 19 02:42:06 1998 Richard Henderson -Sat Apr 8 12:41:01 1995 Mike Stump + * haifa-sched.c (queue_to_ready): Fix typo in prototype. - * cpphash.c: Don't use const on compilers that don't support it. +Sat Apr 18 23:52:35 PDT 1998 Jeff Law (law@cygnus.com) -Sat Apr 8 16:32:22 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * version.c: Bump for snapshot. - * expr.c (expand_increment): Handle case where INCREMENTED - has a non-trivial conversion. +Sat Apr 18 18:30:22 1998 Jim Wilson -Fri Apr 7 19:33:21 1995 Phil Nelson (phil@cs.wwu.edu) + * i386.md (fix_truncsfdi2+[123]): Add + to operand 1 constraints. - * ns32k.h (TRAMPOLINE_TEMPLATE, TRANSFER_FROM_TRAMPOLINE): - Fix assembler syntax errors. + * 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. -Fri Apr 7 19:27:23 1995 Pat Rankin (rankin@eql.caltech.edu) +Sat Apr 18 19:06:59 1998 David Edelsohn - * cccp.c (VMS_fstat, VMS_stat): New functions. + * 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. -Fri Apr 7 19:25:21 1995 Paul Eggert +Sat Apr 18 15:41:16 1998 Jim Wilson - * cccp.c (collect_expansion): If traditional, set stringify - member to SHARP_TOKEN regardless of the value of - stringify_sharp_token_type. + * regmove.c (fixup_match_1): In three places, in flag_exceptions + check, change p to q. -Fri Apr 7 07:48:35 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Sat Apr 18 15:30:49 1998 Jim Wilson - * cse.c (simplify_unary_operation): #ifdef POINTERS_EXTEND_UNSIGNED, - handle sign- or zero-extending addresses. + * 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. - * optabs.c (init{,_integral,_floating,_complex}_libfuncs): - Change SUFFIX to "char" to avoid confusion with prototype. +Sat Apr 18 01:23:11 1998 John Carr - * explow.c (convert_memory_address): No longer static. - New arg, TO_MODE. - Do something special for SYMBOL_REF, LABEL_REF, and CONST. - (memory_address): Add extra arg to call to convert_memory_address. - * rtl.h (convert_memory_address): Add extra arg. - * expr.c (expand_expr, case ADDR_EXPR): Always call - convert_memory_address when converting; add extra arg. - * stmt.c (expand_computed_goto): Convert from ptr_mode to Pmode. + * 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. - * gcc.c (OBJECT_SUFFIX): Default now ".o", not "o". - (all specs): Remove "." before %O; use %O in a few missing cases. - * i386/os2.h (OBJECT_SUFFIX): Delete from here. - * i386/xm-os2.h (OBJECT_SUFFIX): Move to here; now has period. + * sparc.h: Change gen_rtx (CODE to gen_rtx_CODE (. - * Makefile.in (STAGESTUFF): Use $(exeext) for executables. +Fri Apr 17 22:38:17 1998 Jeffrey A Law (law@cygnus.com) -Fri Apr 7 03:32:29 1995 Richard Stallman + * 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. - * config.sub: Accept -lites* as op sys. + * libgcc2.c (__floatdisf): Fix a couple typos. -Thu Apr 6 23:08:50 1995 Per Bothner +Fri Apr 17 17:28:26 1998 Jim Wilson - * cpplib.c (bcopy, bzero, bcmp): Remove #undefs. - * cppalloc.c (xcalloc): Re-implement using calloc, - rather than malloc+bzero. - * cpplib.c (SELF_DIR_DUMMY): New macro. - (do_include): Don't pass searchptr to finclude if it is dsp, - since that is on the stack, and would cause a dangling pointer. - If handling #include_next, recognize SELF_DIR_DUMMY. + * Makefile.in (mostlyclean): Delete *.mach and *.bp files. -Fri Apr 7 00:54:24 1995 Jeffrey A. Law +Fri Apr 17 16:35:35 1998 Greg McGary - * pa.h (MACHINE_DEPENDENT_REORG): Define. - * pa.md (switch_jump): New pattern for jumps which implement - a switch table. - * pa.c (pa_reorg): New function to explode jump tables. - (pa_adjust_insn_length): Account for jumps in switch tables with - unfilled delay slots. + * emit-rtl.c (gen_highpart): initialize `word' properly for pseudo. -Thu Apr 6 14:31:10 1995 Jason Merrill +Fri Apr 17 14:30:37 1998 John Carr - * c-typeck.c (build_binary_op): Don't call common_type for - uncommon pointer types. + * emit-rtl.c (operand_subword_force): If a register can not be + accessed by words, copy it to a pseudo register. -Wed Apr 5 13:53:17 1995 Per Bothner +Fri Apr 17 14:30:37 1998 Jim Wilson - Re-write fixproto/fix-header/etc to use cpplib: - * fix-header.c: Comment out support for adding missing extern "C" - using #ifdef ADD_MISSING_EXTERN_C instead of #if 0. - * fixproto: Removed case of required functions. Instead use ... - * fix-header.c (std_include_table): ... new required-functions table. - (cpp_file_line_for_message, cpp_print_containing_files, cpp_message): - New stub functions, to intercept cpplib error message. - * fixproto: Don't call $CPP, since fix-header now incorporates cpplib. - * gen-protos.c (fatal, hashf): New functions. - (main): Use hashf, instead of hash. - * scan-decls.c (scan_decls, skip_to_closing_brace): Re-write to - take a cpp_reader* as argument, not a FILE*. - * scan.h (hash): Make parameter const. - * scan.c (hash): Removed. - * scan.c (memory_full, xmalloc, xrealloc): Removed. - Use functions from cppalloc.c instead. - * Makefile.in (gen-prtos, fix-header, stmp-fixproto): Update. + * rs6000/vxppc.h (CPP_SPEC): Add support for mrelocatable*. -Wed Apr 5 13:24:14 1995 Per Bothner +Fri Apr 17 17:01:25 1998 Michael Meissner - * cpplib.c (cpp_get_token): If traditional, return after comment, - instead of reading more, so end-of-line can be peeked at. - * cpperror.c (cpp_file_line_for_message, cpp_message): New - functions, that do the actual printing of error messages. - (cpp_print_file_and_line, cpp_error, cpp_warning, cpp_pedwarn, - cpp_error_with_line, cpp_warning_with_line, cpp_pedwarn_with_line, - cpp_pedwarn_with_file_and_line, cpp_error_from_errno, my_strerror, - cpp_perror_with_name): Re-write to use cpp_file_line_for_message - and cpp_message, and move to cpplib.c. + * tree.h (mark_seen_cases): Delete declaration. -Tue Apr 4 23:35:49 1995 Roland McGrath +Fri Apr 17 13:32:20 1998 Jeffrey A Law (law@cygnus.com) - * config/gnu.h (GNU_CPP_PREDEFINES): Remove -D__HURD__. + * stmt.c (mark_seen_cases): Make static and add prototype. -Tue Apr 4 17:15:54 1995 Jeffrey A. Law +Fri Apr 17 11:21:43 1998 Kaveh R. Ghazi - * pa.h (DO_GLOBAL_DTORS_BODY): Fix pointer -> integer assignment - problem. + * 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. - * reorg.c (fill_simple_delay_slots): Don't use a JUMP_INSN - a the target of another JUMP_INSN to fill a delay slot. - -Mon Apr 3 19:03:48 1995 Torbjorn Granlund - - * cse.c (simplify_unary_operation): Sign-extend constants when - they have the most significant bit set for the target. - - * m68k.md (umulsi3_highpart): Test for CONST_INT and CONST_DOUBLE, - not CONSTANT_P. - (smulsi3_highpart): Likewise. - * m68k.c (const_uint32_operand): New function. - (const_sint32_operand): New function. - * m68k.md (const_umulsi3_highpart): Use const_uint32_operand instead - of immediate_operand for op3. Delete mode. - (const_smulsi3_highpart): Analogous change. - -Mon Apr 3 19:03:48 1995 Jim Wilson - - * cse.c (simplify_binary_operation): Sign-extend constants when - they have the most significant bit set for the target. - - * combine.c (force_to_mode, case PLUS): Sign extend masks that are - negative in OP_MODE. - (simplify_and_const_int): Sign-extend constants when they have the - most significant bit set for the target. - (merge_outer_ops): Likewise. - (simplify_shift_const): Likewise. + * 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. -Mon Apr 3 18:23:48 1995 Jason Merrill - - * toplev.c (lang_options): Add -f{no-,}repo. - -Mon Apr 3 18:13:15 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * combine.c (nonzero_bits, case REG): Check POINTERS_EXTEND_UNSIGNED. - (num_sign_bit_copies, case REG): Likewise. - * explow.c (convert_memory_address): New function. - (memory_address): Call if it needed. - (promote_mode, case POINTER_TYPE): Use Pmode and pointer extension. - (allocate_dynamic_stack_space): Convert size from ptr_mode. - * expr.c (clear_storage, expand_assignment, store_{expr,constructor}): - Use ptr_mode instead of Pmode in some places. - (expand_expr, expand_builtin): Likewise. - (push_block, store_expr): Convert size to Pmode. - (expand_expr, case ADDR_EXPR): Convert from Pmode to ptr_mode. - -Mon Apr 3 18:00:52 1995 Jim Wilson - - * explow.c (allocate_dynamic_stack_space): Correct typo in last - change. +Thu Apr 16 22:41:02 1998 Jeffrey A Law (law@cygnus.com) - * sh.c (gen_shifty_op, case ASHIFTRT): Return 0 if shift count is not - a constant. + * varasm.c (asm_output_bss): Add prototype. + (asm_output_aligned_bss): Likewise. -Mon Apr 3 12:17:10 1995 Michael Meissner (meissner@cygnus.com) + * unroll.c (verify_addresses): Add prototype. - * expmed.c (extract_bit_field): When converting a SUBREG into a - REG, if the system is big endian, adjust the bit offset - appropriately. + * toplev.c: Add many prototypes. Too many to mention here. -Mon Apr 3 00:08:45 1995 Roland McGrath + * stmt.c (check_seenlabel): Add prototype. - * config/i386/linux.h: Include "config/linux.h" instead of - "linux.h", to avoid recursion. + * rtlanal.c (reg_set_p_1): Add prototype. + (reg_set_last_1): Likewise. -Sun Apr 2 23:50:27 1995 Roland McGrath + * reorg.c (find_dead_or_set_registers): Add prototype. - * config/i386/gnuelf.h: Include i386/linux.h instead of - i386/linuxelf.h. + * regmove (try_auto_increment): Add prototype. -Sun Apr 2 17:35:10 1995 Jim Wilson + * reg-stack.c (pop_stack): Add prototype. - * cse.c (simplify_relational_operation): Don't simplify A-B for - compare of A and B when the compare is unsigned. + * recog.c (validate_replace_rtx_1): Add prototype. + (find_cosntant_term_loc): Likewise. -Sun Apr 2 08:23:38 1995 Paul Eggert + * 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. - * fixincludes (stdio.h): BSDI 2.0 changed the spelling of _VA_LIST_ - to _BSD_VA_LIST_. - -Sun Apr 2 07:57:28 1995 Richard Kenner - - * i386/xm-bsd386.h: New file. - * configure (i[345]86-*-bsd*): Add xm_file. - - * gcc.c (default_compilers): Pass -W and -w to gnat1. - - * winnt/winnt.h (STDC_VALUE): Add #undef. - * i386/winnt.h (LIB_SPEC): Likewise. - -Sun Apr 2 07:55:25 1995 Douglas Rupp (drupp@cs.washington.edu) - - * i386/winnt.h (RETURN_POPS_ARGS, ENCODE_SECTION_INFO): Call - chain_member_purpose, not chain_member_value. - (ASM_FILE_START, LIB_SPEC): Move to here. - * winnt/winnt.h (ASM_FILE_START, LIB_SPEC): Delete from here. - * tree.c (chain_member_purpose): New function. + * jump.c (mark_modified_reg): Add prototype. -Sat Apr 1 12:19:14 1995 Jason Merrill + * haifa-sched.c (is_prisky): Add prototype. + (queue_to_ready): Likewise. - * c-typeck.c (build_binary_op): New variable build_type controls - type given to expression when created. Set to integer_type_node for - comparison ops instead of result_type so result_type still holds type - in which comparison is done. When checking for comparison between - signed and unsigned, use result_type rather than (possibly shortened) - type of op0. Don't warn about equality comparison of signed operand - to unsigned constant that fits in signed type. + * genextract.c (gen_insn): Add prototype. -Sat Apr 1 09:47:02 1995 Douglas Rupp (drupp@cs.washington.edu) + * 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. - * i386/winnt.h (CPP_PREDEFINES): Add definitions for __stdcall - and __cdecl. - * winnt/winnt.h (LIB_SPEC): Add OLDNAMES.LIB. - * winnt/xm-winnt.h: Remove unneeded #define's for non-ANSI functions. - * fixinc.winnt: Remove unneeded fixes relating to __stdcall. + * genattrtab.c (attr_hash_add_rtx): Add prototype. + (attr_hash_add_string, write_length_unit_log): Likewise. - * objc/Makefile (SHELL): New definition. + * genattr.c (init_range): Add prototype. -Sat Apr 1 08:25:26 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * combine.c (sets_function_arg_p): Add prototype. - * cse.c (cse_insn): When emitting a BARRIER, don't put it after - a deleted insn. + * expr.c (store_constructor_field): Add prototype. + (get_memory_usage_from_modifier): Likewise - * reload.c (push_reload): Initialize secondary_{in,out}_icode. + * expmed.c (synth_mult): Add prototype. + (choose_multiplier, invert_mod2n): Likewise. - * gcc.c (print_multilib_info): Don't use LAST_PATH if not set. + * 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. -Sat Apr 1 08:15:59 1995 Pat Rankin (rankin@eql.caltech.edu) + * dwarfout.c (decl_class_context): Add prototype. + (output_inheritance_die, type_ok_for_scope): Likewise. - * vax.md (extv, extzv): Don't use immediate value for operand 1. + * c-lex.c (skip_white_space_on_line): Add prototype. -Sat Apr 1 07:48:29 1995 Yury Shevchuk (sizif@botik.yaroslavl.su) + * alias.c (record_set): Add prototype. + (find_base_term, base_alias_check): Likewise. - * stmt.c (expand_asm_operands): Properly ignore invalid reg in clobber. + * function.c (assign_outer_stack_local): Make static and add prototype. -Sat Apr 1 07:02:24 1995 Paul Eggert + * 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. - * cccp.c: General code cleanup. - Add prototypes for static functions. - Remove unnecessary casts to (char *); add casts to (U_CHAR *). - Add parentheses suggested by `gcc -Wparentheses'. - Rename local variables as suggested by `gcc -Wshadow'. - , , , : New includes. - , : Include only if defined(RLIMIT_STACK). - : Include, unless already does. - (HAVE_FCNTL_H, HAVE_STDLIB_H, HAVE_SYS_TIME_H): New symbols. - (HAVE_UNISTD_H, STDC_HEADERS, TIME_WITH_SYS_TIME): Likewise. - (__attribute__, PROTO, VA_START, PRINTF_ALIST, PRINTF_DCL): New macros. - (PRINTF_PROTO{,_1,_2,_3}, DO_PROTO): Likewise. - (bcopy, bzero, bcmp): If #defined by configuration file, use that. - If STDC_HEADERS is defined, use standard C functions. - If BSTRING is defined, or USG and VMS are not defined, use - the C library. Otherwise, use my_bcopy, my_bzero, my_bcmp. - (localtime): Remove no-longer-necessary explicit declaration. - (getenv, index, rindex): Don't declare explicitly if the - appropriate system header should declare it. - (fdopen): Remove no-longer-used declaration. - (vprintf): Define a subsitute macro if !defined(HAVE_VPRINTF). - (main): Replace `fdopen (dup (fileno (stdout)), "w"))' - with `stdout'. - (get_lintcmd, rescan, create_definition): Use bcmp instead of strncmp - when both operands are known to be free of null bytes. - (check_macro_name, compare_defs, collect_expansion): Likewise. - (do_assert, compare_token_lists, assertion_lookup, do_line): Likewise. - (skip_if_group, lookup): Likewise. - (rescan): Remove unused label `startagain'. - Abort instead of printing nonsense if the stack is corrupted - when there was an unterminated successful conditional. - (pcfinclude): Include explicit double-cast through GENERICPTR - to identify particularly egregious type puns. - (create_definition, do_define, check_macro_name): Use %.*s - printf format to avoid painful copying-and-casting. - (do_once): Return void, not (unused) int. - (do_ident, do_pragma, do_sccs): Accept extra arguments so that - all directive-handler's types match. - (do_sccs): Define only if SCCS_DIRECTIVE is defined. - (skip_if_group, dump_single_macro): Add `default: break;' to - keep -Wswitch happy. - (error, warning, error_with_line, vwarning_with_line, pedwarn): Use - stdarg/vararg/vfprintf instead of passing bogus char * args around. - (pedwarn_with_line, pedwarn_with_file_and_line, fatal): Likewise. - (verror, vwarning, verror_with_line, vwarning_with_line): New fcns. - (dump_single_macro): Abort if ap points to garbage. - (make_definition, make_undef, make_assertion): Parameter now char *. - (xmalloc, xrealloc, xcalloc, savestring, index0): Make sizes size_t - instead of unsigned; make pointer parameters GENERICPTR, not char *. - (xcalloc): Use bzero to clear memory instead of using own loop. - -Fri Mar 31 08:33:07 1995 Ken Raeburn (raeburn@wombat.gnu.ai.mit.edu) + * basic-block.h (compute_dominators): Declare. - * longlong.h (umul_ppmm mc68000): Use %# instead of #. - -Fri Mar 31 06:37:54 1995 Michael Meissner (meissner@cygnus.com) - - * stor-layout.c (layout_decl): Implment -fpack-struct. - (layout_record): Ditto. + * flow.c (dump_sbitmap, dump_sbitmap_vector): New debugging + functions. + * basic-block.h: Declare them. - * flags.h (flag_pack_struct): New flag variable. - - * toplev.c (flag_pack_struct): New flag variable. - (f_options): Add -fpack-struct support. - - * Makefile.in (stor-layout.o): Add flags.h dependency. - -Fri Mar 31 08:40:16 1995 Douglas Rupp (drupp@cs.washington.edu) +Thu Apr 16 13:45:51 1998 Jim Wilson - * configure (i[345]86-*-winnt3*): Add tmake_file. - * i386/x-winnt (winnt.o): Deleted. - * i386/t-winnt: New file. + * reg-stack.c (constrain_asm_operands): Set n_alternatives to zero if + no operands. -Fri Mar 31 07:26:37 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * m68k/netbsd.h, m68k/hp3bsd44.h: Remove #include of machine/ansi.h. +Wed Apr 15 11:33:09 1998 Alexandre Petit-Bianco - * configure (a29k-*-bsd): Set tmake_file to t-libc-ok. + * 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. - * stmt.c (expand_asm_operands): Properly handle output that can't - be directly written into. - - * c-parse.in (structsp): Correct error in last change. - * c-common.c (init_attributes): A_FORMAT is only for decls. - -Thu Mar 30 18:27:34 1995 Jason Merrill - - * libgcc2.c: Remove explicit 0-initializations of static variables. - -Thu Mar 30 18:22:39 1995 Fergus Henderson - - * c-typeck.c (internal_build_compound_expr): Warn if LHS of comma - expression has no side effects, or computes value which is not used. - * stmt.c (make warn_if_unused_value): No longer static. - * tree.h (warn_if_unused_value): Add declaration. - -Thu Mar 30 18:15:11 1995 Jim Wilson - - * combine.c (get_last_value): Revert back to use prev_nonnote_insn - instead of prev_real_insn. Modify test that ignores USE insns. - - * rs6000.h (SELECT_SECTION): Apply constant DECL_INITIAL test - only to DECLs. - - * explow.c (allocate_dynamic_stack_space): Test STACK_BOUNDARY against - BIGGEST_ALIGNMENT at run time instead of at compile time. - Give MUST_ALIGN macro a value, and test this value in if statements. - -Thu Mar 30 08:59:56 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * c-parse.in: Now have 27 shift/reduce conflicts. - (attribute_list): Just make chain of all attributes. - (attrib): Consistently put name as PURPOSE, args, if any, as VALUE. - (structsp): Allow attributes on any struct or union. - * c-common.c (enum attrs): New enum class. - (attrtab, attrtab_idx): New variables. - (add_attribute, init_attributes): New functions. - (decl_attributes): Major rewrite. - * tree.c (valid_machine_attribute): Now receive name and args. +1998-04-15 Mark Mitchell -Thu Mar 30 07:20:14 1995 Paul Eggert + * c-common.c (declare_hidden_char_array): Use TYPE_DOMAIN to get + the length of an array, not TREE_TYPE. - * protoize.c: Use the phrase `preprocessing directive' consistently. - * cccp.c (handle_directive, do_line, skip_if_group): Likewise. - (output_line_directive): Renamed from output_line_command. - (no_line_directives): Renamed from no_line_commands. +Wed Apr 15 15:31:34 1998 Jeffrey A Law (law@cygnus.com) - * cccp.c (rescan): Don't recognize preprocessing directives - within macro args. Warn if one is found. + * flow.c (sbitmap_union_of_successors): New function. + * basic-block.h (sbitmap_union_of_successors): Declare it. -Thu Mar 30 06:20:36 1995 H.J. Lu (hjl@nynexst.com) +Wed Apr 15 12:38:03 1998 Jim Wilson - * configure (i[345]86-*-linux*): Set xmake_file=x-linux, - tm_file=i386/linux.h, and don't set extra_parts. - (i[345]86-*-linux*aout*): New configuration. - (i[345]86-*-linuxelf): Deleted. - * config/linux{,-aout}.h, config/x-linux, config/xm-linux.h: New files. - * config/i386/linux-aout.h: New file. - * config/i386/linux.h: Extensive modifications to use ELF format - as default. - (LIB_SPEC): Don't use libc_p.a for -p. don't use libg.a - unless for -ggdb. - (LINUX_DEFAULT_ELF): Defined. - * config/i386/linuxelf.h,config/i386/x-linux: Files deleted. - * config/i386/xm-linux.h: Just include xm-i386.h and xm-linux.h. + * configure.in (gnu_ld): Rename to gnu_ld_flag before main loop. + Set gnu_ld to gnu_ld_flag inside main loop. + (gas): Likewise. -Wed Mar 29 19:09:36 1995 Mike Stump +Wed Apr 15 14:50:05 1998 Dave Brolley - * libgcc2.c (__throw_type_match): Update to use new calling convention. + * toplev.c (compile_file): Call init_parse using new interface. + (init_lex): Remove declaration. -Wed Mar 29 14:53:23 1995 Jim Wilson + * c-lex.c (init_parse): Now returns char* containing filename. - * gcc.c (process_command): Delete code modifying gcc_exec_prefix. - (main): Put it here after last use of gcc_exec_prefix. For cross - compiler, set startfile_prefixes if gcc_exec_prefix is set and - standard_startfile_prefix is a relative path. +Wed Apr 15 12:37:10 1998 Jeffrey A Law (law@cygnus.com) - * combine.c (make_compound_operation, AND case): Undo July 7, 1994 - change. + * pa.h (LEGITIMIZE_RELOAD_ADDRESS): Do nothing if not optimizing. - * mips/mips.md (call_internal1, call_value_internal1): Move %* from - start of assembler output to immediately before the jal. - - * mips/mips.c (function_prologue): Put SDB_DEBUGGING_INFO ifdef around - code for SDB_DEBUG support. - (mips_select_rtx_section, mips_select_section): Change rdata_section - to READONLY_DATA_SECTION and sdata_section to SMALL_DATA_SECTION. - * mips/mips.h (SMALL_DATA_SECTION): Define. - - * reorg.c (mark_referenced_resources): Make setjmp use all registers. - - * flow.c (mark_used_regs, case SUBREG): Only fall through to REG case - if operand is a REG. +Wed Apr 15 12:10:18 1998 Michael Meissner - * i960/i960.h (TARGET_SWITCHES): Make -mold-align set - TARGET_FLAG_STRICT_ALIGN. - (STRICT_ALIGNMENT): Test TARGET_STRICT_ALIGN. + * Makefile.in (gen{config,flags,codes,emit}): Link in host print-rtl.o. + (gen{extract,peep,opinit,output}): Ditto. - * sh/sh.c (andcosts): Modify costs to match the hardware, and add - explanatory comments. + * 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. - * sparc/sol2.h (CPP_PREDEFINES): Add -D__SVR4. - -Wed Mar 29 14:30:30 1995 Michael Meissner +Tue Apr 14 07:30:57 1998 K. Richard Pixley - * rs6000/rs6000.md (movsf): When moving to/from integer registers, - don't move floating point to memory if it is being simulated with - -msoft-float. + * fixincludes: discard empty C++ comments, as found in sys/time.h + on hpux-11.0. -Wed Mar 29 06:47:36 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - - * c-parse.in (initdcl): Only call decl_attributes once. - * c-common.c (decl_attributes): Clean up test for __mode__. +Wed Apr 15 10:47:21 1998 Andreas Schwab -Tue Mar 28 08:34:37 1995 John Hassey (hassey@dg-rtp.dg.com) + * config/m68k/m68k.md (adddi3, subdi3): Optimize for constant + operand. - * i386.md (adddi3): Don't treat two non-equal MEMs as non-aliasing. +Wed Apr 15 01:21:21 1998 Jeffrey A Law (law@cygnus.com) -Tue Mar 28 08:20:49 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * emit-rtl.c (operand_subword): Rework slightly to avoid + bogus warning from previous change. - * a29k.h (CONSTANT_ADDRESS_P): Provide consistent definition. +Tue Apr 14 23:39:13 1998 Richard Henderson -Tue Mar 28 07:26:41 1995 Paul Eggert + * 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. - * cccp.c (do_xifdef, do_endif): Remove unnecessary pointer comparisons. +Tue Apr 14 22:00:39 1998 John Carr -Mon Mar 27 20:45:15 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * function.c (assign_parms): Initialize unsignedp before passing + its pointer to promote_mode. - * calls.c (expand_call, store_one_arg): Don't set KEEP in calls - to assign_stack_temp. - * function.c (preserve_temp_slots): Clear ADDR_TAKEN on item - that we are preserving. + * genattrtab.c (check_attr_test): Handle MATCH_INSN like MATCH_OPERAND. + (write_test_expr): Allow MATCH_INSN. -Mon Mar 27 14:39:35 1995 Ian Lance Taylor +Tue Apr 14 21:57:57 1998 Paul Eggert - * mips/mips.h (FIRST_PSEUDO_REGISTER): Increment. - (FIXED_REGISTERS, CALL_USED_REGISTERS): Add new register. - (MD_REG_LAST): Increment. - (ST_REG_FIRST, ST_REG_LAST): Increment. - (HILO_REGNUM): Define. - (enum reg_class): Add HILO_REG. - (REG_CLASS_NAMES): Add "HILO_REG". - (REG_CLASS_CONTENTS): Add HILO_REG initializer, and adjust ST_REGS - and ALL_REGS initializers. - (SECONDARY_RELOAD_CLASS): Remove. - (SECONDARY_INPUT_RELOAD_CLASS): Define. - (SECONDARY_OUTPUT_RELOAD_CLASS): Define. - (REGISTER_MOVE_COST): Treat HILO_REG as MD_REGS. - (REGISTER_NAMES): Add initialization line. - (DEBUG_REGISTER_NAMES): Add "accum". - * mips/mips.md: For each instruction which sets HI or LO, clobber - HILO_REGNUM with (clobber (match_scratch:MODE N "=a")). Change - each explicit reference to register 66 to register 67. - (mulsidi3): Change to define_expand. - (mulsidi3_internal): New name of old mulsidi3. - (mulsidi3_64bit): New insn. - (umulsidi3): Change to define_expand. - (umulsidi3_internal): New name of old umulsidi3. - (umulsidi3_64bit): New insn. - (madddi_64bit, umaddi_64bit): New insns. - (movdi_internal2): Add case for setting HILO_REG to zero. - (reload_indi, reload_outdi): New define_expands. - (movsi_internal1, movsi_internal2): Add cases for setting MD_REGS - to zero, and for setting a general reg to HILO_REG. - (reload_outsi): New define_expand. - * mips/mips.c (mips_reg_names): Add "accum". - (mips_sw_reg_names): Likewise. - (mips_regno_to_class): Map HILO_REGNUM to HILO_REG. - (mips_move_1word): Handle moving HILO_REGNUM to a general - register. Make sure that the normal MD_REG cases aren't used for - HILO_REGNUM. Handle moving zero to a MD_REG. - (mips_move_2words): Make sure that the normal MD_REG cases aren't - used for HILO_REGNUM. Handle moving zero to a MD_REG. - (override_options): Set mips_char_to_class for 'a' and 'b'. - (mips_secondary_reload_class): Add in_p argument. Handle - HILO_REGNUM. + * install.texi: Update section on warnings that can be safely ignored. -Mon Mar 27 07:16:05 1995 Warner Losh +Tue Apr 14 14:55:16 1998 Jim Wilson - * gcc.c: Removed __NetBSD__ from conditional. - Declare strerror if HAVE_STRERROR is defined; otherwise - declare sys_errlist and sys_nerr. - (my_strerror): New function. - -Fri Mar 24 18:08:14 1995 Jason Merrill - - * i386/linux.h (LIB_SPEC): Don't try to link with libraries we - know only exist in archive form unless -static. + * 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. -Fri Mar 24 16:12:16 1995 Doug Evans - - * Makefile.in (multilib.h): Depend on Makefile, not config.status. - -Fri Mar 24 15:01:17 1995 Michael Meissner - - * rs6000/rs6000.h (TARGET_MULTIPLE_SET): New target_flags bit that - indicates -mmultiple or -mno-multiple was explicitly passed by the - user, and not set as part of the cpu defaults. - (TARGET_SWITCHES): Set TARGET_MULTIPLE_SET bit for both -mmultiple - and -mno-multiple. - - * rs6000/rs6000.c (rs6000_override_options): If -mmultiple or - -mno-multiple was explicitly used, don't override the setting with - the processor default. - -Wed Mar 22 21:42:13 1995 Doug Evans - - * i960/i960.c (i960_function_arg_advance): Ensure all regs marked - as used if stack is also used (for va_start). - (i960_setup_incoming_varargs): Rewrite to be similar to Intel's - version, but don't allocate reg block unless necessary. - * ginclude/va-i960.h (varargs va_start): Save g14 explicitly. - Account for arguments preceding va_alist. - -Wed Mar 22 13:24:55 1995 Torbjorn Granlund - - * pa.c (singlemove_string): Handle SFmode constants again. Simplify. - (zdepi_cint_p): Make some variables HOST_WIDE_INT. - (lhs_lshift_cint_operand): Likewise. - (output_and): Likewise. - (output_ior): Likewise. +Tue Apr 14 16:19:03 1998 Michael Meissner -Wed Mar 22 12:40:09 1995 Jim Wilson + * expr.c (MOVE_RATIO): Set to 3 if optimizing for space. - * sh.md (udivsi3): Don't clobber register 6. - (udivsi3, divsi3, mulsi3_call): Use a pseudo-reg with regclass 'z' - for output rather than hard register 0. - (block_move_real): Don't clobber registers 4 and 5. +Tue Apr 14 11:31:28 1998 Krister Walfridsson - * mips.c (mips_select_section): Apply constant DEC_INITIAL tests - only to VAR_DECLs. + * i386/bsd386.h (ASM_OUTPUT_ALIGN): Redefine. -Wed Mar 22 03:53:17 1995 Richard Stallman +Tue Apr 14 09:02:32 1998 Jeffrey A Law (law@cygnus.com) - * config.sub (rm400, rm600): New machine names. - (sinix5.*, sinix): New os aliases. - (mips-siemens): Default os to sysv4. + * svr4.h (ASM_DECLARE_OBJECT_NAME): Use HOST_WIDE_INT_PRINT_DEC. + (ASM_FINISH_DECLARE_OBJECT): Likewise. -Mon Mar 20 21:56:47 1995 Per Bothner + * 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. - Merged Paul Eggert's patch to cccp.c of Wed Mar 8 18:21:51 1995: - * cpplib.c (do_include): Fix type typo: pcfbuflimit is char *, not int. - - Merged Doug Evans' patch to cccp.c of Mon Feb 27 17:06:47 1995: - * cpplib.c (do_include): Check for redundant file before opening in - relative path case. Don't call fstat unnecessarily. + * combine.c (simplify_rtx, case TRUNCATE): Respect value of + TRULY_NOOP_TRUNCATION. - Merged J.T. Conklin's patch to cccp.c of Wed Feb 22 20:29:31 1995: - * cpperror.c: Removed __NetBSD__ from conditional. +Mon Apr 13 11:31:49 1998 Jason Merrill - Merged Kenner's patch to cccp.c & cexp.y of Tue Sep 20 17:49:47 1994: - * cppexp.c (struct operation): Make value by HOST_WIDE_INT. - (cpp_parse_expr): Change return type to HOST_WIDE_INT. - * cpplib (eval_if_expr): Likewise. - (do_if, do_elif): Update appropriately. - * cpplib.h (cpp_parse_expr): Removed, to avoid defining HOST_WIDE_INT. + * tree.h (BINFO_OFFSET_ZEROP): Use integer_zerop. - Merged Paul Eggert's patch to cccp.c of Mon Aug 8 19:42:09 1994: - * cpplib.c (create_definition): Warn about `#define a@', since a - diagnostic is now required (see ISO TC1's addition to subclause 6.8). - Also warn about `#define is-empty(x) (!x)'. +Sun Apr 12 20:55:32 1998 Catherine Moore -Tue Mar 21 00:10:50 1995 Jeffrey A. Law + * invoke.texi (ld options) Include memset requirements + for options -nodstdlib and -nodefaultlibs. - * x-pa (CC): Add "-Dbsd4_4". +1998-04-12 Paul Eggert -Mon Mar 20 18:40:31 1995 Per Bothner + This change is from an idea suggested by Arthur David Olson. - * toplev.c (print_error_function): New function hook. - (default_print_error_function): New function. Default value - of print_error_function. Code moved here from report_error_function. - (report_error_function): Use print_error_function hook. + * 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. -Mon Mar 20 20:27:43 1995 Doug Evans + * c-tree.h (record_function_format): Remove decl; no longer extern. - * cccp.c (do_xifdef): Handle c++ comments. - (do_endif): Likewise. + * extend.texi: Add documentation for strftime format checking. -Mon Mar 20 15:31:45 1995 Jason Merrill +Sun Apr 12 20:23:03 1998 Jeffrey A Law (law@cygnus.com) - * configure (i386 configurations): Prepend i386/ to t-crt*. + * mips/ecoffl.h: Do not include mips.h. + * mips/elf.h: Likewise. -Mon Mar 20 07:58:04 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * configure.in (mips-*-ecoff): Do not mention mips/mips.h in tm_files. + * mips/ecoff.h: Include "mips/mips.h". - * stmt.c (fixup_gotos): Add missing call from last change. +Sat Apr 11 22:42:54 PDT 1998 Jeff Law (law@cygnus.com) - * objc/misc.c: Put Alpha-specific decls before #include of runtime.h. + * version.c: Bump for snapshot. - * alpha.h (EXTRA_SECTIONS): Write zeros first time in .rdata. +Sat Apr 11 01:24:28 1998 Jeffrey A Law (law@cygnus.com) -Sat Mar 18 16:37:24 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * 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. - * flow.c (mark_used_regs, case SUBREG): Set reg_changes_size even - for integer modes. - (mark_used_regs): Set reg_changes_size for RHS, if necessary. - * combine.c (gen_lowpart_for_combine): Set reg_changes_size, if needed. - * reload.c (push_reload): Reload a SUBREG if paradoxical and - class is CLASS_CANNOT_CHANGE_SIZE. - * reload1.c (gen_reload): Handle paradoxical SUBREGs. - * alpha.h (SECONDARY_{INPUT,OUTPUT}_RELOAD_CLASS): Need GENERAL_REGS - for paradoxical SUBREG and FLOAT_REGS. - (SECONDARY_NEEDED_MODE): Use actual mode for 4 bytes or wider. - * alpha.md (movsi): Allow FP regs and add case for store of FP reg. - Remove cvtlq from MEM to FP reg case. +Fri Apr 10 22:28:32 1998 Jeffrey A Law (law@cygnus.com) - * rtl.h (emit_insns_after): Add declaration. - * stmt.c (fixup_gotos): Do a cleanup for a block when it is exited - even if label if not defined yet. + Reinstall this patch from Jason. + * function.c (push_function_context_to): Don't call init_emit. - * function.c (pop_function_context): Fix error in last change; - reference old value of current_function_decl before we modify it. +Fri Apr 10 13:40:20 1998 Nick Clifton -Fri Mar 17 21:57:44 1995 Jason Merrill + * rtl.c (read_skip_spaces): Prevent infinite loops upon + encountering unterminated comments. - * toplev.c (rest_of_compilation): Handle -Wreturn-type properly - for inlines we aren't compiling yet. +Fri Apr 10 10:43:41 1998 Jeffrey A Law (law@cygnus.com) -Fri Mar 17 21:26:48 1995 Mike Stump + * emit-rtl.c (operand_subword): Properly handle CONST_INTs for + 64x32 cross builds. - * libgcc2.c (__register_exceptions): Handle empty tables. + * 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. -Fri Mar 17 11:48:31 1995 Douglas Rupp (drupp@cs.washington.edu) +Fri Apr 10 00:36:31 1998 H.J. Lu (hjl@gnu.org) - * i386/winnt.c (winnt_function_prologue): Deleted. - (gen_stdcall_suffix): New function. + * i386.md (movqi+1): Handle invalid QI register. + (movsf_push-1): Likewise. -Thu Mar 16 17:36:52 1995 Jason Merrill +Thu Apr 9 16:53:59 1998 Nick Clifton - * svr4.h (LINK_SPEC): If the user did not specify -h name, use the - output file name, if any. - * sparc/sol2.h (LINK_SPEC): Ditto. Also, if the user did not - specify -R path, add an -R for each -L. + * 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. - Move SunOS 4-specific assembler switches into the appropriate place. - * m68k/sun[23].h (ASM_SPEC): Add %{R} %{j} %{J} %{h} %{d2} - %{keep-local-as-symbols:-L}. - * i386/sun.h (ASM_SPEC): Add %{R} %{keep-local-as-symbols:-L}. - * sparc/sparc.h (ASM_SPEC): Ditto. - * gcc.c (default_compilers): Remove %{R} %{j} %{J} %{h} %{d2} - %{keep-local-as-symbols:-L} from assembler rules. +Thu Apr 9 01:43:04 1998 Jeffrey A Law (law@cygnus.com) -Thu Mar 16 16:58:09 1995 Michael Meissner + * calls.c (expand_call): Fix typo. - * rs6000/eabi-ctors.c: New file, handle C++ static constructors - and destructors without requiring anything else from a libc. +Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com) - * rs6000/t-eabi (LIB2FUNCS_EXTRA): Build eabi-ctors.c. + * 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. - * rs6000/eabi.asm: Do not load up register 2 if there is no .got - section. Jump to the __do_global_ctors function at the end of - processing to call C++ static constructors, and it will return to - __eabi's caller. Use normal volatile registers, instead of saving - and restoring registers 30 and 31. +Wed Apr 8 23:13:50 1998 Gavin Koch - * rs6000/eabi.h (STARTFILE_SPEC): Define as null. - (LIB_SPEC): Ditto. - (ENDFILE_SPEC): Ditto. - (LIBGCC_SPEC): Always look for libgcc.a. + * config/mips/r3900.h (ASM_OUTPUT_DEF,SUPPORTS_WEAK, + ASM_WEAKEN_LABEL): Add. -Thu Mar 16 17:05:14 1995 Richard Kenner +Wed Apr 8 18:21:30 1998 Richard Henderson - * stmt.c (warn_if_unused_value, case SAVE_EXPR): New case. - (warn_if_unused_value, case NOP_EXPR): OK if CALL_EXPR inside. + * alpha/crtbegin.asm, alpha/crtend.asm, alpha/t-crtb: New files. + * configure.in (alpha-*-linux*): Use them. - * c-common.c (decl_attributes): Allow alignment for TYPE_DECLs. +Fri Apr 3 17:02:13 1998 Alexandre Petit-Bianco - * Makefile.in (xsys-protos.h): Fix typo in -U operand. + * 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. -Thu Mar 16 13:49:10 1995 Per Bothner +Wed Apr 8 12:51:19 1998 Jeffrey A Law (law@cygnus.com) - * cpplib.c, cpplib.h: New files - a C PreProcessor library. - * cpphash.c, cpphash.h, cppalloc.c, cpperror.c, cppexp.c: - New files - utility features used by cpplib. - * cppmain.c: New file - cpp replacement main program for cpplib. - * Makefile.in: New rules to build cppmain. + * configure.in (v850): Use t-v850. + (ix86-wrs-vxworks): Recognize 786 just like other x86 configurations. -Thu Mar 16 16:11:05 1995 Douglas Rupp (drupp@cs.washington.edu) + * protoize.c (creat, read, write): Do not declare. - * i386/winnt.h (FUNCTION_PROLOGUE, HAVE_probe, gen_probe): Deleted. - (ENCODE_SECTION_INFO, VALID_MACHINE_DECL_ATTRIBUTE): New macro. + * jump.c (mark_jump_label): Record REG_LABEL notes for insns which + refer to the CODE_LABEL before a dispatch table. -Thu Mar 16 15:58:24 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * invoke.texi: Add ARC options. - * combine.c (apply_distributive_law, case SUBREG): Fix typo when - checking for paradoxical SUBREG. + * gcc.c (proces_command): Improve error message for -o with + either -c or -S. -Wed Mar 15 18:45:08 1995 Doug Evans + * i386/x-cygwin32 (CLIB): Link in advapi32. - * libgcc1-test.c: Renamed from cross-test.c. - * Makefile.in (LIBGCC1_TEST): Renamed from CROSS_TEST. - (all.cross): Delete $(ENQUIRE) dependency. - (libgcc1-test): Renamed from cross-test. - Delete unnecessary gcc-cross and $(LIBGCC) dependencies. - Link with -nostartfiles -nostdlib - `$(GCC_FOR_TARGET) --print-libgcc-file-name`. - (libgcc1-test.o): Renamed from cross-test.o. - Change gcc-cross dependency to xgcc since the latter is used. + * alpha.h (ASM_IDENTIFY_GCC): Define to nothing. + (ASM_IDENTIFY_LANGUAGE): Likewise. -Wed Mar 15 13:49:21 1995 Jason Merrill + * i386.md (movqi recognizer): Don't perfom byte increment into + a NON_QI_REG_P. - * tree.c (save_tree_status): Now takes a tree 'context' instead of - a boolean 'toplevel' as an argument. If 'context' is not - current_function_decl, create a new obstack for the new function. - Also save inline_obstacks. - (restore_tree_status): No longer takes a second argument. Also - restore inline_obstacks. - (temporary_allocation): Clear inline_obstacks. - (permanent_allocation): Free up the obstacks in inline_obstacks. + * configure.in (x86-dg-dgux): Run fixinc.dgux. - * function.h (struct function): New fields contains_functions and - inline_obstacks. + * i370.h: Fix typo in GEN_INT changes. - * function.c (push_function_context_to): Now takes a tree - 'context' instead of a boolean 'toplevel' as an argument. - Also save current_function_contains_functions. - (push_function_context): Pass current_function_decl to it. - (pop_function_context_from): Takes 'context' instead of 'toplevel'. - Set current_function_contains_functions properly. - (pop_function_context): Pass current_function_decl to it. + * bitmap.c (bitmap_element_allocate): Use "void" for arglist instead + of an empty arglist in prototype. -Wed Mar 15 14:53:09 1995 Michael Meissner + * Makefile.in: Remove bytecode crud that crept back in after the + gcc2 merge. - * rs6000/rs6000.md (abssi2): Turn into a define_expand. If - TARGET_POWER, do old code that uses the abs instruction. If not, - do abs in three instructions, using a temporary register, which - enables generating more reasonable code for sne. Add a recognizer - for negative of the absolute value. Add define_splits for the - PowerPC. - (sne insn): Add a recognizer for sne on the PowerPc to use two - instructions, compared to the four generated using the absolute - value insn. +1998-04-08 Brendan Kehoe -Tue Mar 14 18:38:40 1995 J.T. Conklin + * c-lex.h (is_class_name): Fix arg type to be tree, not void. + (make_pointer_declarator, reinit_parse_for_function): Fix typo. - * m68k.md ({add,sub,mul,div}[sdx]f3): Add new patterns for recognizing - SImode, HImode, and QImode operands. +Wed Apr 8 06:16:45 1998 Richard Earnshaw (rearnsha@arm.com) -Mon Mar 13 18:59:36 EST 1995 David Edelsohn + * arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define. - * rs6000.h (CPP_SPEC): Add PPC403. - (processor_type): Add PPC403. - (RTX_COSTS): Add PPC403. - * powerpc.h (CPP_SPEC): Add PPC403. - * sysv4.h (CPP_SPEC): Add PPC403. - * rs6000.c (processor_target_table): Add PPC403. - * rs6000.md (define_attr cpu and function units): Add PPC403. +Wed Apr 8 00:44:18 1998 Bernd Schmidt (crux@pool.informatik.rwth-aachen.de> -Mon Mar 13 14:40:23 1995 Michael Meissner + * 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. - * rs6000/rs6000.md (call, call_value insns): Do not put a nop - after a bl instruction on System V.4 and eABI. +Tue Apr 7 21:48:52 1998 Jeffrey A Law (law@cygnus.com) - * rs6000/sysv.4 (SUBTARGET_SWITCHES): Add support for - -mno-traceback to suppress the V.4 traceback word. - (ASM_DECLARE_FUNCTION_NAME): Don't put out a traceback work if - -mno-traceback. + * pa.h (LEGITIMIZE_RELOAD_ADDRESS): Define. -Mon Mar 13 13:36:37 1995 Jason Merrill +1998-04-07 Ken Raeburn - * t-svr4, i386/t-{crtpic,sol2}, m88k/t-svr4, sparc/t-sol2: - Use -fPIC, rather than -fpic, for building crtstuff. + * config/mips/mips.c (siginfo): Deleted. + (override_options): Don't install SIGINFO signal handler. -Sat Mar 11 17:27:08 1995 Jason Merrill +Tue Apr 7 11:58:04 1998 Jim Wilson - * configure: Use aix3newas.h for AIX 3.2.4 and 5. - * rs6000/aix41.h: Undefine ASM_OUTPUT_EXTERNAL{,_LIBCALL}. - * rs6000/aix3newas.h: New file. Define ASM_SPEC to -u, and - undefine ASM_OUTPUT_EXTERNAL{,_LIBCALL}. + * loop.c (check_dbra_loop): When normalize comparison_val, add check + to verify it is non-negative. -Sat Mar 11 06:42:50 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Tue Apr 7 02:01:47 1998 Richard Henderson - * dbxout.c (dbxout_symbol): Properly handle decl whose DECL_NAME - points to a TYPE_DECL with a zero TYPE_NAME. + * alpha.c (alpha_expand_block_move): Correctly collect block offsets. + (alpha_expand_block_clear): Likewise. -Fri Mar 10 18:18:33 1995 Torbjorn Granlund +Mon Apr 6 23:36:01 1998 Richard Henderson - * pa.h (PROMOTE_MODE): Define. + * tree.h (sizetype_tab): Fix previous change for K&R. -Fri Mar 10 14:37:58 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Mon Apr 6 22:23:29 PDT 1998 Jeff Law (law@cygnus.com) - * sdbout.c (sdbout_record_type_name): If TYPE_NAME is - a TYPE_DECL, get name from DECL_NAME. + * version.c: Bump for snapshot. -Fri Mar 10 14:09:26 1995 Doug Evans +Mon Apr 6 23:16:10 1998 Richard Earnshaw (rearnsha@arm.com) - * arm/riscix.h (SUBTARGET_SWITCHES): Renamed from - ARM_EXTRA_TARGET_SWITCHES. - * arm/riscix1-1.h (SUBTARGET_SWITCHES): Likewise. - * arm.h (SUBTARGET_SWITCHES): Likewise. - (TARGET_HARD_FLOAT, TARGET_SOFT_FLOAT): Define. - (TARGET_SWITCHES): Add -msoft-float, -mhard-float. - (BYTES_BIG_ENDIAN): Delete #ifndef/#endif. - (CONDITIONAL_REGISTER_USAGE): If -msoft-float, disable fp regs. - (FUNCTION_VALUE): R16 is return reg only if !-msoft-float. - (LIBCALL_VALUE): Likewise. - * arm.md (all fp patterns): Conditionalize on TARGET_HARD_FLOAT. - (*movsf_soft_insn, *movdf_soft_insn): New patterns. + * configure.in (sparc-*-solaris2*): Add xm-siglist.h to xm_file. + Add USG and POSIX to xm_defines. -Fri Mar 10 13:53:46 1995 Jim Wilson +Mon Apr 6 21:49:57 1998 Bob Manson - * reorg.c (steal_delay_list_from_target): Exit at the top if the - branch in SEQ is not a single set. + * 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. - * sh.md (movdi define_split, movdf define_split): Correct indentation - and formatting. Make the condition fail if an operand is a MEM - with an auto-inc address. + * Makefile.in (USE_COLLECT2): It's named collect2 now, not ld. + (ld:) Deleted. + (install-collect2): Install as collect2, not ld. - * varasm.c (copy_constant): Copy operand of ADDR_EXPR if it is a - constant. + * configure.in(will_use_collect2): It's named collect2 now. + + * collect2: Remove checks to see if we were invoked recursively. + (collect_execute): Use _spawnvp under cygwin32. + +Mon Apr 6 17:23:41 1998 Jim Wilson + + * haifa-sched.c (build_control_flow): Set unreachable for block whose + only predecessor is itself. + +Mon Apr 6 16:08:04 1998 Kaveh R. Ghazi + + * 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. + + * Makefile.in (c-parse.o, cccp.o, cexp.o, protoize.o, unprotoize.o): + Depend on system.h. + + * objc/Make-lang.in (objc-parse.o): Likewise. + +Mon Apr 6 14:59:58 1998 Kaveh R. Ghazi + + * 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. + + * genoutput.c (process_template): Use ATTRIBUTE_UNUSED in place + of __attribute__. + +Mon Apr 6 07:17:52 1998 Catherine Moore + + * combine.c (can_combine_p): Include successor in volatile test. + +Mon Apr 6 14:16:33 1998 J"orn Rennecke + + * sh.h (CASE_VECTOR_SHORTEN_MODE): Fix logic when to set + offset_unsigned. + +Mon Apr 6 02:03:29 1998 Jeffrey A Law (law@cygnus.com) + + * objc/objc-act.c (encode_aggregate_within): Avoid GNU extensions + in prototype and definition. + +Mon Apr 6 00:48:56 PDT 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Mon Apr 6 00:08:50 1998 Richard Henderson + + * alpha.c (alpha_expand_block_clear): Add missing offset arg to + alpha_expand_unaligned_store_words. + +Sun Apr 5 21:31:24 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. 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. + +Sun Apr 5 18:45:51 PDT 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sun Apr 5 16:31:10 1998 Richard Henderson + + * configure.in (alpha-dec-osf*): Match osf1.3 correctly. + +Sun Apr 5 16:53:37 1998 Don Bowman + + * configure.in (mips-wrs-vxworks): New target. + +Sat Apr 4 23:34:32 PST 1998 Jeff Law (law@cygnus.com) - * mips/abi64.h (SETUP_INCOMING_VARARGS): Correct arguments to - move_block_from_reg call. + * expmed.c (synth_mult): The value -1, has no zeros, so it can + never have the form ...011. - * expr.c (expand_assignment): When offset is zero, make new MEM - before setting MEM_VOLATILE_P. + * version.c: Bump for snapshot. - * reload.c (find_reloads, case 'o'): Accept a fully reloaded - auto-increment address. +Sat Apr 4 20:16:46 1998 Richard Henderson - * combine.c (max_uid_cuid): New static variable. - (INSN_CUID): Call abort if INSN is out of range. - (combine_instructions): Set max_uid_cuid. Set uid_cuid directly - instead of through INSN_CUID. - (get_last_value): Use prev_real_insn instead of prev_nonnote_insn. - Ignore USE insns generated by combine. + * 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. -Fri Mar 10 13:47:08 1995 Rod Barman +Sat Apr 4 19:08:37 1998 Richard Henderson - * m68k/fpgnulib.c (__fixdfsi): Catch values < 0.5 in magnitude. + * 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. -Fri Mar 10 12:02:33 1995 Ian Lance Taylor +Sat Apr 4 18:07:16 1998 David Mosberger-Tang (davidm@mostang.com) - * fixincludes: Fix `typedef struct term;' on hppa1.1-hp-hpux9. + * 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. -Fri Mar 10 05:50:11 1995 Oliver Kellogg (Oliver.Kellogg@RST13.DASA.DBMAIL.d400.de) +Sat Apr 4 17:42:05 1998 Richard Henderson - * 1750a.c (sectname): Reverse Init and Normal. - (print_operand_address, case PLUS): Add case for LABEL_REF. - (print_operand_address, case LABEL_REF): Split fom SYMBOL_REF. - (print_operand_address, case CODE_LABEL): New case. - (ASM_FILE_END): Delete. - * 1750a.h (FUNCTION_EPILOGUE): Restore stack before freeing local vars. - (DEFAULT_SIGNED_CHAR): Now 1. - (DATA_SECTION_ASM_OP): Use pseudo-op for read-only data (later copied). - (JUMP_TABLES_IN_TEXT_SECTION): Define. - (ASM_OUTPUT_ASCII): Split into multiple lines if long. - (ASM_OUTPUT_{CHAR,SHORT,INT,LONG_INT}): Split up. - (ASM_OUTPUT_COMMON): Call check_section. + * 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 Mar 9 12:46:53 1995 Michael Meissner +Sat Apr 4 17:04:41 1998 Richard Henderson - * rs6000.md (movsf): Do not call truncdfsf2 for non PowerPC - when expanding a store to memory and -msoft-float was used. + * configure.in (alpha-*-linux-*): Undo tm_file changes from gcc2 merge. -Thu Mar 9 08:51:35 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Sat Apr 4 13:50:01 1998 Richard Henderson - * c-decl.c (start_function): Handle new parameter ATTRIBUTES. - * c-tree.h (start_function): Add new parameter. - * c-lang.c (finish_file): Pass new parm to start_function. - * objc-act.c (build_module_descriptor, really_start_method): Likewise. - * c-parse.in (fndef, nested_function): Pass prefix_attributes - to start_function. - (setspecs): Save prefix_attributes in declspec_stack. - (decl rules): Restore prefix_attributes along with current_declspecs. - (setattrs): Concatenate prefix_attributes to previous value. - * c-common.c (decl_attributes): Handle prefix and suffix attributes - the same way. + * haifa-sched.c (split_block_insns): Don't supress insn splitting + on subsequent passes. - * print-tree.c (print_node): Fix typo in printing large INTEGER_CST. + * 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. - * varasm.c (assemble_variable): Consistently use DECL_SIZE for - everything. +Sat Apr 4 13:32:08 1998 Richard Henderson - * c-typeck.c (convert_for_assignment): Fix typo in testing for - pointer to function type. + * configure.in (alpha-*-linux-gnu*): Undo Feb 3 change brought in + from gcc2 merge. - * varasm.c (record_constant_1): Handle NON_LVALUE_EXPR. - Rewrite to use switch instead of if/then/elseif/else. +Sat Apr 4 10:23:41 1998 Jeffrey A Law (law@cygnus.com) -Wed Mar 8 18:21:51 1995 Paul Eggert + * Check in merge from gcc2. See ChangeLog.11 and ChangeLog.12 + for details. - * cccp.c (do_include): Fix type typo: pcfbuflimit is char *, not int. + * haifa-sched.c: Mirror recent changes from gcc2. -Wed Mar 8 17:30:29 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +Fri Apr 3 00:17:01 1998 Jeffrey A Law (law@cygnus.com) - * fold-const.c (force_fit_type): Always propagate OVERFLOW. + * Makefile.in (insn*.o): Depend on system.h. - * rtl.def (INLINE_HEADER): Add new "e" field. - * rtl.h (FORCED_LABELS): New field; other fields adjusted. - (gen_inline_header_rtx): New parm FORCED_LABELS. - * emit-rtl.c (gen_inline_header): Add new parm FORCED_LABELS. - * integrate.c (initialize_for_inline, output_inline_function): - Handle FORCED_LABELS. + * pa.c (output_global_address): Initialize base. + * pa.h (GO_IF_LEGITIMATE_ADDRESS): Initialize index. -Wed Mar 8 13:47:20 1995 Jason Merrill (jason@cygnus.com) +1998-04-03 Mike Stump - * alpha.h (WORD_SWITCH_TAKES_ARG): Add -rpath. - (LINK_SPEC): Pass through -taso and -rpath. - * alpha/osf12.h (LINK_SPEC): Ditto. + * 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. -Wed Mar 8 09:59:56 1995 Michael Meissner +Thu Apr 2 18:00:52 1998 Jim Wilson - * rs6000/eabi.asm: Rewrite so that the initialized pointers go - into the .got2 section, which allows eabi.asm to be assembled with - the -mrelocatable option. Move the data picked up from the bl - instruction to before the traceback tag. + * i386.md (movqi+1): Change alternative 1 from *r/r to *r/*rn. - * rs6000/sysv4.h (CPP_SPEC): Define _RELOCATABLE if -mrelocatable - switch is used. +1998-04-02 Vladimir N. Makarov - * libgcc2.c (__new_handler): Don't initialize the pointer variable - with the address of __default_new_handler, which may not work in - some shared library mechanisms. - (__builtin_new): If __new_handler is NULL, call the function - __default_new_handler. + * ginclude/va-i960.h (va_end): Change void * to void. -Tue Mar 7 17:34:59 1995 Ian Lance Taylor +Thu Apr 2 13:51:10 1998 Kaveh R. Ghazi - * i960.h (PROCESS_PRAGMA): Define. - (ROUND_TYPE_ALIGN): Pass maximum of COMPUTED and SPECIFIED to - i960_round_align. - (ROUND_TYPE_SIZE): Delete. - * i960.c (process_pragma): Uncomment, and rewrite for gcc 2. - (i960_round_size): Delete. - (i960_round_align): Don't adjust suggested alignment downward. - Restrict alignment to value set by #pragma align. + * Makefile.in (choose-temp.o): Depend on system.h. -Tue Mar 7 12:14:46 1995 Doug Evans + * choose-temp.c: Include system.h when IN_GCC. - * configure (sparc64-*-elf): Add crtbegin.o, crtend.o to extra_parts. - * sparc/sp64-elf.h (TARGET_VERSION): Define. - (CPP_PREDEFINES): Delete sun, sparc, unix. Delete OS assertions. - (ASM_SPEC): Define. - (LINK_SPEC): Delete solaris stuff, this is an embedded target. - (STARTFILE_SPEC, ENDFILE_SPEC): Define. +Thu Apr 2 02:37:07 1998 Joern Rennecke (amylaar@cygnus.co.uk) + Richard Henderson -Mon Mar 6 17:54:01 1995 Doug Evans + * reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS. + (move_replacements): New function. + * reload.h: Prototype it. - * Makefile.in (install-common): Fix typo in installation of cpp. - Likewise with gcc-cross. + * alpha.h (LEGITIMIZE_RELOAD_ADDRESS): New definition. -Mon Mar 6 02:29:05 1995 Jeffrey A. Law +Thu Apr 2 01:01:34 1998 Richard Henderson - * pa.md (movsicc): New expander. + * configure (alpha-*-linuxecoff, alpha-*-linux-gnulibc1): + Run fixincludes. -Fri Mar 3 13:34:20 1995 Michael Meissner (meissner@cygnus.com) + * 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. - * rs6000/sysv4.h (ASM_SPEC): If -mrelocatable was passed to - compiler, pass it on to the assembler. +Wed Apr 1 22:26:22 1998 Jeffrey A Law (law@cygnus.com) -Fri Mar 3 12:11:28 1995 Ian Lance Taylor + * fold-const.c optimze_bit_field_compare): Initialize rnbitpos, + rnbitsize, rnmode and rinner. + (make_range): Initialize type. + (fold): Initialize arg0, arg1 and varop. - * fixincludes: Add fixes for VxWorks header files. - * ginclude/stddef.h: If VxWorks typedef macros are defined, invoke - them as appropriate. + * function.c (instantiate_virtual_regs_1): Initialize offset, regnoi + and regnor. + (expand_function_start): Initialize last_ptr. -Fri Mar 3 05:48:54 1995 Paul Eggert + * stor-layout.c (layout_record): Initialize desired_align. + (get_best_mode): Initialize unit. - * cccp.c (dump_single_macro): Fix typo: % wasn't properly - doubled in printf formats. + * tree.c (copy_node): Initialize length. -Thu Mar 2 19:44:02 1995 Jason Merrill + * c-lex.c (yylex): Initialize traditional_type, ansi_type and type. - * expr.c (expand_expr, CLEANUP_POINT_EXPR): Force the operand out - of memory before running cleanups. + * caller-save.c (insert_save_restore): Initialize pat, code and + numregs. -Thu Mar 2 19:15:24 1995 Paul Eggert + * emit-rtl.c (push_to_sequence): Initialize top. + (push_topmost_sequence): Likewise. - * cccp.c (rescan): Prevent accidental token-pasting to - get !=, *=, /=, ==, or ^=. + * genattrtab.c (simplify_by_exploding): Initialize defval. -Thu Mar 2 15:37:13 1995 Jason Merrill + * profile.c (branch_prob): Initialize dest. - * c-typeck.c (build_binary_op): Avoid spurious warning - comparing enumerator to unsigned variable. + * rtl.h (note_stores): Remove duplicate prototype. + (GEN_INT): Re-instate cast of second arg to HOST_WIDE_INT. -Thu Mar 2 18:18:38 1995 J.T. Conklin + * cplus-dem.c (gnu_special): Don't get confused by . + strings that are not actually lengths. - * m68k.md (sqrtsf2,sqrtdf2): Use fp precision specifiers. + * 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 -Thu Mar 2 18:09:01 1995 Stephen L Moshier (moshier@world.std.com) + * genoutput.c (process_template): Mark operands in the generated + function as potentially unused if compiling with GNU CC. - * c-lex.c (yylex, case !NOT_FLOAT): Remove previous change. + * i386/freebsd-elf.h (CPP_PREDEFINES): Update from FreeBSD folks. -Thu Mar 2 15:26:50 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * pa.md (reload peepholes): Remove unused variable "mode". - * Makefile.in (bootstrap*): Pass new STAGE_PREFIX to recursive makes. +Wed Apr 1 17:06:19 1998 Nick Clifton -Wed Mar 1 14:52:16 1995 Ian Lance Taylor + * 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. - * i960/i960-coff.h (ASM_FILE_START): Define. - (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): Define. - (EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS): Define. - (CTORS_SECTION_FUNCTION, DTORS_SECTION_FUNCTION): Define. - (INT_ASM_OP): Define. - (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Define. - * i960/vx960-coff.h (CPP_PREDEFINES): Define. - (CPP_SPEC): Define. - (CC1_SPEC): Default to -mca. +Wed Apr 1 14:38:10 1998 Jim Wilson -Wed Mar 1 11:10:54 1995 Michael Meissner (meissner@cygnus.com) + * config/mips/iris6.h (MD_EXEC_PREFIX): Set to /usr/bin/. + (MD_STARTFILE_PREFIX): Unset. - * rs6000/rs6000.c (output_prologue): Do not emit the word that - gives the PC relative location to the local GOT table for the - -mrelocatable option here. - * rs6000/sysv4.h (ASM_DECLARE_FUNCTION_NAME): Emit it here. +1998-04-01 Mark Mitchell - * t-eabi (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Build -msoft-float - and -mrelocatable versions of the library. + * varasm.c (make_decl_rtl): Update the DECL_ASSEMBLER_NAME for a + entity in a local scope. - * rs6000/powerpc.h (CPP_PREDEFINES): Define the cpu and machine as - powerpc, not rs6000. + * fold-const.c (fold): Call truthvalue_conversion for values which + are folded to boolean type. - * libgcc2.c (_unwind_function): Clone for powerpc, using the - PowerPC mnemonics. +Wed Apr 1 06:09:53 1998 Jeffrey A Law (law@cygnus.com) - * rs6000/rs6000.md (uminsi3, umaxsi3): Silence warnings that - -2147483648 is too large to fit in a signed integer on 32-bit - hosts. + * 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. -Wed Mar 1 06:48:31 1995 Richard Kenner +Wed Apr 1 08:33:44 1998 Manfred Hollstein - * fold-const.c (decode_field_reference): Don't check TREE_CODE - of EXP; let get_inner_reference decide if have reference. - Allow no bit reference if have AND_MASK. - (all_ones_mask_p): Use tree_int_cst_equal, not operand_equal_p. - (unextend): New function. - (fold_truthop): For constant cases, use new function, rework - conversion, and warn if comparison can never be true. + * fixincludes (limits.h): Fix nested comments in Motorola's + limits.h and sys/limits.h. - * expr.c (store_expr): Do conversion in two steps for promoted lhs. +Tue Mar 31 16:57:33 1998 Jim Wilson -See ChangeLog.9 for earlier changes. + * alpha.c (alpha_expand_unaligned_load): Use tgt instead of addr + as dest of expand_binop call. + + * alpha.md (extzv): Correct check for valid operand[2] values. + + * profile.c (branch_prob): Add code to recognize HPPA tablejump entry + branch. + + * toplev.c (rest_of__compilation): Call init_recog_no_volatile at end. + +Mon Mar 30 13:11:05 1998 Stan Cox + + * libgcc2.c: (__main, __do_global_dtors, __do_global_ctors): + For __CYGWIN32__ use the versions in winsup/dcrt0.cc. + + * gcc.c, cccp.c, cpplib.c, collect2.c (GET_ENVIRONMENT): Added. + cygwin32 can override this to allow both unix and win32 style PATHs. + + * i386/xm-cygwin32.h (GET_ENVIRONMENT): Defined to allow win32 + style environment paths. + +Mon Mar 30 14:43:20 1998 Kaveh R. Ghazi + + * 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. + + * 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. + +Mon Mar 30 11:06:45 1998 Jim Wilson + + * README.gnat: Add lang_print_xnode definition. + +Mon Mar 30 11:12:24 1998 Andreas Schwab + + * config/m68k/m68k.c (standard_68881_constant_p): Don't use + fmovecr on the 68060. + +Mon Mar 30 00:21:03 1998 Jeffrey A Law (law@cygnus.com) + + * genemit.c (DONE): Rework so that it works in the true arm if + an if-else conditional. + (FAIL): Likewise. + +Sun Mar 29 12:45:23 1998 Jeffrey A Law (law@cygnus.com) + + * rs6000.c: Do not include stdioh or ctype.h anymore. + + * 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. + + * 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. + + * collect2.c (is_in_list): Wrap inside COLLECT_EXPORT_LIST ifdef. + + * local-alloc.c (reg_classes_overlap_p): Delete dead function. + + * tree.h (lang_print_xnode): Provide prototype. + +Sat Mar 28 23:50:44 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sun Mar 29 00:42:21 1998 Jeffrey A Law (law@cygnus.com) + + * objc/sendmsg.c (__objc_block_forward): Add braces for return + value if INVISIBLE_STRUCT_RETURN. + + * pa.c (arith_double_operand): Fix parens. + + * haifa-sched.c (print_pattern): Correct arg to sprintf. + + * Makefile.in (libgcc1.null): Make return type for __foo void. + +Sat Mar 28 14:37:20 1998 Jeffrey A Law (law@cygnus.com) + + * pa.h: Add declarations for many functions defined in pa.c. + + * genpeep.c (main): Remove unused variable 'i' from the generated + file. + + * 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. + + * integrate.c (copy_rtx_and_substitute): Rework to avoid need for + unused "junk" variable. + + * genattrtab.c (write_complex_function): Add a default case in + generated switch statement to keep -W -Wall quiet. + +Sat Mar 28 10:47:21 1998 Nick Clifton + + * invoke.texi: Document more ARM and Thumb command line options. + + * config/arm/xm-thumb.h: New file. + +Sat Mar 28 01:37:33 1998 Craig Burley + + * stmt.c (expand_expr_stmt): Must generate code for + statements within an expression (gcc's `({ ... )}') + even if -fsyntax-only. + +Sat Mar 28 01:06:12 1998 Bernd Schmidt + Jeffrey A Law (law@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 + instead. + +Sat Mar 28 00:21:37 1998 Jeffrey A Law (law@cygnus.com) + + * i386/freebsd.h (CPP_PREDEFINES): Remove __386BSD__. + (DWARF2_UNWIND_INFO): Define to zero. + +Fri Mar 27 16:04:49 1998 Michael Meissner + + * 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. + + * 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. + +Fri Mar 27 18:08:21 1998 J"orn Rennecke + + * sh.c (find_barrier): Fix calculations for alignment increase. + +Fri Mar 27 08:56:52 1998 Manfred Hollstein + + * 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. + +Fri Mar 27 00:49:46 1998 Jeffrey A Law (law@cygnus.com) + + * regclass.c (reg_scan_mark_refs): Be more selective about + when we mark a register with REGNO_POINTER_FLAG. + +Thu Mar 26 23:00:11 1998 J"orn Rennecke + + 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. + +Thu Mar 26 18:34:13 1998 J"orn Rennecke + + * regclass.c (record_reg_classes): '?' increases cost by two. + + * reload.c (find_reloads): Double previous costs. Output + reloads cost one unit extra. + + * reload1.c (eliminate_regs): Delete LOAD_EXTENDED_OP code that + boiled down to && ! 0. + + * reload.c (find_equiv_reg): Also consider a goal offset from the + frame pointer to be constant. + +Thu Mar 26 17:34:46 1998 J"orn Rennecke + + * sh.h (OPTIMIZATION_OPTIONS): Define. + +Thu Mar 26 00:19:47 1998 Richard Henderson + + * combine.c (make_compound_operation): Simplify (subreg (*_extend) 0). + +Wed Mar 25 23:53:11 1998 Jeffrey A Law (law@cygnus.com) + + * pa.c (pa_adjust_cost): Avoid redundant calls to get_attr_type. + +Wed Mar 25 13:40:48 1998 Jim Wilson + + * 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. + +Wed Mar 25 16:09:01 1998 Michael Meissner + + * rs6000.h (FUNCTION_ARG_PADDING): Cast result to be enum + direction. + (function_arg_padding): Declare. + + * rs6000.c: Include system.h. + (function_arg_padding): Change return type to int, cast enum's to + int. + + (From Kaveh R. Ghazi ) + * collect2.c (scan_prog_file): Add explicit braces to avoid + ambiguous `else'. + + * dbxout.c (dbxout_type_fields): Add braces around empty body in + an if-statement. + (dbxout_type): Likewise. + + * 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'. + + * 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. + + * rs6000.md (udivmodsi4): Add explicit braces to avoid ambiguous + `else'. + +Wed Mar 25 10:05:19 1998 Nick Clifton + + * 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. + + * configure.in: Add Thumb-coff target. + * configure: Add Thumb-coff target. + * config.sub: Add Thumb-coff target. + +Wed Mar 25 10:30:32 1998 Jim Wilson + + * loop.c (scan_loop): Initialize move_insn_first to zero. + +Wed Mar 25 01:06:49 1998 Joel Sherrill (joel@OARcorp.com) + + * 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. + +Wed Mar 25 00:57:26 1998 Richard Kenner + + * pa.c (emit_move_sequence): If in reload, call find_replacement. + +Tue Mar 24 10:44:11 1998 Nick Clifton + + * Makefile.in (gcov$(exeext)): Support .exe extension to gcov. + + * 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. + +1998-03-24 Mark Mitchell + + * 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 Mar 24 12:13:18 1998 Kaveh R. Ghazi + + * 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. + + * 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. + +1998-03-24 Martin von Loewis + + * c-lang.c (lang_print_xnode): New function. + * objc/objc-act.c (lang_print_xnode): Likewise. + * print-tree.c (print_node): Call it + +Mon Mar 23 23:59:11 1998 H.J. Lu (hjl@gnu.org) + + * c-parse.in: Recognize protocol qualifiers in class + definitions for objc. + Include "output.h". + (yyerror): Remove redundant decl. + (yyprint): Fix prototype. + +Mon Mar 23 23:49:47 1998 Jeffrey A Law (law@cygnus.com) + + * cse.c (rtx_cost): Only call CONST_COSTS if it is defined. + + * stmt.c (unroll_block_trees): Free block_vector if needed. + +Mon Mar 23 23:26:42 1998 Philippe De Muyter + + * 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. + + * 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. + +1998-03-22 Mark Mitchell + + * tree.h (IS_EXPR_CODE_CLASS): New macro. + +Mon Mar 23 23:18:48 1998 Jeffrey A Law (law@cygnus.com) + + * h8300.h (CONST_COSTS): Remove definition. + (DEFAULT_RTX_COSTS): Define. + +Mon Mar 23 22:58:22 1998 Joel Sherrill (joel@OARcorp.com) + + * config/sh/rtems.h: Switched from ELF to COFF. + +Mon Mar 23 14:14:20 1998 J"orn Rennecke + + * freebsd.h (ASM_OUTPUT_ALIGN): Redefine. + +Sat Mar 21 23:52:56 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sun Mar 22 00:50:42 1998 Nick Clifton + Geoff Noer + + * Makefile.in: Various fixes for building cygwin32 native toolchains. + + * objc/Makefile.in: Various fixes for building cygwin32 native toolchains. + * objc/Make-lang.in: Likewise. + + * config/i386/xm-cygwin32.h (PATH_SEPARATOR): Set to a semi-colon. + +Sun Mar 22 00:21:46 1998 R. Ganesan + + * configure.in: Handle with-PACKAGE=no correctly + +Fri Mar 20 17:36:23 1998 Kaveh R. Ghazi + + * Makefile.in (alias.o, bitmap.o, c-aux-info.o, c-common.o, + c-decl.o, c-iterate.o, c-lang.o, c-lex.o, c-pragma.o, c-typeck.o, + caller-save.o, calls.o, collect2.o, combine.o, cse.o, dbxout.o, + dwarf2out.o, dwarfout.o, emit-rtl.o, except.o, explow.o, expmed.o, + expr.o, final.o, flow.o, function.o, getpwd.o, global.o, + integrate.o, jump.o, local-alloc.o, loop.o, optabs.o, pexecute.o, + prefix.o, print-rtl.o, print-tree.o, profile.o, real.o, recog.o, + reg-stack.o, regclass.o, regmove.o, reload.o, reload1.o, reorg.o, + rtl.o, rtlanal.o, sdbout.o, stmt.o, stor-layout.o, stupid.o, + tlink.o, toplev.o, tree.o, unroll.o, varasm.o, xcoffout.o): Depend + on system.h. + + * alias.c, bitmap.c, c-aux-info.c, c-common.c, c-decl.c, + c-iterate.c, c-lang.c, c-lex.c, c-pragma.c, c-typeck.c, + caller-save.c, calls.c, collect2.c, combine.c, cse.c, dbxout.c, + dwarf2out.c, dwarfout.c, emit-rtl.c, except.c, explow.c, expmed.c, + expr.c, final.c, flow.c, function.c, gcc.c, getpwd.c, global.c, + integrate.c, jump.c, local-alloc.c, loop.c, optabs.c, pexecute.c, + prefix.c, print-rtl.c, print-tree.c, profile.c, real.c, recog.c, + reg-stack.c, regclass.c, regmove.c, reload.c, reload1.c, reorg.c, + rtl.c, rtlanal.c, sched.c, sdbout.c, stmt.c, stor-layout.c, + stupid.c, tlink.c, toplev.c, tree.c, unroll.c, varasm.c, + xcoffout.c: Include system.h. Organize include ordering so + that stdarg/varargs comes before other system headers. Remove + spurious casts of functions assured of a prototype in system.h. + +Fri Mar 20 11:19:40 1998 Stan Cox + + * reg-stack.c (pop_stack): Define. Pops any register on the + regstack and adjusts regstack. + (compare_for_stack_reg): Use pop_stack. + +Thu Mar 19 23:51:01 1998 Jeffrey A Law (law@cygnus.com) + + * configure.in (hppa1.0-hp-hpux10): Handle threads for this + config too. + +Thu Mar 19 20:30:31 1998 Philippe De Muyter + + * libgcc2.c (exit): Do not call __bb_exit_func if HAVE_ATEXIT. + + * fold-const.c (fold): Replace sign-extension of a zero extended + value by a single zero extension. + +Thu Mar 19 00:58:07 1998 Jason Merrill + + * 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 Mar 19 13:39:52 1998 Michael Meissner + + * rs6000/sysv4.h (RELATIVE_PREFIX_NOT_LINKDIR): Undef for System V + and EABI. + +Thu Mar 19 10:10:36 1998 Kaveh R. Ghazi + + * final.c (shorten_branches): Add parentheses around +/- in + operand of &. + + * flow.c (life_analysis): Wrap variable `i' in macro ELIMINABLE_REGS. + +Thu Mar 19 09:15:17 1998 Manfred Hollstein + + * regclass.c (memory_move_secondary_cost): Wrap uses of + SECONDARY_INPUT_RELOAD_CLASS and SECONDARY_OUTPUT_RELOAD_CLASS + with #ifdef tests. + +Thu Mar 19 09:06:35 1998 Manfred Hollstein + + * config/m68k/m68k.md (addqi3): Fix typo gen_INT vs. GEN_INT. + + * flow.c (life_analysis): #include to make sure + size_t is defined. + * cplus-dem.c (demangle_function_name): Likewise. + +Thu Mar 19 09:00:01 1998 Manfred Hollstein + + * final.c (insn_noperands): Change type to unsigned int. + (final_scan_insn): Likewise for noperands; + properly check operand number boundaries. + +Wed Mar 18 16:20:30 1998 Richard Henderson + + * alpha.md (extzv): Don't reject register operands. Fix + mode of operand 1. + +Wed Mar 18 16:14:23 1998 Richard Henderson + + * dbxout.c (dbxout_function_end): Fix last change. The correct + predicate is ASM_OUTPUT_SECTION_NAME. + +Wed Mar 18 12:43:20 1998 Jim Wilson + + * sh.md (ashlsi_c-1): Delete 3rd argument to gen_ashlsi_c. + (ashlsi): Use match_dup 1 instead of match_operand 2. + +Wed Mar 18 13:46:07 1998 Richard Kenner + + * fold-const.c (operand_equal_for_comparison_p): See if equal + when nop conversions are removed. + +Wed Mar 18 13:42:01 1998 Richard Kenner + + * expr.c (expand_expr, case COND_EXPR): If have conditional move, + don't use ORIGINAL_TARGET unless REG. + +Wed Mar 18 16:53:19 1998 J"orn Rennecke + + * netbsd.h (ASM_OUTPUT_ALIGN): Redefine. + +Wed Mar 18 12:43:20 1998 Jim Wilson + + * 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. + +Wed Mar 18 09:52:56 1998 Richard Henderson + + * 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. + + * alpha/xm-vms.h (HAVE_ATOLL): Define. + Reported by Klaus Kaempf . + +Wed Mar 18 09:56:26 1998 Kaveh R. Ghazi + + * c-lang.c (finish_file): Wrap variable `void_list_node' with macro + test !ASM_OUTPUT_CONSTRUCTOR || !ASM_OUTPUT_DESTRUCTOR. + + * calls.c (emit_call_1): Wrap variable `already_popped' with macro + test !ACCUMULATE_OUTGOING_ARGS. + + * collect2.c (write_c_file_glob): Wrap function definition in + macro test !LD_INIT_SWITCH. + + * combine.c (try_combine): Wrap variables `cc_use' and + `compare_mode' in macro test EXTRA_CC_MODES. + + * 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'. + + * 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. + + * dwarf2out.c (add_subscript_info): Wrap variable `dimension_number' + in macro test !MIPS_DEBUGGING_INFO. + + * expr.c (expand_builtin_setjmp): Move declaration of variable `i' + into the scope where it is used. Wrap empty else-statement body + in braces. + + * fix-header.c: Fix typo in comment. + (inf_skip_spaces): Cast results of INF_UNGET to (void). + (check_protection, main): Likewise. + + * flow.c (find_basic_blocks_1): Remove dangling comment text. + + * function.c (contains): Wrap prototype and definition in macro + test HAVE_prologue || HAVE_epilogue. + (fixup_var_refs_1): Remove unused variable `width'. + + * gen-protos.c (main): Remove unused variable `optr'. + + * haifa-sched.c (debug_control_flow): Remove unused variable `j'. + + * libgcc2.c (__udiv_w_sdiv): Provide dummy return value of 0. + (__sjpopnthrow): Remove unused variable `jmpbuf'. + (__throw): Remove unused variable `val'. + + * protoize.c: Check for a previously existing definition before + defining *_OK macros. + + * scan-decls.c (scan_decls): Remove unused variable `old_written'. + +Tue Mar 17 00:45:48 1998 J"orn Rennecke + + * vax.h (ADDR_VEC_ALIGN): Define. + +Mon Mar 16 15:57:17 1998 Michael Meissner + + * gcc.c (default_arg): Don't wander off the end of allocated + memory. + + (From Geoffrey Keating ) + * rs6000.c (small_data_operand): Ensure that any address + referenced relative to the small data area is inside the SDA. + +Mon Mar 16 12:55:15 1998 Jim Wilson + + * config/m68k/netbsd.h (ASM_SPEC): Add %{m68060}. + +Mon Mar 16 15:50:20 EST 1998 Andrew MacLeod + + * 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. + +Mon Mar 16 11:16:50 1998 Jim Wilson + + * README.gnat: New file. + +Mon Mar 16 11:14:20 1998 Andreas Schwab + + * config/m68k/m68k.c: Include 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. + + * 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. + +Sun Mar 15 22:30:44 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Fri Mar 13 11:30:12 1998 Andreas Schwab + + * config/m68k/m68k.h (CONST_OK_FOR_LETTER_P): Fix logic in range + check for 'M' constraint. + +Thu Mar 12 14:47:14 1998 Jim Wilson + + * cccp.c (create_definition): If pedantic, call pedwarn for macro + varargs feature. + +Thu Mar 12 13:43:25 1998 Bernd Schmidt + + * 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. + +Thu Mar 12 15:13:16 1998 Kaveh R. Ghazi + Richard Earnshaw + Nick Clifton + + * tm.texi (DEFAULT_RTX_COSTS): Document new macro. + + * arm.h (DEFAULT_RTX_COSTS): Define instead of RTX_COSTS. + + * cse.c (rtx_cost): Provide a default case in an enumeration + switch, and call DEFAULT_RTX_COSTS if it's defined. + +Thu Mar 12 10:02:38 1998 Manfred Hollstein + + * basic-block.h (compute_preds_succs): Change return type in + prototype to void. + * flow.c (compute_preds_succs): Likewise in function definition. + + * regmove.c (find_matches): Cast char used as array index to unsigned char + to supress warning. + +Thu Mar 12 09:39:40 1998 Manfred Hollstein + + * i386.h (RTX_COSTS): Insert braces around nested if. + (ADDITIONAL_REGISTER_NAMES): Insert braces around structured + elements. + + * gcc.c (default_compilers): Properly put brackets around array elements in + initializer. + + * getopt.c (_getopt_internal): Add explicit braces around nested if; + reformatted. + + * 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. + +Thu Mar 12 09:25:29 1998 Manfred Hollstein + + * bitmap.c (bitmap_element_allocate): Remove unused parameter; + change callers accordingly. + + * cplus-dem.c (arm_special): Remove unused parameter work in prototype + and definition; change all callers accordingly. + + * except.c (init_eh): Avoid assignment of unused return value of + build_pointer_type; cast it to void, instead, and remove unused + variable type. + + * gcc.c (lang_specific_driver): Define prototype only #ifdef + LANG_SPECIFIC_DRIVER. + (temp_names): Define only #ifdef MKTEMP_EACH_FILE. + + * genoutput.c (output_epilogue): Initialize next_name to 0. + + * real.c (efrexp): #if 0 prototype and function definition. + (eremain): Likewise. + (uditoe): Likewise. + (ditoe): Likewise. + (etoudi): Likewise. + (etodi): Likewise. + (esqrt): Likewise. + + * reload.c (push_secondary_reload): Define prototype only + #ifdef HAVE_SECONDARY_RELOADS. + + * varasm.c (assemble_static_space): Define rounded only + #ifndef ASM_OUTPUT_ALIGNED_LOCAL. + +Thu Mar 12 09:11:35 1998 Manfred Hollstein + + * i386.md (andsi): Add default case in enumeration switch. + (iorsi3): Likewise. + (iorhi3): Likewise. + (xorsi3): Likewise. + +Thu Mar 12 08:37:02 1998 Manfred Hollstein + + * c-decl (finish_struct): Change type of min_align to unsigned. + + * cplus-dem.c (demangle_function_name): Change type of variable i to size_t; + remove unused variable len. + + * 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. + + * enquire.c (bitpattern): Change type of variable i to unsigned. + + * final.c (output_asm_insn): Don't cast insn_noperands to unsigned. + + * flow.c (life_analysis): Change type of variable i to size_t; + remove unused variable insn. + + * 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. + + * genemit.c (output_init_mov_optab): Change type of variable i to size_t. + + * genopinit.c (get_insn): Change type of variable pindex to size_t. + + * genrecog.c (add_to_sequence): Change type of variable i to size_t. + + * global.c (global_alloc): Change type of variable i to size_t. + + * regclass.c (init_reg_sets): Change type of variables i and j to unsigned. + + * stmt.c (expand_end_bindings): Change type of variable i to size_t. + (expand_end_case): Change type of variable count to size_t. + + * 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. + + * varasm.c (assemble_variable): Change type of variable align to size_t. + (const_hash_rtx): Change type of variable i to size_t. + +1998-03-11 Mark Mitchell + + * dbxout.c (dbxout_type_methods): Only treat TYPE_METHODS as a + TREE_VEC if that's what it really is. + +Wed Mar 11 15:16:01 1998 Michael Meissner + + * {haifa-,}sched.c (rank_for_schedule): Only take void * arguments + as per ISO C spec. + +Wed Mar 11 12:05:20 1998 Teemu Torma + + * 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. + +Wed Mar 11 18:26:25 1998 J"orn Rennecke + + * 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. + +Wed Mar 11 15:07:18 1998 J"orn Rennecke + + * final.c (shorten_branches): Remove conditionalizing on + SHORTEN_WITH_ADJUST_INSN_LENGTH + * sh.h, pa.h (SHORTEN_WITH_ADJUST_INSN_LENGTH): Remove. + +Wed Mar 11 02:37:41 1998 Jeffrey A Law (law@cygnus.com) + + * flow.c (find_basic_blocks_1): Keep the cfg accurate when removing + an unconditional jump around deleted blocks. + +Mon Mar 9 12:02:23 1998 Jim Wilson + + * profile.c (branch_prob): If see computed goto, call fatal instead of + abort. + + * config/mips/sni-svr4.h (CPP_PREDEFINE): Add -DSNI and -Dsinix. + + * configure.in (alpha-dec-osf): Add default case for osf* to switch. + Patch from Bruno Haible. + + * function.c (put_reg_into_stack): Copy MEM_IN_STRUCT_P from new. + (assign_parms): Set aggregate if hide_last_arg and last_named. + +Mon Mar 9 19:57:56 1998 J"orn Rennecke + + * final.c (shorten_branches): Initialize insn_addresses. + +Mon Mar 9 14:10:23 1998 J"orn Rennecke + + * sh.h (MUST_PASS_IN_STACK): Define. + +Sun Mar 8 13:01:56 1998 Jeffrey A Law (law@cygnus.com) + + * final.c (shorten_branches): Fix minor logic error in + ADDR_DIFF_VEC shortening support. + +Sun Mar 8 02:17:42 PST 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 + + * 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 + + * m32r.md (right): Correctly check for length == 2, not 1. + +Fri Mar 6 14:00:04 1998 Kaveh R. Ghazi + + * 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 + + * configure.in: Remove duplicate uses of AC_PROG_CC and + AC_PROG_MAKE_SET. + +Fri Mar 6 00:59:30 1998 Richard Henderson + + * 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 + + * 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 + + * 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. + + * 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. + + * mips/mips.md (movdi): Add parentheses around && within ||. + (movsf, movdf): Likewise. + (branch_zero, branch_zero_di): Add default case in + enumeration switch. + + +Thu Mar 5 02:45:48 1998 Richard Henderson + + * 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. + +Thu Mar 5 02:41:27 1998 Richard Henderson + + * reload.c (find_reloads): Always force (subreg (mem)) to be + reloaded if WORD_REGISTER_OPERATIONS. + +Thu Mar 5 02:14:44 1998 Richard Henderson + + * 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. + +Thu Mar 5 00:05:40 1998 Jeffrey A Law (law@cygnus.com) + + * cccp.c (main): Avoid undefined behavior when setting pend_includes + and pend_files. + +Wed Mar 4 21:58:25 1998 Franz Sirl + + * 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 + +Wed Mar 4 12:11:36 1998 Jim Wilson + + * mips.md (movdf_internal1a): Fix misplaced parenthesis in condition. + +Wed Mar 4 18:47:48 1998 J"orn Rennecke + + * final.c (final_scan_insn, case CODE_LABEL: Cleanup. + +Wed Mar 4 15:51:19 1998 J"orn Rennecke + + * final.c (shorten_branches): Tag the loop alignment onto the + first label after NOTE_INSN_LOOP_BEG even if there is an + intervening insn. + +Tue Mar 3 21:48:35 1998 J"orn Rennecke + + * final.c (insn_current_reference_address): + Use SEQ instead of BRANCH as argument to align_fuzz, to get a + proper alignment chain. + + * 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. + +Tue Mar 3 14:27:23 1998 Kaveh R. Ghazi + + * sparc.c (ultrasparc_adjust_cost): Add default case in + enumeration switch. + + * sparc.h: Add prototypes for extern functions defined in + sparc.c. + +Tue Mar 3 10:00:11 1998 Nick Clifton + + * toplev.c: Only generate .dbr file when dumping RTL if + DEALY_SLOTS is defined. + +Tue Mar 3 07:36:37 1998 Manfred Hollstein + + * reorg.c (fill_eager_delay_slots): Add new argument delay_list + in call to fill_slots_from_thread. + +Mon Mar 2 13:45:03 1998 Richard Henderson + + * alpha/linux.h (CPP_PREDEFINES): Correct connecting whitespace + to SUB_CPP_PREDEFINES. Reported by asun@saul4.u.washington.edu. + +Mon Mar 2 22:59:28 1998 J"orn Rennecke + + * 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) + + * version.c: Bump for snapshot. + +Mon Mar 2 00:52:18 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sun Mar 1 18:25:49 1998 Michael P. Hayes + + * reorg.c (fill_slots_from_thread): Don't steal delay list from target + if condition code of jump conflicts with opposite_needed. + + * 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 Mar 1 18:26:21 1998 Ken Rose (rose@acm.org) + + * reorg.c (fill_slots_from_thread): New parameter, delay_list. + All callers changed. + +Sun Mar 1 18:25:37 1998 Bruno Haible + + * 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. + +Sun Mar 1 18:06:21 1998 Jeffrey A Law (law@cygnus.com) + + * ginclude/va-ppc.h (va_arg): Fix typo in long long support. + + * i386.c (reg_mentioned_in_mem): Fix dangling else statement. + + * fold-const.c (fold_range_test): Always return a value. + +Sun Mar 1 17:57:34 1998 Mumit Khan + + * config/i386/winnt.c (i386_pe_unique_section): Put read-only + data in the text section unless READONLY_DATA_SECTION is defined. + +Sun Mar 1 17:48:46 1998 Jeffrey A Law (law@cygnus.com) + + * c-parse.in (undeclared variable error): Tweak error message to + be clearer. + +Sun Mar 1 10:22:36 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +1998-02-28 Mark Mitchell + + * final.c (final_scan_insn): Undo overzealous removal of `set'. + +Sat Feb 28 07:54:03 1998 Kaveh R. Ghazi + + * pa.h (CONST_COSTS): When checking the CONST_DOUBLE enumerated + case, add parentheses to specify the proper order of precedence in + the if-statement. + + + * 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 ||. + + * pa.h: Add prototypes for pa_reorg, symbolic_operand, + following_call, function_label_operand, lhs_lshift_cint_operand + and zdepi_cint_p. + + * pa.md: Add parentheses around && within ||. + + * cppalloc.c: Include stdlib.h. + + * cpperror.c (cpp_print_containing_files): Remove unused variable + `i'. Fix format specifier in fprintf. + + * cse.c (cse_around_loop): Add explicit braces to avoid + ambiguous `else'. + (delete_dead_from_cse): Wrap variable `tem' in macro HAVE_cc0. + + * expr.c (expand_expr): Add parentheses around && within ||. + + * 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. + + * 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. + + * integrate.c (expand_inline_function): Wrap variable + `cc0_insn' in macro HAVE_cc0. + + * jump.c (jump_optimize): Wrap variable `q' in macro + HAVE_cc0. Remove unused variable `prev1'. + + * 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. + + * local-alloc.c: Include stdlib.h. + (requires_inout): Add parentheses around assignment used + as truth value. + + * 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. + + * 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. + + * protoize.c: Include stdlib.h. + (substr): Add parentheses around assignment used as truth value. + (abspath): Likewise. + (shortpath): Likewise. + + * regmove.c (fixup_match_1): Add parentheses around assignment + used as truth value. + + * reload.c (push_secondary_reload): Remove unused variable `i'. + (find_reloads): Add parentheses around assignment used as truth + value. + + * reload1.c: Include stdlib.h. + + * 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. + + + * system.h: Remove sys/stat.h. + * gcc.c: Add sys/stat.h. + + * 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. + +Fri Feb 27 11:02:47 1998 Andreas Schwab + + * invoke.texi: Use @itemx for a secondary item in a @table. + + * config/m68k/m68k.md (movsf+1): Optimize moving a CONST_DOUBLE + zero. + +Thu Feb 26 00:13:21 1998 Ian Lance Taylor + + * choose-temp.c: Fix handling of sys/file.h to work in libiberty. + +Wed Feb 25 23:40:54 1998 Jeffrey A Law (law@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. + +Wed Feb 25 01:31:40 1998 Jeffrey A Law (law@cygnus.com) + + * c-parse.y (undeclared variable error): Tweak error message + to be clearer. + +Tue Feb 24 23:54:07 1998 Richard Henderson + + * 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. + + +Mon Feb 23 15:09:18 1998 Bruno Haible + * config.sub (sco5): Fix typo. + +Mon Feb 23 18:19:31 1998 Manfred Hollstein + + * 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. + +Mon Feb 23 10:47:39 1998 Robert Lipe + * 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. + +1998-02-23 Mike Stump + + * configure.in: Add support for i386-wrs-vxworks configuration. + * i386/vxi386.h: New file. + +Sun Feb 22 21:16:51 1998 Bruno Haible + + * 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. + +Sun Feb 22 20:58:19 1998 Jeffrey A Law (law@cygnus.com) + + * vms.h (SELECT_SECTION): Use TREE_CODE_CLASS correctly. + +1998-02-22 Paul Eggert + + * 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. + +Sun Feb 22 20:07:32 1998 Jim Wilson + + * iris5.h (DWARF2_UNWIND_INFO): Define to 0. + * iris5gas.h (DWARF2_UNWIND_INFO): Define to 1. + +Sun Feb 22 15:29:48 1998 Richard Henderson + + * objc/Object.m (-error): Call objc_verror with our va_list. + +Sun Feb 22 09:45:39 1998 Kaveh R. Ghazi + + * collect2.c (scan_prog_file): Completely cover uses of variable + `exports' with macro COLLECT_EXPORT_LIST. + +Sat Feb 21 20:36:23 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Fri Feb 20 16:22:13 1998 Michael Meissner + + * 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. + +1998-02-20 Jason Merrill + + * collect2.c (main): Still handle !do_collecting for non-AIX targets. + +1998-02-16 Mark Mitchell + + * toplev.c (rest_of_compilation): Do not defer the output of a + nested function. + +Fri Feb 20 10:39:47 1998 Michael Tiemann + + * ginclude/va-mips.h (va_arg): Remove trailing space after '\' + continuation character (line 243). + +Fri Feb 20 12:10:26 1998 Andreas Schwab + + * genrecog.c (main): Remove duplicated sentence in emitted comment. + +Thu Feb 19 22:36:53 1998 Andrey Slepuhin + David Edelsohn + + * 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. + +Thu Feb 19 22:36:52 1998 Robert Lipe + + * collect2.c (full_real_ld_suffix): #ifdef CROSS_COMPILE. + +1998-02-19 Mike Stump + + * Makefile.in: Use $tooldir for sys-include to match toplevel + configure. + +Thu Feb 19 01:32:37 1998 Jeffrey A Law (law@cygnus.com) + Richard Kenner + + * emit-rtl.c (gen_lowpart_common): Suppress last change if __complex__. + + * 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. + + * combine.c: Revert previous patch. + +1998-02-19 Paul Eggert + + * config/sparc/sol2-sld.h: New file. + * configure.in (sparc-*-solaris2*): Use it when using the + system linker. + +Thu Feb 19 00:46:59 1998 Jeffrey A Law (law@cygnus.com) + + * loop.c (force_movables): Fix typo. + +Thu Feb 19 08:26:30 1998 Manfred Hollstein + + * m88k.h: Change file pattern to match reality. + +Wed Feb 18 23:19:52 1998 Jeffrey A Law (law@cygnus.com) + + * varasm.c (output_constant_pool): Fix dumb thinko in last + change. + + * pa.h (ASM_OUTPUT_FUNCTION_PREFIX): Correctly translate from + a function name to a section name. + +1998-02-18 Doug Evans + + * 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. + +1998-02-18 Jim Wilson + + * c-decl.c (shadow_tag_warned): Call split_specs_attrs. + +Wed Feb 18 09:09:50 1998 Jeffrey A Law (law@cygnus.com) + + Remove this change until we can fix it correctly. + * collect2.c: Bracket declaration of 'exportf' and + 'full_real_ld_suffix'. + +Wed Feb 18 08:44:25 1998 Bernd Schmidt + + * Makefile.in (STAGESTUFF): Add genrtl.c, genrtl.h and gengenrtl. + +Tue Feb 17 23:30:20 1998 Bernd Schmidt + + * 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. + +Tue Feb 17 23:56:50 1998 Robert Lipe + + * sco5.h (ASM_OUTPUT_DOUBLE, ASM_OUTPUT_FLOAT, + ASM_OUTPUT_LONG_DOUBLE): Delete. Use the ones from i386.h + instead. + +Tue Feb 17 22:56:14 1998 Richard Henderson + + * 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. + +Tue Feb 17 22:37:22 1998 Kaveh R. Ghazi + + * 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'. + + * Makefile.in (fold-const.o): Depend on system.h. + + * Makefile.in (gcc.o): Depend on system.h, in accordance with last + change to gcc.c. + + * haifa-sched.c: Include "system.h" to get and . + (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'. + + * Makefile.in ($(SCHED_PREFIX)sched.o): Depend on system.h. + +Tue Feb 17 22:31:04 1998 Jeffrey A Law (law@cygnus.com) + + * loop.c (rtx_equal_for_loop_p): Add some braces to disambiguate + a dangling else clause. + +Tue Feb 17 21:28:12 1998 Gavin Koch + + * mips/mips.h (CAN_ELIMINATE): Don't eliminate the frame + pointer for the stack pointer in MIPS16 and 64BIT. + +Tue Feb 17 21:17:30 1997 J"orn Rennecke + + * 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. + +Tue Feb 17 10:14:32 1998 J"orn Rennecke + + * i386.md (adddi3): Add =!r,0,0,X alternative. + +Mon Feb 16 16:13:43 1998 David Edelsohn + + * rs6000.h (MY_ISCOFF): Add numeric value of U803XTOCMAGIC. + * x-aix31 (INSTALL): Delete. + +Mon Feb 16 09:24:32 1998 Gavin Koch + + * mips/mips.c (mips_expand_epilogue): Update tsize_rtx if + tsize changes to something other than zero. + +Mon Feb 16 09:11:48 1998 Gavin Koch + + * ginclude/va-mips.h: Replace casts of pointers to int with + casts of pointers to __PTRDIFF_TYPE__. + +Mon Feb 16 08:17:14 1998 John Carr + + * loop.c (strength_reduce, record_biv, record_giv): Use + HOST_WIDE_INT_PRINT_DEC to print CONST_INT values. + +1998-02-16 Jason Merrill + + * 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. + +Sun Feb 15 23:28:44 1998 Jeffrey A Law (law@cygnus.com) + + * 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. + +Sun Feb 15 21:33:55 1998 Kaveh R. Ghazi + + * 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". + + * 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. + +Sun Feb 15 17:05:41 1998 Jim Wilson + + * mips/mips.h (INITIAL_ELIMINATION_OFFSET): Readd Jun 6 change. + +Sun Feb 15 15:23:15 1998 John Carr + + * alias.c: Include and . + (init_alias_analysis): Pass NULL_RTX instead of 0 to record_set. + +Sat Feb 14 11:23:09 PST 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 + + * 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 + + * 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 + + * except.c (emit_throw): Lose throw_used. + +Fri Feb 13 20:36:05 1998 J"orn Rennecke + + * 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 + + * 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): + + * collect2.c: include when appropriate. + Bracket declaration of 'exportf' and 'full_real_ld_suffix'. + + * emit-rtl.c (prev_cc0_setter): Remove unused variable 'link'. + + * explow.c (plus_constant_for_output_wide): Remove unused variable + 'code'. + (memory_address): Remove unused variable 'orig_x'. + + * genattrtab.c (make_canonical): Remove unreferenced label 'cond:'. + (write_const_num_delay_slots): Remove unused variable 'i'. + + * genopinit.c (main): Remove unused variables 'dummy', 'insn_ptr'. + (gen_insn): Remove unused variable 'obstack_ptr'. + + * libgcc2.c (__bb_exit_func): Remove unused variables 'ret', + 'j', 'tmp', 'i'. + (__bb_exit_trace_func): Remove unused variable 'e'. + + * 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 (branch_prob): Remove unused variables 'insn', 'dest'. + + * 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'. + + * rtlanal.c (computed_jump_p): Remove unused variable 'computed_jump'. + + * sched.c (actual_hazard): Bracket declaration of 'this_cost'. + + * 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'. + + * tlink.c: Include , , /. + + * 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'. + + * i386/i386.h (ENCODE_SECTION_INFO): TREE_PUBLIC is an int, not + a string. + + * i386/sco5.h (ASM_OUTPUT_ASCII): Add parens for assignment used + as truth. + +Fri Feb 13 10:21:41 1998 J"orn Rennecke + + * combine.c (can_combine_p): Handle USEs in PARALLELs. + +Fri Feb 13 01:34:14 1998 H.J. Lu (hjl@gnu.org) + + * config/linux.h (LIB_SPEC): Add -lc for -shared if + USE_GNULIBC_1 is not defined. + * config/sparc/linux.h; Ditto. + + * config/sparc/linux64.h (LIB_SPEC): Add -lc for -shared. + + * config/alpha/linux-elf.h (LIB_SPEC): New. Defined if + USE_GNULIBC_1 is not defined. + +Fri Feb 13 01:29:29 1998 Franz Sirl + + * rs6000/sysv4.h (ENDFILE_SPEC): add missing %(endfile_linux) + for -mcall-linux + +Fri Feb 13 01:23:46 1998 Kaveh R. Ghazi + + * system.h: New file to get common systems includes and various + definitions and declarations based on autoconf macros. + +Fri Feb 13 00:46:19 1998 Jeffrey A Law (law@cygnus.com) + + * cccp.c (new_include_prefix): Correctly handle -I./. + +Thu Feb 12 20:16:35 1998 Michael Meissner + + * rs6000.md: Replace gen_rtx (CONST_INT,...) with GEN_INT. + +Thu Feb 12 16:45:17 1998 Robert Lipe + + * expr.c (expand_assignment): Correct typo exposed by -Wall. + offset should have been a truth value, not an assignment. + +Thu Feb 12 15:26:50 1998 Jeffrey A Law (law@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. + +Thu Feb 12 14:04:09 1998 Gavin Koch + + * mips.md (trucndihi2,truncdiqi2): Change these to support + mips16. + +Thu Feb 12 11:34:55 1998 Gavin Koch + + * mips/mips.c (movdi_operand): Direct referances to symbols + that arn't mips16 consts in mips16 mode arn't valid operands. + + * mips/mips.c (mips_move_2words): Add gprel handling. + +Thu Feb 12 11:18:37 1998 Gavin Koch + + * mips.md (extendsidi2): Allow extension to/from a non-mips16 + register. + +Thu Feb 12 00:04:16 1998 Marc Lehmann + + * i386.c: Conditionally include , , and + . + +Wed Feb 11 11:43:34 1998 Kaveh R. Ghazi + + * Makefile.in (WARN_CFLAGS): New variable. + (bootstrap, bootstrap2, bootstrap3, bootstrap4): Use it. + +1998-02-11 Mark Mitchell + + * config/i386/i386.c (reg_mentioned_in_mem): Don't abort when + falling through default case in switch. + (i386_aligned_p): Likewise. + +Wed Feb 11 12:59:56 1998 Lee Iverson + + * mips/mips.h (mips_abi_string): Correct typo in comment. + +Wed Feb 11 08:29:56 1998 Gavin Koch + + * mips/mips.md (movdi): These PLUS's need to be Pmode. + +Wed Feb 11 01:47:54 1998 Kaveh R. Ghazi + + * 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. + +Wed Feb 11 01:44:13 1998 Richard Henderson + + * stor-layout.c (layout_type): Do upper - lower in the native type, + so as to properly handle negative indices. + +Wed Feb 11 01:35:55 1998 Robert Lipe + + * 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. + + * 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'. + +Wed Feb 11 01:30:49 1998 Marc Lehmann + + * 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. + +Wed Feb 11 01:23:03 1998 John F. Carr + + * 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. + +Wed Feb 11 01:17:39 1998 Jeffrey A Law (law@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. + +1998-02-10 John F Carr + + * config/sparc/sparc.md (movdi_v8plus): Output stx on alternative + 1, fzero on alternative 8. + +Tue Feb 10 09:02:19 1998 Richard Kenner + + * rs6000.c (setup_incoming_varargs): Always set rs6000_sysv_varargs_p. + +Tue Feb 10 03:35:43 1998 J"orn Rennecke + + * reload.c (find_reloads_toplev): Handle arbitrary non-paradoxical + SUBREGs of CONST_INTs. + +Mon Feb 9 17:52:36 1998 John Carr + + * mips.c (print_operand, function_prologue): Make printf format + match argument type. + +Mon Feb 9 02:37:25 1998 Kaveh R. Ghazi + + * 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'. + +Sun Feb 8 14:56:03 1998 Richard Kenner + + * loop.c (strength_reduce): When placing increment for auto-inc + case, do comparison in loop order. + +Sun Feb 8 13:21:38 1998 John Carr + + * bitmap.c (bitmap_debug_file): HOST_PTR_PRINTF converts a pointer, + not a HOST_WIDE_INT. + + * calls.c (expand_call): Change test of expand_inline_function + return value to stop compiler warning. + + * genattrtab.c (RTL_HASH): Cast pointer to long, not HOST_WIDE_INT. + +Sun Feb 8 12:04:24 1998 Jim Wilson (wilson@cygnus.com) + Jeff Law (law@cygnus.com) + + * 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. + +Sun Feb 8 01:49:18 1998 Kaveh R. Ghazi + + * gansidecl.h: Check for a conflicting macro definition before + attempting to prototype bcopy, bcmp or bzero. + +Sun Feb 8 00:09:59 1998 Jeffrey A Law (law@cygnus.com) + + * expr.c (clear_pending_stack_adjust): Handle case where a function + calls alloca, but the user has specified -fomit-fframe-pointer. + + * function.c (assign_parms): Fix typo in last change. + +Sat Feb 7 23:54:29 1998 Robert Lipe + + * gcc.c: Include /, , , + . + (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> + + * c-common.c: Include and /. + + * calls.c (expand_call): Remove unused variables funtree, + n_regs, and tmpmode. + + * dbxout.c, except.c: Include /. + + * explow.c: (plus_constant_for_output_wide) Removed unused + variable all_constant. + + * 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 + . + + * genextract.c: (walk_rtx) Remove unused variable link. + + * genrecog.c: (concat) Remove unreferenced static function. + + * prefix.c: Include /, + + * stmt.c: Include . + (expand_asm_operands): Remove unused variable val1. + (expand_return): Remove unused variable block. + (pushcase): Remove unused variables l and n. + (pushcaserange): Likewise. + + * unroll.c (unroll_loop): Remove unused variable temp. + +Sat Feb 7 23:46:09 1998 Greg McGary + + * c-decl.c (pushdecl): Set DECL_ORIGINAL_TYPE once only. + +Sat Feb 7 15:11:28 1998 Kaveh R. Ghazi + + * 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 Feb 6 14:20:16 1998 Jim Wilson + + * function.c (assign_parms): New variable named_arg, with value + depending on STRICT_ARGUMENT_NAMING. Use instead of ! last_named. + +Fri Feb 6 14:34:28 1998 Gavin Koch + + * 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. + +1998-02-06 Jason Merrill + + * 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. + +1998-02-06 Kriang Lerdsuwanakij + + * cplus-dem.c (demangle_template_template_parm): New function. + (demangle_template): Handle template template parameters. + +1998-02-02 Mark Mitchell + + * calls.c (expand_call): Don't confuse member functions named + realloc, setjmp, and so forth with the standard library + functions of the same names. + +Thu Feb 5 21:59:49 1998 Jeffrey A Law (law@cygnus.com) + + * stmt.c (expand_asm_operands): Correctly identify asm statements + no output operands. + +Thu Feb 5 21:56:06 1998 Mumit Khan + + * c-common.c (decl_attributes): Flag unrecognized attribute + functions as warnings instead of as errors. + +1998-02-05 Marc Lehmann + + * 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. + +Fri Feb 6 00:27:36 1998 J"orn Rennecke + + * 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. + +Thu Feb 5 13:38:42 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Thu Feb 5 01:45:19 1998 J"orn Rennecke + Undo this change (the problem was actually in reload): + Fri Jan 23 23:28:59 1998 J"orn Rennecke + + * sh.md (movqi_i+1): New peephole. + +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. + + * jump.c (jump_optimize): Fix first arg to modified_in_p in + previous change. + +Mon Feb 2 19:18:14 1998 Richard Henderson + + * 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. + + * 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. + +Mon Feb 2 16:43:10 1998 John Carr + + * mips.md: Change gen_rtx (CONST_INT) to GEN_INT. + +Mon Feb 2 13:06:47 1998 Jim Wilson + + * vmsconfig.com: Remove bytecode references. + +1998-01-30 Andreas Schwab + + * dwarf2out.c (dwarf2out_frame_init): Undo last change, so that + -fno-sjlj-exceptions works for a target that defines + DWARF2_UNWIND_INFO as zero. + + * regmove.c (fixup_match_1): Undo last change which removed some + "useless" code, and add a comment explaining this. + +Mon Feb 2 10:47:14 1998 Gavin Koch (gavin@cygnus.com) + + * mips.c (mips_expand_prologue): Change uses of TARGET_64BIT + to TARGET_LONG64. + +Mon Feb 2 10:38:41 1998 Klaus Kaempf + + * makefile.vms: Remove bytecode references. + Create genrtl files. + +Mon Feb 2 02:08:04 1998 Michael P. Hayes + + * jump.c (jump_optimize): Allow conditional loading of floating point + constants and constants from memory. Reinstalled modified_in_p tests. + +Mon Feb 2 01:38:39 1998 J"orn Rennecke + + * loop.c (get_condition): Handle sign-extended constants. + +Mon Feb 2 01:22:46 1998 Hans-Peter Nilsson + + * expr.c (emit_push_insn): Add code to use movstrti if present. + + * expr.c (emit_push_insn): Use same max-move-amount for movstrhi + and movstrqi as in emit_block_move (). + +Mon Feb 2 00:09:52 1998 Toon Moene + + * 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. + +Sun Feb 1 14:15:33 1998 Franz Sirl + + * rs6000/linux.h: define JUMP_TABLES_IN_TEXT_SECTION + +Sun Feb 1 13:01:15 1998 Klaus Kaempf + + * cccp.c (main): Predefine __VMS_VER on VMS. + +Sun Feb 1 12:39:53 1998 J"orn Rennecke + + * 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 + + * combine.c (simplify_shift_const): (lshiftrt (truncate (lshiftrt))) + is (truncate (lshiftrt)). + +Sun Feb 1 01:06:53 1998 Richard Henderson + + * 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 + + * 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 + + * 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 + + * 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) + + * version.c: Bump for snapshot. + +Thu Jan 29 10:12:27 1998 Jeffrey A Law (law@cygnus.com) + + * 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. + +Thu Jan 29 01:28:14 1998 Klaus Kaempf + + * cccp.c (SYS$SEARCH, SYS$PARSE): Write as upper-case. + + * vmsconfig.com: Remove bytecode references. + + * alpha/vms.h (PREFIX): Define. + + * alpha/vms.h (ASM_OUTPUT_ALIGNED_COMMON): Remove. + + * am-alpha.h: Don't include alloca for OPEN_VMS. + + * alpha/xm-vms.h (HAVE_CPP_STRINGIFY): Define. + + * alpha/xm-vms.h (INCLUDE_DEFAULTS): Define. + (GCC_INCLUDE_DIR): Define + + * make-cc.com, make-cccp.com, make-cc1.com: Removed. + * makefile.vms: New file. + + * alpha/vms.h (CPP_PREDEFINES): Remove -Dalpha. + + * alpha.c (output_prolog): Output '.name' directive + for minimal traceback information. + + * alpha.c (output_prolog): Don't prepend entry point symbols + with '$' on OPEN_VMS. + +Thu Jan 29 00:25:35 1998 David S. Miller + Jeffrey A Law (law@cygnus.com) + + * rtl.c (read_rtx): Use atol/atoq based upon disposition of + HOST_WIDE_INT. + + * 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. + + * 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. + +Thu Jan 29 00:24:29 1998 Jeffrey A Law (law@cygnus.com) + + * combine.c: Fix typos in Jan27 changes. + +Thu Jan 29 00:07:49 1998 Ollivier Robert + + * i386/freebsd.h (LIB_SPEC): Correctly handle -shared, -p and friends. + (LINK_SPEC): Likewise. + (STARTFILE_SPEC): Likewise. + +1998-01-28 Mike Stump + + * rtlanal.c (dead_or_set_regno_p): Ignore REG_DEAD notes after + reload completes. + * genattrtab.c (reload_completed): Define. + + * m32r.md, mips.md, mn10200.md, mn10300.md, pyr.md: Remove obsolete + comments. + +Wed Jan 28 20:11:06 1998 J"orn Rennecke + + * 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 + + * i386/t-cygwin32 (LIMITS_H_TEST, LIBGCC2_INCLUDES): Define. + +Wed Jan 28 11:45:27 1998 Per Bothner + + * 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 + + * config.sub: More accurate determination of HP processor types. + +Tue Jan 27 23:11:11 1998 Kaveh R. Ghazi + + * c-lex.c: Include and /. 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 . 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 and /. + 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 . + (demangle_signature): Avoid an empty body in an else-statement. + (do_type): Remove unused variable `lvl'. + + * cppexp.c: Don't have depend on MULTIBYTE_CHARS. + Include /. + (cpp_lex): Remove unused variable `namelen'. + (cpp_lex): Explicitly declare `num_chars' as an int. + + * cpplib.c: Avoid duplicate inclusion of , include + 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 and /. + (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 and /. + (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 . Prototype `my_strerror'. + + * print-rtl.c (print_inline_rtx): Explicitly declare the parameter + `ind'. + + * profile.c: Include /. + (instrument_arcs): Remove unused variables `note', `inverted', + `zero' and `neg_one'. + (branch_prob): Avoid empty body in an if-statement. + + * regclass.c: Include . + (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 . + (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 and /. + (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 + + * 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 + + * 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 + + * tlink.c (scan_linker_output): Call fclose() for opened files. + +Tue Jan 27 05:05:26 1998 Richard Henderson + + * 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. + + * 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. + +Tue Jan 27 03:21:23 1998 Richard Henderson + + * alpha.md (abssf, absdf): Revert last change. + +Tue Jan 27 00:26:50 1998 John Carr + + * dwarf2out.c (dwarf2out_frame_init): Test value of DWARF2_UNWIND_INFO. + * mips/sni-svr4.h: Define DWARF2_UNWIND_INFO as 0. + +Tue Jan 27 00:07:02 1998 Jeffrey A Law (law@cygnus.com) + + * emit-rtl.c (gen_lowpart_common): Handle more case where converting + a CONST_INT into SFmode. + +Tue Jan 20 16:01:03 1998 Anthony Green + + * 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. + +Mon Jan 26 23:57:39 1998 Manfred Hollstein + + * libgcc2.c (__clear_insn_cache): On sysV68 enable the memctl + stuff only if MCT_TEXT is #define'd. + +Mon Jan 26 23:52:51 1998 Markus F.X.J. Oberhumer + + * configure.in (i*86-pc-msdosdjgpp): Treat like msdos & go32 + configurations. + +Fri Jan 23 09:39:36 1998 Nick Clifton + + * 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. + +Mon Jan 26 12:09:42 1998 Benjamin Kosnik + + * except.c (check_exception_handler_labels): Disable warning when + flag_syntax_only. + +Mon Jan 26 18:17:32 1998 Jim Wilson + + * sparc.c (pic_setup_code): Don't set LABEL_PRESERVE_P. + +Mon Jan 26 18:11:30 1998 J"orn Rennecke + + * 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. + +Mon Jan 26 01:44:12 1998 Jeffrey A Law (law@cygnus.com) + + * h8300.c (print_operand): Handle CONST_DOUBLE for 'e', 'f', and + the default case. + (get_shift_alg): Fix typo. + +Sun Jan 25 22:22:04 1998 Richard Henderson + + * alpha.c (alpha_expand_block_move): Copy ADDRESSOF to reg. + +Sun Jan 25 22:14:28 1998 Richard Henderson + + * toplev.c (get_run_time): Make sure each case gets its variables. + +Sun Jan 25 22:10:21 1998 Richard Henderson + + * 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. + +Sun Jan 25 22:00:25 1998 Alasdair Baird + + * recog.c (validate_replace_rtx_1): Only perform substitutions + of arguments to commutative and comparison operators once. + +Sun Jan 25 12:30:18 1998 Kaveh R. Ghazi + + * sparc.c (output_cbranch): Add default case in + enumeration switch. + + * 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. + + * objc/Make-lang.in (objc.stage1): Depend on stage1-start. + (objc.stage2, objc.stage3, objc.stage4): Likewise. + +Sun Jan 25 12:13:47 1998 Michael Tiemann + + * cse.c (simplify_ternary_operation): Don't try to simplify + IF_THEN_ELSE expressions (created by combine) that don't use + relational operators. + +Fri Jan 23 22:48:24 1998 Jeffrey A Law (law@cygnus.com) + + * cse.c (simplify_ternary_operation): Handle more IF_THEN_ELSE + simplifications. + + * crtstuff.c (init_dummy): Keep the epilogue in the init + section for non-ELF systems. + +Fri Jan 23 23:28:59 1998 J"orn Rennecke + + * sh.md (movqi_i+1): New peephole. + +Fri Jan 23 15:39:42 1998 Jim Wilson + + * Makefile.in: Remove remaining bytecode stuff. + * emit-rtl.c, expr.c: Likewise. + +Fri Jan 23 12:41:10 1998 Nick Clifton (nickc@cygnus.com) + + * toplev.c (lang_options): Add unknown-pragma options. + +Thu Jan 22 23:43:38 1998 Per Bothner + + * dwarfout.c (byte_size_attribute): Simplify and fix - don't need + special (and incomplete) handling for Chill arrays. + +Fri Jan 23 00:27:23 1998 John Carr + + * toplev.c (get_run_time): Call sysconf(_SC_CLK_TCK), when available, + to get clock rate. + +Fri Jan 23 00:19:36 1998 Gavin Koch (gavin@cygnus.com) + + * mips.md (muldi3_internal2): Reverse test for TARGET_MIPS16. + +1998-01-22 scott snyder + + * mips.c (function_prologue): Use HARD_FRAME_POINTER_REGNUM in + .frame directive instead of FRAME_POINTER_REGNUM. + +Fri Jan 23 00:08:55 1998 Robin Kirkham + + * 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__. + +Thu Jan 22 19:55:40 PST 1998 Jeff Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Thu Jan 22 14:47:31 1998 Jim Wilson + + * 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. + +Thu Jan 22 14:49:14 1998 Jeffrey A Law (law@cygnus.com) + + * regmove.c (find_matches): Initialize matches->earlyclobber too. + +Thu Jan 22 01:40:52 1998 Richard Henderson + + * alpha.md (abssf2, absdf2): Disable in IEEE mode. + (negsf2, negdf2): Use proper subtract in IEEE mode. + +Tue Jan 20 09:29:09 1998 Jeffrey A Law (law@cygnus.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. + + * 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. + +Tue Jan 20 09:02:31 1998 Gavin Koch (gavin@cygnus.com) + + * mips/mips.md (divsi3,divdi3,modsi3,moddi3,udivsi3,udivdi3, + umodsi3,umoddi3): Handle mips16 div/mod by a constant. + +Mon Jan 19 21:57:00 1998 Richard Henderson + + * i386.md (push): Prohibit symbolic constants if flag_pic. + (movsi+1): Likewise for move to non-register. + +Mon Jan 19 11:15:38 1998 Jim Wilson + + * alpha.c (mode_mask_operand): Accept 0xffffffff on 32 bit host. + (print_operand): Handle 0xffffffff on 32 bit host. + + * 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. + + * 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. + +Mon Jan 19 10:14:55 1998 Andreas Schwab + + * unprotoize.c: Define UNPROTOIZE first, to actually take effect. + +Mon Jan 19 10:11:52 1998 Richard Henderson + + * configure.in: Add cpp stringify test. + * acconfig.h (HAVE_CPP_STRINGIFY): New tag. + * gengenrtl.c: Use it. + * configure, config.in: Rebuild. + +Mon Jan 19 09:43:15 1998 Andreas Schwab + + * Makefile.in (genrtl.c genrtl.h): Add dummy command for GNU make. + +Mon Jan 19 09:38:18 1998 Richard Henderson + + * 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. + +Sun Jan 18 20:18:01 1998 Richard Henderson + + * alpha.c (alpha_handle_trap_shadows): Ignore CLOBBERs. + +Sun Jan 18 01:54:27 1998 Jeffrey A Law (law@cygnus.com) + + * alpha/xm-winnt.h (HAS_INIT_SECTION): Undefine. + +Sun Jan 18 00:57:35 1998 Mike Stump (mrs@wrs.com) + + * configure.in (i960-wrs-vxworks): Default to latest vxworks release. + +Sat Jan 17 23:41:36 1998 David S. Miller + + * combine.c (force_to_mode, nonzero_bits): Correctly optimize + constant offset computations from objects with known alignment in + the presence of STACK_BIAS. + + * varasm.c (immed_double_const): Add casts to HOST_WIDE_INT where + necessary. + (const_hash): Hash val is unsigned long. + (SYMHASH): Likewise. + + * tree.c (TYPE_HASH): Type of hash val is unsigned long. + + * 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. + + * cse.c (canon_hash): Hash is unsigned long not HOST_WIDE_INT. + + * 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. + +Sat Jan 17 23:22:59 1998 John Wehle (john@feith.com) + + * i386.md: Remove redundant integer push patterns. + Don't bother checking for TARGET_PUSH_MEMORY when + pushing constants or registers. + +Sat Jan 17 22:35:39 1998 Mumit Khan + J.J VanderHeijden + + * pexecute.c (pexecute): New function for mingw32. Supports pipes. + (pwait): New function for mingw32. + + * gcc.c (execute): Mingw32 pexecute() supports pipes, but cygwin32 + pipe support is broken for now. + +1998-01-17 Lee Iverson + + * 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. + + * reorg.c: #include "expr.h" for rtx prototypes. + * Makefile.in (reorg.o): Depend on expr.h + +Sat Jan 17 21:28:08 1998 Pieter Nagel + + * Makefile.in (FLAGS_TO_PASS): Pass down gcc_include_dir and + local_prefix to sub-make invocations. + +Sat Jan 17 21:24:16 1998 David T. McWherter + + * objc-parse.c: Recognize protocol qualifiers in class definitions. + +Sat Jan 17 21:16:19 1998 Jeffrey A Law (law@cygnus.com) + + * rtl.h: Fix typos. + + * 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. + + * rtl.c (read_rtx): Initialize list_rtx to NULL, not NULL_RTX. + + * 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. + + * jump.c (jump_optimize): Remove Dec 17, 1997 chance in + favor of an equivalent change from gcc-2.8. + + * i386/x-sco5 (CC): Remove trailing whitespace. + +Sat Jan 17 21:09:46 1998 Kaveh R. Ghazi + + * gengenrtl.c (type_from_format): De-ANSIfy function signature. + (accessor_from_format): Likewise. + (xmalloc): New function for use when linking with alloca.o. + +Mon Jan 5 02:53:01 1998 Bruno Haible + + * frame.c (find_fde): Correct FDE's upper bound. + +Fri Jan 16 16:23:52 1998 Richard Henderson + + * gengenrtl.c (DEF_RTL_EXPR): Provide a K&R compliant version. + +Fri Jan 16 10:16:10 1998 Jeffrey A Law (law@cygnus.com) + + * calls.c (expand_call): Move #ifdef code out of macro argument + lists. + (emit_library_call, emit_library_call_value): Likewise. + +Fri Jan 16 00:46:40 1998 Jeffrey A Law (law@cygnus.com) + + * rtl.def (INLINE_HEADER): Fix bug exposed by gen_rtx_FOO changes. + +Thu Jan 15 01:02:30 1998 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Wed Jan 14 22:49:17 1998 Richard Henderson + + * 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. + +Wed Jan 14 19:36:08 1998 Gavin Koch (gavin@cygnus.com) + + * mips.h: Fix some type-o's from a previous change. + +Wed Jan 14 01:26:05 1998 Jeffrey A Law (law@cygnus.com) + + * loop.c (check_dbra_loop): Make sure initial value is a + CONST_INT before trying to normalize it. + +Tue Jan 13 23:27:54 1998 Robert Lipe (robertl@dgii.com) + + * sco5.h (ASM_OUTPUT_SECTION_NAME): Refresh from ../svr4.h. + +Tue Jan 13 22:47:02 1998 Herman ten Brugge + + * cppexp.c: Include gansidecl.h + +Tue Jan 13 22:43:35 1998 Ian Lance Taylor + + * svr4.h (LINK_SPEC): Never specify -h. + * ptx4.h (LINK_SPEC): Likewise. + * rs6000/sysv4.h (LINK_SPEC): Likewise. + * sparc/sol2.h (LINK_SPEC): Likewise. + +Tue Jan 13 22:39:40 1998 Richard Henderson (rth@cygnus.com) + + * c-typeck.c (comptypes): Exit early on NULL input. + + * haifa-sched.c (schedule_insns): Correctly remove inter-block + dependencies after reload. + +Tue Jan 13 22:22:31 1998 Franz Sirl + + * rs6000/linux.h (CPP_PREDEFINES): Add -D__ELF__. + +Tue Jan 13 22:14:57 1998 Klaus Kaempf + + * alpha/vms.h (DIR_SEPARATOR): define + +Tue Jan 13 22:13:04 1998 Bruno Haible + + * Makefile.in (stamp-proto): Remove. + (protoize.o, unprotoize.o): Straightforward compile. + * unprotoize.c: Define UNPROTOIZE here, not in the Makefile. + +Tue Jan 13 21:59:39 1998 Mumit Khan + + * i386/cygwin32.h (STRIP_NAME_ENCODING): Define for Win32 to strip + off the trailing @[NUM] added by ENCODE_SECTION_INFO. + +Tue Jan 13 21:55:06 1998 Jeffrey A Law (law@cygnus.com) + + * 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. + +Tue Jan 13 21:37:07 1998 Shigeya Suzuki + + * i386/bsd386.h (DWARF2_UNWIND_INFO): Define as zero for now. + +Tue Jan 13 17:50:55 1998 Jim Wilson + + * configure.in (target_cpu_default, target_cpu_default2): Use double + quotes around them when testing their value. + * configure: Rebuilt. + +Tue Jan 13 09:07:44 1998 John Carr + + * gengenrtl.c (gencode): Emit new function obstack_alloc_rtx + to allocate rtx. + (gendef): Call obstack_alloc_rtx. + +Tue Jan 13 01:16:36 1998 Robert Lipe (robertl@dgii.com) + + * configure.in: (i[3456]86-UnixWare7-sysv5): Treat much like SVR4 + for now. + +Thu Dec 18 18:40:17 1997 Mumit Khan + + * 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. + +Tue Jan 13 00:44:02 1998 Jim Wilson + + * mips.md (return_internal): Change mode from SImode to VOIDmode. + +Sat Jan 10 22:11:39 1998 J. Kean Johnston + + * i386/sco5.h (STARTFILE_SPEC, ENDFILE_SPEC): Correctly handle + "-static". + +Sat Jan 10 22:04:15 1998 Stan Cox + + * i386.md: (movsicc_1, movhicc_1): For alternate 3 set the opcode + suffix from operand 3. + +Sat Jan 10 21:50:16 1998 J"orn Rennecke + Jeffrey A Law (law@cygnus.com) + + * 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. + +Sat Jan 10 20:30:12 1998 Jeffrey A Law (law@cygnus.com) + + * regclass.c (record_address_regs): Don't use REG_OK_FOR_BASE_P + if it is not defined. + +Thu Jan 8 21:06:54 1998 Richard Henderson + + * 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. + +Mon Jan 5 13:00:18 1998 John F. Carr + + * 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. + +Mon Jan 5 11:39:49 1998 Jeffrey A Law (law@cygnus.com) + + * 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. + +Sun Jan 4 20:24:00 1998 Nigel Stephens + + * mips/mips16.S: Various changes to make it work with -msingle-float + and -EL. + +Sun Jan 4 14:25:18 1998 Gavin Koch + Ian Lance Taylor + Jeff Law + + * mips.c, mips.h, mips.md: First cut at merging in mips16 + support. Major modifications throughout all three files. + +Sun Jan 4 01:01:50 1998 scott snyder + + * configure.in: Make gthr-default.h a forwarding header instead of + a symlink. + +Sat Jan 3 12:08:06 1998 Kaveh R. Ghazi + + * gcov-io.h: Include sys/types.h to ensure we get size_t. + + * pa.h (ASM_OUTPUT_MI_THUNK): Add missing % in fprintf. + +Fri Jan 2 23:40:09 1998 Jim Wilson (wilson@cygnus.com) + Jeffrey A Law (law@cygnus.com) + + * crtstuff.c (__frame_dummy): New function for irix6. + (__do_global_ctors): Call __frame_dummy for irix6. + * iris6.h (LINK_SPEC): Hide __frame_dummy too. + +Fri Jan 2 04:57:57 1998 Weiwen Liu + + * alpha.c (vms_valid_decl_attribute_p): Move within #if OPEN_VMS. + +Fri Jan 2 04:34:14 1998 Richard Henderson + + * 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. + + * 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. + + * alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Set to 3. + (CONSTANT_ALIGNMENT, DATA_ALIGNMENT): Disable. + +Thu Jan 1 15:40:15 1998 Richard Henderson + + * configure.in: Put parenthesis around TARGET_CPU_DEFAULT's value. + * configure: Update. + +Thu Jan 1 10:49:12 1998 Jeffrey A Law (law@cygnus.com) + + * emit-rtl.c (operand_subword): Correctly handle extracting a word + from a CONST_DOUBLE for 16bit targets with !WORDS_BIG_ENDIAN. + + * mn10200.md (tstxx, cmpxx): Use "nonimmediate_operand" as predicate + for first argument. + +Wed Dec 31 14:42:18 1997 Ian Lance Taylor + + * 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. + +Wed Dec 31 10:05:44 1997 Jeffrey A Law (law@cygnus.com) + + * mn10200.md (addsi3, subsi3): Fix thinkos. + +Tue Dec 30 00:04:49 1997 Richard Henderson + + * 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. + +Mon Dec 29 14:37:31 1997 Ian Lance Taylor + + * mips/t-ecoff (CROSS_LIBGCC1): Define to libgcc1-asm.a. + (LIB1ASMSRC, LIB1ASMFUNCS): Define. + +Mon Dec 29 14:03:38 1997 Jeffrey A Law (law@cygnus.com) + + * expr.c (expand_expr): For {BITFIELD,COMPONENT,ARRAY}_REF, if the + offset's mode is not ptr_mode, convert it. + +Mon Dec 29 15:58:18 1997 Michael Meissner + + * libgcc2.c (inhibit_libc): Don't define inhibit_libc when cross + compiling if it was already defined. + +Sun Dec 28 00:32:16 1997 Jeffrey A Law (law@cygnus.com) + + * flow.c (find_basic_blocks): Don't create a new basic block + for calls in a LIBCALL block. + +Sun Dec 28 00:30:24 1997 David Edelsohn + + * config/fp-bit.c (L_df_to_sf): Fix typo in last change. + +Sat Dec 27 22:43:12 1997 Jeffrey A Law (law@cygnus.com) + + * cse.c (rtx_cost): Remove conflicting default case. + +Sat Dec 27 21:20:02 1997 Richard Henderson + + * configure.in: Move default enabling of Haifa out of for loop. + * configure: Rebuild. + +Thu Dec 25 01:02:54 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +1997-12-25 Teemu Torma + + * Makefile.in (GTHREAD_FLAGS): New var. + (LIBGCC2_CFLAGS): Added $(GTHREAD_FLAGS). + (distclean): Remove gthr-default.h. + + * 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. + + * config/pa/t-dce-thr: New file. + * config/pa/t-pa: Removed multilibs. + * config/sparc/t-sol2: Ditto. + + * 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. + + * 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. + +Wed Dec 24 23:33:17 1997 Jeffrey A Law (law@cygnus.com) + + * expr.h (MUST_PASS_IN_STACK): Allow target port to override. + +Wed Dec 24 23:12:14 1997 Jim Wilson + + * cse.c (max_insn_uid): New variable. + (cse_around_loop): Use max_insn_uid. + (cse_main): Set max_insn_uid. + + * 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. + +Wed Dec 24 22:38:34 1997 John Carr + + * flags.h, toplev.c, calls.c, alias.c: Remove flag_alias_check; + optimization is now always enabled. + + * calls.c (expand_call): Recognize C++ operator new as malloc-like + function. + + * 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 : + + * 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 + + * 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 + + * 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. + +Tue Dec 23 03:14:54 1997 Richard Henderson + + * Makefile.in (clean): Remove the stages with their objects here ... + (distclean): ... instead of here. + +Mon Dec 22 11:24:01 1997 Kaveh R. Ghazi + + * 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. + +Mon Dec 22 09:58:51 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + +Mon Dec 22 09:18:37 1997 Jeffrey A Law (law@cygnus.com) + + * c-pragma.c: Include flags.h. + +Sun Dec 21 22:10:59 1997 Mumit Khan + + * 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. + + * 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. + +Sun Dec 21 21:54:22 1997 Jeffrey A Law (law@cygnus.com) + + * pa.c (emit_move_sequence): Handle a function label source + operand. + +Sun Dec 21 16:13:55 1997 Nick Clifton + + * 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 + Jeff Law + + * 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 + + * 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 + + * 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. + +Fri Dec 19 00:19:42 1997 Richard Henderson + + * 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): + Likewise. + +Thu Dec 18 17:05:10 1997 Kaveh R. Ghazi + + * mips.c (fatal): Remove declaration. + +1997-12-18 Mark Mitchell + + * 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. + +Thu Dec 18 19:19:57 1997 Ian Lance Taylor + + * 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. + +Thu Dec 18 14:51:12 1997 Jason Merrill + + * except.c: Remove register_exception_table{,_p}. + +Thu Dec 18 14:57:29 1997 Gavin Koch + + * unroll.c (calculate_giv_inc): Handle constant increment found in + a MEM with an appropriate REG_EQUAL note. + + * calls.c (expand_call): Implement LOAD_ARGS_REVERSED. + + * dwarf2out.c (dwarf2out_frame_debug): Handle adjustments of the + frame pointer in the prologue. + +Thu Dec 18 00:19:38 1997 Robert Lipe + + * i386/x-sco5 (CLIB) Deleted. (ALLOCA) Added. + * i386/xm-sco5.h (USE_C_ALLOCA) Added. + +Tue Dec 16 18:51:00 1997 Bill Moyer + + * config/m68k/m68k.c (output_function_prologue): Typecast + dwarf2out_cfi_label to (char *). + * config/m68k/m68kemb.h (STARTFILE_SPEC): Redefined to "". + +Wed Dec 17 15:06:04 1997 Richard Henderson + + * sparc.md (jump): Don't use the annul bit around an empty loop. + Patch from Kevin.Kelly@East.Sun.COM. + +Wed Dec 17 00:51:36 1997 Stan Cox (scox@cygnus.com) + + * jump.c: (jump_optimize): Don't use the return register as a + source1 of a conditional move. + +Tue Dec 16 23:45:40 1997 Richard Henderson + + * sparc.c (DF_MODES): Or the mask not the bit number. + (function_arg) [ARCH64]: Send unprototyped arg to fp reg first. + +Wed Dec 17 00:13:48 1997 Christian Iseli + + * combine.c (force_to_mode): return immediately if operand is a CLOBBER. + +Tue Dec 16 23:44:54 1997 Manfred Hollstein + + * 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. + + * 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. + +Tue Dec 16 23:25:45 1997 H.J. Lu (hjl@gnu.org) + + * config/sparc/linux64.h (LIBGCC_SPEC): Removed. + (CPP_SUBTARGET_SPEC): Add %{pthread:-D_REENTRANT}. + (LIB_SPEC): Updated for glibc 2. + +Tue Dec 16 20:11:36 1997 Jeffrey A Law (law@cygnus.com) + + * ginclude/stdarg.h: Undo BeOS changes, they break hpux. + * ginclude/varargs.h: Likewise. + +Tue Dec 16 00:32:01 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Tue Dec 16 00:14:29 1997 H.J. Lu (hjl@gnu.org) + + * 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. + +Mon Dec 15 18:40:08 1997 Richard Henderson + + * expmed.c (expand_shift): If SHIFT_COUNT_TRUNCATED, drop a SUBREG. + +Mon Dec 15 18:31:43 1997 Richard Henderson + + * 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. + + * alpha.h (ASM_COMMENT_START): New macro. + +Mon Dec 15 17:48:05 1997 Richard Henderson + + * reload.h, reload1.c (eliminate_regs), caller-save.c, dbxout.c, + dwarfout.c, dwarf2out.c, reload.c, sdbout.c: Revert March 15 change. + + * 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. + +Mon Dec 15 Mark Mitchell 11:41:32 1997 + + * toplev.c (rest_of_compilation): Don't call save_for_inline_copy + if all we're doing is dealing with -Wreturn-type. + +Mon Dec 15 09:44:39 1997 Richard Henderson + + * alpha.md (zero_extendqihi2, zero_extendqisi2, zero_extendqidi2): + Use and 255 instead of zapnot 1, since it schedules better. + +Mon Dec 15 08:48:24 1997 Jeffrey A Law (law@cygnus.com) + + * stmt.c (expand_asm_operands): If an ASM has no outputs, then treat + it as volatile. + +Mon Dec 15 00:04:48 1997 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (remove_dependencies): Set RTX_INTEGRATED_P on + dependency we delete. Properly update prev for multiple consecutive + deletions. + (priority): Skip deleted dependence. + +Fri Dec 12 18:54:23 1997 Per Bothner + + * expr.c (expand_builtin): Support BUILT_IN_FMOD - just call fmod. + +Fri Dec 12 01:19:48 1997 Jason Merrill + + * flow.c (flow_analysis): Be consistent with find_basic_blocks in + determining when a new basic block starts. + + * alpha/osf2or3.h (LIB_SPEC): Restore missing defn. + + * pa.h (TEXT_SPACE_P): Use TREE_CODE_CLASS. + * pa.md (iorsi3): Add missing args to *_operand calls. + + * except.c (call_get_eh_context): Don't mess with sequences. + (emit_eh_context): Include the call in the sequence here. + +1997-12-11 Paul Eggert + + * collect2.c (write_c_file_glob): Allocate initial frame object + in static storage and pass its address. + +Thu Dec 11 23:33:48 1997 Jason Merrill + + * 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. + +Fri Oct 10 17:58:31 CEST 1997 Marc Lehmann + + * i386/xm-go32.h (EXECUTABLE_SUFFIX): Define. + (DIR_SEPARATOR, NO_SYS_SIGLIST): Likewise. + +Thu Dec 11 23:55:17 1997 Manfred Hollstein + + * fixincludes (strlen,strspn,strcspn return value): Handle different + layout on sysV88. + (hypot): Provide a fake for hypot which is broken on + m88k-motorola-sysv3. + +Thu Dec 11 23:50:17 1997 John F. Carr + + * 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. + + * cp/lex.c (init_lex): Update for tree_code_* changes. + * objc/objc-act.c (init_objc): Likewise. + + * tree.def, cp/cp-tree.def, objc/objc-tree.def: Update for tree_code + changes. + +Thu Dec 11 23:34:54 1997 Fred Fish + + * 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. + +Thu Dec 11 23:25:23 1997 Jeffrey A Law (law@cygnus.com) + Toon Moene (toon@moene.indiv.nluug.nl) + + * 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. + +Thu Dec 11 23:06:48 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * 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. + +Thu Dec 11 22:02:10 1997 Jason Merrill + + * flow.c (find_basic_blocks): A CALL_INSN that can throw starts + a new basic block. + (find_basic_blocks_1): Likewise. + +Thu Dec 11 21:08:48 1997 Jason Merrill + + * 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 + + 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 : + * 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 + + * 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 + + * configure.in ({rs6000,powerpc}-*-*): Enable Haifa scheduler by + default. + +Wed Dec 10 12:30:18 1997 Anthony Green + + * crtstuff.c (__do_global_ctors): Fix typo. + +Tue Dec 9 09:43:59 1997 Manfred Hollstein + + * 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 + + * rs6000.h (FUNCTION_ARG_PADDING): Define. + * rs6000.c (function_arg_padding): New function. + +Tue Dec 9 10:34:21 1997 Manfred Hollstein + + * m68k.c: Include tree.h only once. + +Tue Dec 9 09:32:33 1997 Richard Kenner + + * 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. + +Tue Dec 9 01:15:15 1997 Fred Fish + + * libgcc2.c (string.h): Hoist inclusion to occur before first use of + string functions like strlen. + +Tue Dec 9 00:57:38 1997 Manfred Hollstein + + * 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. + +Mon Dec 8 23:53:26 1997 Jay Sachs + + * Makefile.in (compare*): Handle losing behavior from 4.4bsd make. + +Mon Dec 8 21:03:28 1997 Richard Henderson + + * alpha.c (REG_RA, alpha_return_addr, output_epilog): + Fix merge problems. + + * alpha.c (override_options): Don't know about scheduling for EV6. + * alpha.md (ev5 function units): Don't overload as ev6. + + * 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. + +Mon Dec 8 18:15:00 1997 Richard Henderson + + * alpha/win-nt.h (TRAMPOLINE_TEMPLATE): Fix backported gcc-2.8 bug. + +Mon Dec 8 21:17:28 1997 J"orn Rennecke + + * cstamp-h, auto-config.h: Delete. + +Sun Dec 7 19:19:03 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sat Dec 6 22:22:22 1997 Jeffrey A Law (law@cygnus.com) + + * cccp.c: Fix typo brought over in merge. + + * Merge in changes from gcc-2.8. + +Mon Nov 3 05:45:32 1997 Philippe De Muyter + + * m68k.c: Include tree.h for dwarf2out_cfi_label. + + * gcc.c (process_command): Do not take address of function fatal when + calling lang_specific_driver. + +Sat Dec 6 01:02:38 1997 Mumit Khan + + * 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 Dec 6 01:01:02 1997 Christian Iseli + + * cse.c (cse_insn): Check for invalid entries when taking references. + +Fri Dec 5 18:26:25 1997 J"orn Rennecke + + * 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 Dec 5 16:26:03 1997 Bernd Schmidt + + * i386.c (notice_update_cc): Remove bogus pentium GCC code. + +Fri Dec 5 16:25:14 1997 Jeffrey A Law (law@cygnus.com) + + * stmt.c (warn_if_unused_value): Don't warn for TRY_CATCH_EXPR. + +Thu Dec 4 11:51:00 1997 Jason Merrill + + * except.c (get_dynamic_handler_chain): Only make the call once per + function. + + * except.c (expand_end_all_catch): Fix for sjlj exceptions. + +Thu Dec 4 12:30:40 1997 J"orn Rennecke + + * sh.c (final_prescan_insn): Use local label prefix + when emitting .uses pseudo-ops. + +Wed Dec 3 12:01:56 1997 Jason Merrill + + * 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. + +Thu Dec 4 00:24:09 1997 Jeffrey A Law (law@cygnus.com) + + * i386/t-sol2 (CRTSTUFF_T_CFLAGS): Turn on the optimizer. + +Wed Dec 3 12:01:56 1997 Jason Merrill + + * 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. + +Wed Dec 3 11:41:13 1997 Gavin Koch + + * 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. + +Tue Dec 2 19:40:43 1997 Jason Merrill + + * stmt.c (expand_decl_cleanup): Update thisblock after eh_region_start. + +Tue Dec 2 12:54:33 1997 Jim Wilson + + * unroll.c (find_splittable_givs): Remove last change. Handle givs + with a dest_reg that was created by loop. + +Sat Nov 29 12:44:57 1997 David Edelsohn + + * rs6000.c (function_arg_partial_nregs): Undo Nov. 26 patch. + + * rs6000/aix41.h (ASM_CPU_SPEC): Define. + +Fri Nov 28 10:00:27 1997 Jeffrey A Law (law@cygnus.com) + + * configure.in: Fix NCR entries. + +Thu Nov 27 12:20:19 1997 Jeffrey A Law (law@cygnus.com) + + * flow.c (find_basic_blocks): Handle cfg issues for rethrows and + nested exceptions correctly. + + * unroll.c (find_splittable_givs): Don't split givs with a dest_reg + that was created by loop. + +Thu Nov 27 09:34:58 1997 Jason Merrill + + * expr.c (preexpand_calls): Don't look past a TRY_CATCH_EXPR. + + * except.c (expand_start_all_catch): One more do_pending_stack_adjust. + +Wed Nov 26 15:47:30 1997 Michael Meissner + + * 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. + + * rs6000/linux.h (LINK_SPEC): Pass -dynamic-linker /lib/ld.so.1 if + -dynamic linker is not used. + + * rs6000.md (call insns): For local calls, use @local suffix under + System V. Don't use @plt under Solaris. + + * rs6000.c (output_function_profiler): Put label address in r0, and + store LR in 4(sp) for System V/eabi. + + * rs6000.h (ASM_OUTPUT_REG_{PUSH,POP}): Keep stack aligned to 16 + byte boundary, and maintain stack backchain. + +Tue Nov 25 14:08:12 1997 Jim Wilson + + * mips.md (fix_truncdfsi2, fix_truncsfsi2, fix_truncdfdi2, + fix_truncsfdi2): Change *. + +Wed Nov 26 11:12:26 1997 Jason Merrill + + * toplev.c (main): Complain about -gdwarfn. + +Tue Nov 25 22:43:30 1997 Jason Merrill + + * dwarfout.c (output_type): If finalizing, write out nested types + of types we've already written. + +Tue Nov 25 20:32:24 1997 Michael Meissner + + (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. + + * rs6000.md (call insns): If -fPIC or -mrelocatable, add @plt + suffix to calls. + +Tue Nov 25 23:37:27 1997 Jason Merrill + + * integrate.c (output_inline_function): Just unset DECL_INLINE. + +Tue Nov 25 23:33:29 1997 scott snyder + + * dwarf2out.c (outout_call_frame_info): Ensure that the info has + proper alignment. + + * libgcc2.c (__throw): Initialize HANDLER. + +Tue Nov 25 14:08:12 1997 Jim Wilson + + * mips.md (fix_truncdfsi2, fix_truncsfsi2, fix_truncdfdi2, + fix_truncsfdi2): Change *X to ?*X. + +Tue Nov 25 10:00:42 1997 Richard Henderson (rth@cygnus.com) + + * alpha.h (CONST_OK_FOR_LETTER): Fix 'L' handling. + +Tue Nov 25 10:00:42 1997 Jeffrey A Law (law@cygnus.com) + + * crtstuff.c (do_global_dtors_aux): Handle multiple calls better. + +Tue Nov 25 01:26:55 1997 Bruno Haible : + + * dwarf2out.c (ASM_OUTPUT_DWARF_DELTA1): Implement. + +Mon Nov 24 22:41:55 1997 Jason Merrill + + * except.c (get_dynamic_handler_chain): Build up a FUNCTION_DECL. + * optabs.c (init_optabs): Lose get_dynamic_handler_chain_libfunc. + * expr.h: Likewise. + +Sat Nov 22 18:58:20 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + +Fri Nov 21 15:20:05 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (program_transform_cross_name): Clean up "-e" confusion. + (GCC_INSTALL_NAME, GCC_CROSS_NAME): Likewise. + +Fri Nov 21 19:37:40 1997 Andrew Cagney + + * config/mips/elf64.h (MULTILIB_DEFAULTS): Test for + TARGET_ENDIAN_DEFAULT == zero instead of testing for macro + definition. + +Fri Nov 21 12:49:56 1997 Bruno Haible + + * stmt.c (expand_end_bindings): Allow jump into block with cleanups. + +Fri Nov 21 12:18:51 1997 Jason Merrill + + * 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. + +Fri Nov 21 10:13:11 1997 Robert Lipe (robertl@dgii.com) + + * i386/sco5.h (HAVE_ATEXIT): Revert last change. + +Thu Nov 20 16:11:50 1997 Richard Henderson + + * alpha.c (alpha_emit_set_const_1): Handle narrow hosts better. + +Thu Nov 20 16:11:50 1997 Klaus Kaempf + + * 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. + +Thu Nov 20 14:42:15 1997 Jason Merrill + + * 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. + + * except.c (output_exception_table): Don't bother with + __EXCEPTION_END__. + +Thu Nov 20 16:11:50 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * mips/x-iris (FIXPROTO_DEFINES): Add -D_SGI_SOURCE. + +Thu Nov 20 13:19:32 1997 Jason Merrill + + * 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. + +Thu Nov 20 00:38:46 1997 Dave Love + + * configure.in: Add AC_ARG_ENABLE for Haifa as documentation. + +Wed Nov 19 12:03:04 1997 Philippe De Muyter + + * 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. + +Tue Nov 18 23:03:30 1997 J"orn Rennecke + + * 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. + +Tue Nov 18 15:39:59 1997 Jim Wilson + + * 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. + +Mon Nov 17 15:35:38 1997 Tom Tromey + + * cccp.c (deps_output): Properly quote file names for make. + +Mon Nov 17 13:21:40 1997 Jeffrey A Law (law@cygnus.com) + + * t-h8300 (MULTILIB_EXCEPTIONS): Define. + +Fri Nov 7 15:33:11 1997 Robert Lipe (robertl@dgii.com) + + * i386/sco5.h (HAVE_ATEXIT): Delete definition. + +Sun Nov 16 23:52:48 1997 Jeffrey A Law (law@cygnus.com) + + * cse.c (cse_insn): Don't look at JUMP_LABEL field of a conditionl + return. + (cse_end_of_basic_block): Similarly. + +Sun Nov 16 23:01:40 1997 J. Kean Johnston + + * i386/sco5.h (ASM_OUTPUT_ALIGNED_BSS): Define. + (SELECT_RTX_SECTION): Define. + (LIBGCC_SPEC, LIB_SPEC): Do the right thing for PIC. + +Sun Nov 16 22:47:03 1997 Manfred Hollstein + + * Makefile.in (compare, compare-lean): Define $stage for each + shell command. + (gnucompare, gnucompare-lean): Likewise. + +Sun Nov 16 22:02:16 1997 Richard Henderson (rth@cygnus.com) + + * alpha/win-nt.h (TRAMPOLINE_TEMPLATE): Fix offsets. + + * alpha.h (ASM_OUTPUT_ADDR_DIFF_ELT): Add an L for the local label + to correspond with the change to ASM_GENERATE_INTERNAL_LABEL. + +Fri Nov 14 09:09:20 1997 Fred Fish (fnf@cygnus.com) + + * 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. + +Fri Nov 14 08:46:56 1997 Jeffrey A Law (law@cygnus.com) + + * toplev.c (get_run_time): Do something sensible for cygwin32. + +Fri Nov 14 07:24:20 1997 Richard Henderson + + * 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. + + * 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. + + * 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. + + * alpha.h (ASM_OUTPUT_INTERNAL_LABEL): Don't omit L from local label. + (ASM_GENERATE_INTERNAL_LABEL): Likewise. + + * 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. + +Fri Nov 14 06:59:33 1997 Jeffrey A Law (law@cygnus.com) + + * calls.c (expand_call): Handle pcc_struct_value correctly for C++. + + * 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. + +Thu Nov 13 20:37:33 1997 Michael Meissner + + * reload1.c (new_spill_reg): Improve fixed or forbidden register + spill error message. + +Thu Nov 13 20:29:08 1997 Kaveh R. Ghazi + + * prefix.c: Use stdarg.h only ifdef __STDC__. Otherwise, + use varargs.h. Wrap header with <>, not "". + +Thu Nov 13 20:21:17 1997 Jeffrey A Law (law@cygnus.com) + + * integrate.c (save_for_inline_copying): Add return value from + savealloc. + +Thu Nov 13 19:12:33 1997 Brendan Kehoe + + * fixincludes: Be a little more restrictive on what we will + substitute to replace definitions of MAXINT for HPUX. + +Thu Nov 13 18:41:02 1997 Michael Meissner + + * dbxout.c (dbxout_symbol_location): Don't assume that variables + whose address is the stack or argument pointers are indirect + pointers. + +1997-11-13 Paul Eggert + + * 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. + +Thu Nov 13 23:33:50 1997 J"orn Rennecke + + * fold-const.c (fold_truthop): Fix bug in last change. + +1997-11-13 Paul Eggert + + Fix some confusion with IEEE minus zero. + + * real.h (REAL_VALUES_IDENTICAL): New macro. + + * 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. + + * varasm.c (immed_real_const_1): Use new REAL_VALUES_IDENTICAL + macro instead of doing it by hand. + +Thu Nov 13 16:56:14 1997 Jeffrey A Law (law@cygnus.com) + + * v850/lib1funcs.asm: Minor whitespace changes. + * v850.c: Fix minor formatting problems in many places. + (construct_restore_jr, construct_save_jarl): Remove unwanted aborts. + +Thu Nov 13 12:53:44 1997 Jim Wilson + + * mips.h (GO_IF_LEGITIMATE_ADDRESS): Delete code swapping xplus0 and + xplus1 when xplus0 is not a register. + +Thu Nov 13 11:41:42 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * m68k/x-next (OTHER_FIXINCLUDES_DIRS): Include /NextDeveloper/Headers. + + * confiugre.in: Tweak NCR entries. + * configure: Rebuilt. + +Thu Nov 13 11:07:41 1997 Michael Meissner + + * 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. + + * 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. + +Thu Nov 13 00:06:58 1997 J"orn Rennecke + + * fold-const.c (fold_truthop): When changing a one-bit comparison + against zero into a comparison against mask, do a proper sign + extension. + +Wed Nov 12 09:37:01 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * 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. + +Tue Nov 11 21:47:27 1997 J"orn Rennecke + + * glimits.h (SHRT_MIN): Define in a way suitable for 16 bit hosts. + + * c-lex.c (whitespace_cr, skip_white_space_on_line): New functions. + (skip_white_space): Use whitespace_cr. + (check_newline): Handle whitespace more consistently. + +Tue Nov 11 16:25:49 1997 Jim Wilson + + * i386/cygwin32.h (CPP_PREDEFINES): Delete -DPOSIX. + * i386/xm-cygwin32.h (POSIX): Define. + +Mon Nov 10 20:53:11 1997 Gavin Koch + + * config/mips/mips.h (MASK_DEBUG_H): Set to zero, so this bit + is available elsewhere. + +Mon Nov 10 16:21:58 1997 Doug Evans + + * sparc/sparc.md (mov[sdt]f_const_insn): Fix condition to match + what the instruction can handle. + +Mon Nov 10 03:02:19 1997 Jason Merrill + + * stmt.c (expand_decl_cleanup_no_eh): New fn. + + * except.c (expand_leftover_cleanups): do_pending_stack_adjust. + +Mon Nov 10 00:05:56 1997 Jeffrey A Law (law@cygnus.com) + + * alias.c (MAX_ALIAS_LOOP_PASSES): Define. + (init_alias_analysis): Break out of loops after MAX_ALIAS_LOOP_PASSES. + +Sun Nov 9 14:34:47 1997 David Edelsohn + + * rs6000.md (lshrdi3_power): Delete '&' from first alternative and + swap instruction order. + +Sun Nov 9 02:07:16 1997 Jeffrey A Law (law@cygnus.com) + + * fixinc.svr4 (__STDC__): Add another case. + +Sun Nov 9 02:00:29 1997 J"orn Rennecke + + * a29k.h (ELIGIBLE_FOR_EPILOGUE_DELAY): Avoid loads from varying + addresses in the epilogue delay slot. + +Sun Nov 9 01:40:40 1997 Manfred Hollstein (manfred@s-direktnet.de) + + * m88k/dgux.h (ASM_CPU_SPEC): Reformatted to suppress wrong whitespace + in generated `specs' file. + +Sun Nov 9 01:37:11 1997 Jim Wilson (wilson@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. + +Sat Nov 8 18:20:21 1997 J"orn Rennecke + + Bring over from FSF: + + Thu Oct 30 12:21:06 1997 J"orn Rennecke + + * 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. + + Tue Oct 28 15:06:44 1997 J"orn Rennecke + + * sh/elf.h (PREFERRED_DEBUGGING_TYPE): Undefine before including + svr4.h. + + Mon Oct 27 16:11:52 1997 J"orn Rennecke + + * 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. + + Tue Oct 21 07:12:28 1997 J"orn Rennecke + + * sh/elf.h (PREFERRED_DEBUGGING_TYPE): Don't redefine. + +Fri Nov 7 10:22:24 1997 Jason Merrill + + * frame.c (add_fdes, count_fdes): Go back to checking pc_begin for + linked once FDEs. + +Wed Nov 5 14:26:05 1997 Jeffrey A Law (law@cygnus.com) + + * alias.c (find_base_value): Only return the known base value for + pseudo registers. + +Wed Nov 5 11:27:14 1997 Jim Wilson + + * 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. + +Tue Nov 4 20:36:50 1997 Richard Henderson (rth@cygnus.com) + + * alpha.c (summarize_insn): Handle ASM_OPERANDS. Don't recurse + for SUBREG, just fall through. + + * alpha.c (alpha_handle_trap_shadows): Init sum.defd to zero. + + * alpha.md (attr trap): Make TRAP_YES non-zero for sanity's sake. + +Tue Nov 4 18:49:42 1997 Jeffrey A Law (law@cygnus.com) + + * fixincludes: Fix "hypot" prototype in NeXT math.h. + + * Makefile.in (USE_ALLOCA): Always include alloca.o. + (USE_HOST_ALLOCA): Likewise. + + * rtl.def (CODE_LABEL): Use separate fields for LABEL_NUSES + and LABEL_REFS fields. + * rtl.h (LABEL_REFS): Update. + +Tue Nov 4 16:55:11 1997 Jim Wilson + + * 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. + + * mips.md (insv, extzv, extv): Add change_address call. + (movsi_ulw, movsi_usw): Change QImode to BLKmode in pattern. + + * integrate.c (save_for_inline_copying): Copy parm_reg_stack_loc. + + * reload.c (find_reloads, case 'm' and 'o'): Reject HIGH constants. + + * mips.c (mips_expand_epilogue): Emit blockage insn before call to + save_restore_insns if no FP and GP will be restored. + + * dwarf2out.c (expand_builtin_dwarf_reg_size): New variable mode. + Convert CCmode to word_mode before calling GET_MODE_SIZE. + + * 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. + +Tue Nov 4 16:07:15 1997 Jeffrey A Law (law@cygnus.com) + + * alias.c (find_base_value): When copying arguments, return the + tenative value for a hard register. + +Tue Nov 4 13:40:35 1997 Doug Evans + + * c-lex.c (MULTIBYTE_CHARS): #undef if cross compiling. + (yylex): Record wide strings using target endianness, not host. + +Tue Nov 4 13:13:12 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + +Tue Nov 4 00:55:48 1997 J"orn Rennecke + + * profile.c (branch_prob): Insert an insn after a NOTE_INSN_SETJMP. + +Mon Nov 3 14:36:50 1997 Jeffrey A Law (law@cygnus.com) + + * configure.in (sco5): Use cpio to install header files. + +Sun Nov 2 23:31:43 1997 Manfred Hollstein + + * aclocal.m4 (conftestdata_from, conftestdata_to): Names shortened to + 14 char length. + * configure: Rebuild. + +Sun Nov 2 19:44:00 1997 Robert Lipe (robertl@dgii.com) + + * i386/sco5.h: enable -gstabs once again. + +Sun Nov 2 19:27:21 1997 Jeffrey A Law (law@cygnus.com) + + * arm.c (output_move_double): Allocate 3 entries in otherops array. + +Sat Nov 1 21:43:00 1997 Mike Stump (mrs@wrs.com) + + * 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. + +Sat Nov 1 19:15:28 1997 Jeffrey A Law (law@cygnus.com) + + * alias.c (init_alias_analysis): Handle -fno-alias-check when + optimizing correctly. + + * expr.c (expand_builtin_setjmp): Don't emit a SETJMP note + or set current_function_calls_setjmp anymore. + + * 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. + +Sat Nov 1 16:44:49 1997 Jason Merrill (jason@cygnus.com) + + * flow.c (find_basic_blocks): Generate correct flow control + information when exception handling notes are present. + +Sat Nov 1 13:42:19 1997 Jeffrey A Law (law@cygnus.com) + + * dwarf2out.c (output_call_frame_info): Fix length argument + to ASM_OUTPUT_ASCII. + (output_die, output_pubnames, output_line_info): Likewise. + +Fri Oct 31 07:10:09 1997 Jeffrey A 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. + + * alias.c (init_alias_analysis): Add struct_value_incoming_rtx + and static_chain_rtx into the potential base values array if + they are registers. + + * 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. + + * global.c (global_alloc): Free the conflict matrix after + reload has finished. + +Fri Oct 31 01:45:31 1997 Jason Merrill + + * libgcc2.c (L_eh): Define __eh_pc. + Replace __eh_type with generic pointer __eh_info. + +Fri Oct 31 00:34:55 1996 J"orn Rennecke + + * expr.c (expand_increment): When enqueing a postincrement for a MEM, + use copy_to_reg if address is not a general_operand. + +Fri Oct 31 00:16:55 1997 J"orn Rennecke + + * profile.c (output_func_start_profiler): Clear flag_inline_functions + for the duration of the call to rest_of_compilation. + +Thu Oct 30 14:40:10 1997 Doug Evans + + * 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. + +Thu Oct 30 13:26:12 1997 Jeffrey A Law (law@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. + +Wed Oct 29 16:57:19 1997 Michael Meissner + + * rs6000/xm-sysv4.h: Include xm-linux.h instead of xm-svr4.h if we + are running on PowerPC Linux. + +Wed Oct 29 13:10:11 1997 Gavin Koch + + * config/mips/elf64.h (PREFERRED_DEBUGGING_TYPE): Only define + if not previously defined. + +Tue Oct 28 23:55:27 1997 Doug Evans (devans@cygnus.com) + + * function.c (assign_parms): Correct mode of stack_parm if + entry_parm underwent a mode conversion. + +1997-10-28 Brendan Kehoe + + * 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. + +Tue Oct 28 15:29:15 1997 Richard Henderson + + * reload1.c (eliminate_regs [SET]): If [SUBREG] widened the mode of + DEST for the spill, adjust mode of SRC to compensate. + +Tue Oct 28 14:36:45 1997 Richard Henderson + + * 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. + +Tue Oct 28 11:53:14 1997 Jim Wilson + + * m68k.md (btst patterns): Add 5200 support. + +Tue Oct 28 11:58:40 1997 Toon Moene + + * 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. + +Tue Oct 28 10:19:01 1997 Jason Merrill + + From Brendan: + * dwarf2out.c (output_call_frame_info): Use l1 instead of ".". + +Tue Oct 28 00:32:14 1997 Richard Henderson + + * alpha.c (summarize_insn [SUBREG]): Propogate SET. + +Mon Oct 27 23:59:26 1997 Richard Henderson + + * alpha.c (alpha_handle_trap_shadows): Don't call get_attr_trap + on a CLOBBER. + +Mon Oct 27 21:25:20 1997 Richard Henderson + + * 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. + +Mon Oct 27 16:11:10 1997 Jeffrey A Law (law@cygnus.com) + + * mn10300.h (GO_IF_LEGITIMATE_ADDRESS): Disable reg+reg. + +Sun Oct 26 13:50:44 1997 Richard Henderson + + * alpha.c (alpha_sa_mask [VMS]): Don't include $26 in the mask. + Patch from Klaus Kaempf . + +Sun Oct 26 13:31:47 1997 Jim Wilson (wilson@cygnus.com) + + * expr.c (expand_expr, case INDIRECT_REF): Optimize a reference + to an element in a constant string. + +Sun Oct 26 11:41:49 1997 Jason Merrill + + * 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. + + From H.J. Lu: + * frame.c (count_fdes, add_fdes): Skip linked once FDE entries. + +Sun Oct 26 11:52:01 1997 Richard Henderson + + * alias.c (memrefs_conflict_p): Treat arg_pointer_rtx just + like stack_pointer_rtx. + +Sun Oct 26 11:32:16 1997 Manfred Hollstein + + * 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. + + * 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. + +Sun Oct 26 10:06:11 1997 Toon Moene + + * fold-const (fold): Also simplify FLOOR_DIV_EXPR to EXACT_DIV_EXPR + if the dividend is a multiple of the divisor. + +Sun Oct 26 09:21:40 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (LIBGCC2_CFLAGS): Add -fexceptions. + + * alias.c (find_base_term): Handle PRE_INC, PRE_DEC, POST_INC, + and POS_DEC. + + * alias.c (true_dependence): Fix typo. + + * 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. + + * loop.c (simplify_giv_expr): Adding two invariants results + in an invariant. + +Sun Oct 26 09:15:15 1997 Richard Henderson + + * expr.c (get_inner_reference): Remove the array bias after + converting the index to Pmode. + +Sat Oct 25 12:20:58 1997 Jeffrey A Law (law@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. + +Fri Oct 24 17:40:34 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + +Fri Oct 24 15:54:57 1997 Richard Henderson + + * 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. + +Fri Oct 24 13:23:04 1997 Doug Evans + + * sparc/sparc.h (ASM_SPEC): Delete asm_arch. + +Fri Oct 24 13:19:40 1997 Jeffrey A Law (law@cygnus.com) + + * mn10300.c (symbolic_operand, legitimize_address): New functions. + * mn10300.h (LEGITIMIZE_ADDRESS): Call legitimize_address. + (GO_IF_LEGITIMATE_ADDRESS): Don't allow base + symbolic. + +Thu Oct 23 09:35:12 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Thu Oct 23 08:03:59 1997 J"orn Rennecke + + * dbxout.c (dbxout_start_new_source_file): Use output_quoted_string + for FILENAME. + +Wed Oct 22 00:34:12 1997 Jeffrey A Law (law@cygnus.com) + + * toplev.c (flag_exceptions): Default value is 2. + (compile_file): If flag_exceptions still has the value 2, then + set it to 0. + + * 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. + + * local-alloc.c (block_alloc): Don't lose if two SCRATCH expressions + are shared. + + * 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 + + * obstack.h (obstack_empty_p): Fix spurious space after backslash. + +Tue Oct 21 18:34:01 1997 Geoffrey KEATING + + * 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 + + * 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 + + * 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 + + * mips/mips.c (compute_frame_size): Not a leaf function if + profile_flag set. + +Mon Oct 20 14:16:38 1997 Geoffrey KEATING + + * rs6000/t-ppccomm: Use -msdata=none for crtstuff. + +Mon Oct 20 12:28:17 1997 Doug Evans + + * 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_ 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 + Jeff Law + Richard Kenner + + * 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. + + * 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. + + * make-l2.com: Support openVMS/Alpha. + + * vmsconfig.com: Fix to work on openVMS/Alpha and openVMS/VAX. + +Sun Oct 19 19:00:35 1997 J"orn Rennecke + + * longlong.h (count_leading_zeros): Add missing casts to USItype. + +Sun Oct 19 18:44:06 1997 Jeffrey A Law (law@cygnus.com) + + * i386/bsd386.h (ASM_COMMENT_START): Define. + +Sat Oct 18 13:47:15 1997 Jason Merrill + + * tree.c (restore_tree_status): Also free up temporary storage + when we finish a toplevel function. + (dump_tree_statistics): Print stats for backend obstacks. + +Sat Oct 18 12:47:31 1997 Doug Evans + + * expr.c (use_group_regs): Don't call use_reg for MEMs. + +Sat Oct 18 09:49:46 1997 Jason Merrill + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * rs6000.h (ROUND_TYPE_ALIGN): Don't blow up if no fields in record. + +Thu Oct 16 11:20:30 1997 Richard Henderson + + * 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) + + * version.c: Bump for snapshot. + +Wed Oct 15 21:38:18 1997 Richard Kenner + + * pa.c (move_operand): Respect -mdisable-indexing. + * pa.h (GO_IF_LEGITIMATE_ADDRESS): Likewise. + +Wed Oct 15 21:34:45 1997 David Edelsohn + + * rs6000.md (udivsi3, divsi3): Split into MQ and non-MQ cases for + PPC601. + (umulsidi3,umulsi3_highpart): Ditto. + (smulsi3_highpart_no_mq): Add !TARGET_POWER. + +Wed Oct 15 18:21:46 1997 Richard Henderson + + * 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. + +Wed Oct 15 18:16:05 1997 Richard Henderson + + 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. + +Wed Oct 15 17:42:41 1997 Jeffrey A Law (law@cygnus.com) + + * pa.c (following_call): Fail if the CALL_INSN is an indirect + call. + +Tue Oct 14 12:01:00 1997 Mark Mitchell + + * cplus-dem.c (demangle_signature): Don't look for return types on + constructors. Handle member template constructors. + +Tue Oct 14 11:30:29 1997 Jason Merrill + + * tree.c (expr_tree_cons, build_expr_list, expralloc): New fns. + * tree.h: Declare them. + +Fri Oct 10 13:46:56 1997 Doug Evans + + * configure.in: Handle --with-newlib. + * Makefile.in (LIBGCC2_CFLAGS): Add @inhibit_libc@. + + * sparc/t-sp64 (LIBGCC2_CFLAGS): Delete. + +Wed Oct 8 14:37:44 1997 Jeffrey A Law (law@cygnus.com) + + * config/ptx4.h: Fix typo. + +Wed Oct 8 08:57:20 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Tue Oct 7 16:27:34 1997 Manfred Hollstein + + * aclocal.m4: Substitute INSTALL. + * configure: Re-built. + +Tue Oct 7 15:37:35 1997 Jeffrey A Law (law@cygnus.com) + + * integrate.c (save_for_inline_copying): Avoid undefined pointer + operations. + (expand_inline_function): Likewise. + + * dwarf2out.c (output_call_frame_info): Reinstate last change + using flag_debug_asm check instead of flag_verbose_asm. + +Tue Oct 7 12:57:26 1997 Jim Wilson + + * dwarf2out.c (output_call_frame_info): Remove last change. + +1997-10-04 Andreas Schwab + + * frame.c (__frame_state_for): Execute the FDE insns until the + current pc value is strictly bigger than the target pc value. + +Tue Oct 7 11:00:42 1997 Jason Merrill + + * regclass.c (init_reg_modes): If we can't find a mode for the + register, use the previous one. + +Tue Oct 7 10:55:34 1997 Richard Henderson + + * haifa-sched.c (print_block_visualization): Call fprintf directly, + don't sprintf through an alloca'ed buffer. + +Tue Oct 7 10:52:29 1997 Thomas Koenig (ig25@rz.uni-karlsruhe.de) + + * reload.c (decompose): Always initialize val.base. + +Tue Oct 7 10:19:26 1997 Manfred Hollstein (manfred@lts.sel.alcatel.de) + + * 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. + +Tue Oct 7 11:41:21 1997 Michael Meissner + + * 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. + +Tue Oct 7 10:01:45 1997 Chip Salzenberg + + * Makefile.in (program_transform_name): Let autoconf substitute + the correct value. + +Tue Oct 7 09:54:35 1997 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (schedule_block): If the first real insn in a + block has any special notes attached to it, remove them. + +Tue Oct 7 09:48:51 1997 Richard Henderson + + * alpha.h (FLOAT_STORE_FLAG_VALUE): It's 2.0 not 0.5. + +Mon Oct 6 12:47:32 1997 Manfred Hollstein (manfred@lts.sel.alcatel.de) + + * m88k.c (m88k_begin_prologue): Remove superfluous backslash. + +Mon Oct 6 12:04:24 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (check-g77): New test target. + (CHECK-TARGETS): Add check-g77. + +Fri Oct 3 11:56:36 1997 Jason Merrill + + * toplev.c (rest_of_compilation): Defer all non-nested inlines. + +Fri Oct 3 15:49:27 1997 Michael Meissner + + * flow.c (print_rtl_with_bb): Cast alloca return value for + in_bb_p. + +Thu Oct 2 21:15:03 1997 Richard Henderson + + * i386.h (RETURN_ADDR_RTX): New definition that works for + __builtin_return_address(0) and -fomit-frame-pointer. + +Wed Oct 1 13:43:53 1997 Jim Wilson + + Bring over from FSF. + Tue Aug 5 16:10:45 1997 Jason Merrill + + * mips.c (function_arg): Handle passing a struct + containing a double in a DFmode register without the PARALLEL. + +Wed Oct 1 11:13:25 1997 Ian Lance Taylor + + * pexecute.c: Use spawn if __CYGWIN32__. + + * pexecute.c: Include "config.h" first, as per autoconf manual + (from Paul Eggert ). + +Wed Oct 1 01:44:36 1997 Philippe De Muyter + + * m68k/x-mot3300 (XCFLAGS): Disable as's long/short jump + optimisation for f/expr.o and f/stb.o. + +Tue Sep 30 23:48:57 1997 Jeffrey A Law (law@cygnus.com) + + * cse.c (this_insn_cc0_mode): Initialize. + +Tue Sep 30 23:09:40 1997 Thomas Koenig + + * cccp.c (expand_to_temp_buffer): Initialize all members of obuf. + + * haifa-sched.c (get_block_head_tail): Remove unneeded initialization. + +Tue Sep 30 23:06:43 1997 Richard Henderson + + * 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. + +Tue Sep 30 16:07:58 1997 Jim Wilson + + * except.c (find_exception_handler_labels): Correct argument to free. + +Tue Sep 30 11:00:00 1997 Brendan Kehoe + + * except.c (find_exception_handler_labels): Free LABELS when we're + done. + +Mon Sep 29 14:04:35 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Mon Sep 29 10:51:53 1997 Jason Merrill + + * flow.c (find_basic_blocks): Mark calls as potentially jumping + to the EH labels. + +Mon Sep 29 09:58:06 1997 Jeffrey A Law (law@cygnus.com) + + * configure.in: Substitute for "install" too. + * configure: Rebuilt. + +Mon Sep 29 00:38:42 1997 Aaron Jackson + + * Makefile.in (bootstrap-lean, compare-lean): New targets. + +Mon Sep 29 00:18:16 1997 Richard Henderson (rth@cygnus.com) + + * alias.c (base_alias_check): Two symbols can conflict if they + are accessed via AND. + (memrefs_conflict_p): Likewise. + + * alpha.h (SETUP_INCOMING_VARARGS): Emit a blockage insn + after flushing argument registers to the stack. + + * Makefile.in (mostlyclean): Remove .regmove files. + +Sun Sep 28 18:59:58 1997 Jason Merrill + + * libgcc2.c (__throw): Fix thinko. + +Sun Sep 28 12:00:52 1997 Mark Mitchell + + * 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. + +Sun Sep 28 01:55:04 1997 Philippe De Muyter + + * flow.c (print_rtl_with_bb): Cast alloca return values for variables + start and end. + +Sun Sep 28 01:05:16 1997 Jeffrey A Law (law@cygnus.com) + + * frame.c: Remove last change. + * dwarf2.h: Remove last change. + * tree.h: Add declarations of DWARF2 unwind info support + functions. + +Sat Sep 27 11:02:38 1997 Jason Merrill + + * 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 26 08:54:59 1997 Paul Eggert + + * 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 26 09:00:13 1997 Andreas Schwab + + * 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. + + * integrate.c (expand_inline_function): Make sure there is at + least one insn that can be used as an insertion point. + +Wed Sep 24 21:34:06 1997 Jason Merrill + + * dwarf2out.c: s/flag_verbose_asm/flag_debug_asm/ + +Wed Sep 24 22:05:30 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Wed Sep 24 17:36:23 1997 Doug Evans + + Bring over from FSF. + + Wed Sep 24 19:17:08 1997 Doug Evans + + * 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 + + * 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. + + Tue Sep 23 19:02:46 1997 Doug Evans + + * sparc/linux-aout.h (COMMENT_BEGIN): Delete. + * sparc/linux.h (COMMENT_BEGIN): Likewise. + * sparc/linux64.h (COMMENT_BEGIN): Likewise. + + Tue Sep 23 14:48:18 1997 David S. Miller + + 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. + + Sat Sep 20 03:07:54 1997 Doug Evans + + * 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. + + Wed Sep 17 15:04:19 1997 Doug Evans + + * 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. + + Mon Sep 8 08:45:19 1997 Richard Kenner + + * 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. + +Tue Sep 23 12:34:51 1997 Richard Kenner + + * fold-const.c (make_range): Correctly handle cases of converting + from unsigned to signed type. + +Tue Sep 23 12:34:51 1997 Bernd Schmidt + + * 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. + +Tue Sep 23 08:32:51 1997 Jason Merrill + + * 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 + + * 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) + + * loop.c (indirect_jump_in_function_p): Return 0 + by default. + +Tue Sep 23 00:33:55 1997 Jeffrey A Law (law@cygnus.com) + + * rs6000/xm-rs6000.h: Fix thinko in last change. + * rs6000/xm-sysv4.h: Likewise. + +Mon Sep 22 19:33:53 1997 Jim Wilson + + * mips.c (save_restore_insns): Only set RTX_FRAME_RELATED_P if store_p. + +Mon Sep 22 14:41:00 1997 Jeffrey A Law (law@cygnus.com) + + * reg-stack.c (find_blocks): Fix thinko in last change. + +1997-09-21 Andreas Schwab + + * m68k.c (output_function_prologue): Add dwarf2 support. + + * m68k.h (INCOMING_RETURN_ADDR_RTX, DWARF_FRAME_REGNUM, + INCOMING_FRAME_SP_OFFSET): New definitions. + +Mon Sep 22 11:36:42 1997 David S. Miller + + * 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. + + * sparc.h (INCOMING_FRAME_SP_OFFSET): Define to + SPARC_STACK_BIAS for sake of dwarf2 on sparc64. + +Mon Sep 22 11:21:33 1997 J. Kean Johnston + + * 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. + +Mon Sep 22 02:10:43 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sun Sep 21 17:45:45 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * 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. + + * cse.c (simplify_relational_operation): Set h0u just like h0s. + Similarly for h1u and h1s. + + * 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. + + * loop.c (fix_bct_param): Delete unused function. + (check_bct_param): Likewise. + +Sat Sep 20 16:22:06 1997 Jason Merrill + + * frame.c (__deregister_frame): Check properly for initialized object. + +Fri Sep 19 20:51:03 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * alpha/linux.h (HANDLE_SYSV_PRAGMA): Defined. + +Fri Sep 19 18:53:50 1997 J"orn Rennecke + + * jump.c (thread_jumps): check can_reverse_comparison_p before + threading a reversed-condition jump. + + * sched.c (update_flow_info): Don't pass SCRATCH to dead_or_set_p. + * haifa-sched.c (update_flow_info): Likewise. + +Thu Sep 18 21:13:40 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (BOOT_CFLAGS): Use -O2. + + * configure.in (strtoul, bsearch): Have autoconf check for these + functions. + * configure, config.in: Rebuilt. + + * 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. + +Thu Sep 18 14:22:22 1997 Jason Merrill + + * 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. + + * 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 >. + +Thu Sep 18 10:43:07 1997 Nick Clifton + + * 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. + +1997-09-18 Brendan Kehoe + + * configure.in, configure: Make sure to create the stage* and include + symbolic links in each subdirectory. + +Thu Sep 18 01:47:06 1997 Jeffrey A Law (law@cygnus.com) + + * pa.md (reload_peepholes): Don't allow addresses with side + effects for the memory operand. + +Wed Sep 17 18:19:53 1997 Jason Merrill + + * libgcc2.c (find_exception_handler): Subtract one from our PC when + looking for a handler, to avoid hitting the beginning of the next + region. + + * except.c (expand_builtin_set_return_addr_reg): Use force_operand. + +Wed Sep 17 18:33:59 1997 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. + +Wed Sep 17 14:11:38 1997 Jeffrey A Law (law@cygnus.com) + + * v850.c (construct_save_jarl): Fix thinko in last change. + +Wed Sep 17 09:53:07 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Tue Sep 16 14:22:36 1997 Jason Merrill + + * libgcc2.c (find_exception_handler): Not found is -1. + + * integrate.c (expand_inline_function): Move expand_start_bindings + after expanding the arguments. + +Tue Sep 16 11:13:46 1997 Jim Wilson + + * 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. + +Tue Sep 16 09:18:52 1997 Jason Merrill (jason@cygnus.com) + + * expr.c (expand_expr, case TARGET_EXPR): Call mark_addressable + again for the slot after we give it RTL. + +Tue Sep 16 00:13:20 1997 Nick Clifton + + * 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. + + * v850.h (pattern_is_ok_for_prologue, + pattern_is_ok_for_epilogue, register_is_ok_for_epilogue): New + predicates. + + * v850.md: Replace prologue and epilogue patterns with a + match_parallel pattern. + +Mon Sep 15 22:53:01 1997 Jeffrey A Law (law@cygnus.com) + + * aclocal.m4: Add replacement for AC_PROG_INSTALL. + * configure.in: Use EGCS_PROG_INSTALL. + +Mon Sep 15 22:40:55 1997 Jim Wilson (wilson@cygnus.com) + + * dwarf2out.c (gen_subprogram_die): Handle redefinition of an + extern inline function. + +Mon Sep 15 22:40:55 1997 Richard Henderson (rth@cygnus.com) + + * 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. + +Mon Sep 15 15:24:00 1997 Richard Henderson + + * alpha.md (movdi): Handle CONST_DOUBLE for TARGET_BUILD_CONSTANTS. + + * alpha/alpha.c (output_prolog): New variable sa_reg. Use it for + out-or-range reg_offset. + (output_epilog): Likewise. + +Mon Sep 15 15:39:26 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + +Mon Sep 15 11:43:38 1997 Jason Merrill + + Support dwarf2 unwinding on PUSH_ROUNDING targets like the x86. + + * 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. + + * 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. + + * 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. + + * 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. + + * collect2.c (write_c_file_stat, write_c_file_glob): Declare + __register_frame_table and __deregister_frame. + +1997-09-15 Brendan Kehoe + + * 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. + +Sun Sep 14 21:01:23 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in: Various changes to build info files + in the object tree rather than the source tree. + +Sun Sep 14 12:24:30 1997 Jeffrey A Law (law@cygnus.com) + + * fixinc.math: New file to fix math.h on some systems. + * configure.in (freebsd, netbsd): Use fixinc.math on these + systems. + * configure: Rebuilt. + +Sun Sep 14 11:11:05 1997 Jeffrey A Law (law@cygnus.com) + + * regmove.c (regmove_optimize): If we end up moving the + original insn due to lifetime overlaps, make sure to move + REG_NOTES too. + +Sat Sep 13 15:51:11 1997 Manfred Hollstein + + * Makefile.in (INSTALL_{PROGRAM,DATA}): Use value found by configure. + +Sat Sep 13 12:57:26 1997 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. + +Fri Sep 12 13:49:58 1997 Jason Merrill + + * except.h: Prototype dwarf2 hooks. + * expr.c: Adjust. + +Thu Sep 11 17:43:55 1997 Jim Wilson + + * configure.in (native_prefix): Delete. + (mips-dec-netbsd): Don't set prefix. + (*linux*): Don't set prefix. + +Thu Sep 11 15:48:32 1997 Fred Fish + + * protoize.c: Include only if HAVE_VARARGS_H is + defined. If not defined, include 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. + + * 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 Sep 10 21:37:30 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + + * Makefile.in (compare): Exit with nonzero status if there + are comparison failures. Note which files failed the + comparison test in .bad_compare. + +Wed Sep 10 17:05:46 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * config/alpha/elf.h (CPP_PREDEFINES): Remove -D__PIC__ -D__pic__. + +Wed Sep 10 16:37:28 1997 Fred Fish + + * 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. + +Thu Sep 11 11:09:43 1997 Jeffrey A Law (law@cygnus.com) + + * loop.c (strength_reduce): Fix typo. + +Wed Sep 10 16:01:15 1997 Jim Wilson + + * 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. + +Wed Sep 10 14:58:40 1997 Jim Wilson + + * emit-rtl.c (gen_lowpart_common): For a SUBREG, add in word when + create new subreg. + +Wed Sep 10 15:19:22 1997 Jeffrey A Law (law@cygnus.com) + + * config.sub: Accept 'amigados' for backward compatability. + +Wed Sep 10 14:05:08 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * Makefile.in (testsuite/site.exp): New target. + (check-gcc, check-g++): Depend on testsuite/site.exp. + Don't stop for failure. + +Wed Sep 10 12:59:57 1997 Jason Merrill + + * expr.c (expand_builtin): Only support __builtin_dwarf_fp_regnum() + if DWARF2_UNWIND_INFO. + +Wed Sep 10 11:49:20 1997 Jason Merrill + + Add support for exception handling using DWARF 2 frame unwind info. + Currently works on SPARC and MIPS, and almost on x86. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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 + + * i386.c (ix86_prologue): Add dwarf2 support for !do_rtl case. + +Wed Sep 10 08:17:10 1997 Torbjorn Granlund + + * except.c (eh_outer_context): Do masking using expand_and. + +Wed Sep 10 01:38:30 1997 Doug Evans + + 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. + +Wed Sep 10 01:32:54 1997 Jeffrey A Law (law@cygnus.com) + + * expr.c (clear_storage): Use CONST0_RTX instead of const0_rtx. + when clearing non-BLKmode data. + +Wed Sep 10 00:29:29 1997 Manfred Hollstein + + * m88k/sysv3.h (INITIALIZE_TRAMPOLINE) Define. + * libgcc2.c (__enable_execute_stack): Provide for sysV88 too. + + * xm-m88k.h (USG): Only define if it hasn't already been defined. + + * Makefile.in (risky-stage1): Delete gratutious whitespace. + + * Makefile.in (clean): Delete libgcc1-test. + + * Makefile.in (INSTALL): cd to $(srcdir) before running texinfo. + +Tue Sep 9 17:07:36 1997 Stan Cox + + * m88k.c (m88k_expand_prologue): Set MEM_IN_STRUCT_P of va_list + template. + +Tue Sep 9 09:50:02 1997 Richard Kenner + + * dwarf2out.c (output_call_frame_info): Call named_section. + +Tue Sep 9 09:12:17 1997 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (print_value): Fix last change. + +Tue Sep 9 01:30:37 1997 Jason Merrill + + * mips.h (DWARF_FRAME_REGNUM): Use the same numbering regardless of + write_symbols. + +Mon Sep 8 16:32:43 1997 Jason Merrill + + * mips.c (function_prologue): Set up the CFA when ABI_32. + + * 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. + + * 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. + + * expr.c (expand_builtin_return_addr): Only SETUP_FRAME_ADDRESSES if + count > 0. + + * varasm.c (exception_section): Check EXCEPTION_SECTION first. + +Mon Sep 8 15:15:11 1997 Nick Clifton + + * 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. + +Mon Sep 8 18:26:35 1997 Jim Wilson + + * m68k.h (MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): In MOTOROLA + cases, add %# and %/, and add : to make them into extended asms. + +Sun Sep 7 23:57:50 1997 Weiwen Liu + + * alias.c (init_alias_analysis): Clean up incompatible pointer + type warning in bzero. + * regmove.c (regmove_optimize): Ditto. + * haifa-sched.c (find_rgns): Ditto. + + * haifa-sched.c (print_value): Clean up ptr->int cast + warnings. + +Sun Sep 7 23:18:32 1997 Fred Fish + + * INSTALL: Change 'amigados' to 'amigaos' to match current usage. + * install.texi (Configurations): Ditto. + * config.sub: Ditto. + +Sun Sep 7 22:56:56 1997 Weiwen Liu (liu@hepvms.physics.yale.edu) + + * Makefile.in (sdbout.o): Depend on insn-config.h. + +Sun Sep 7 18:44:50 1997 Jim Wilson + + * m68k/m68k.h (TARGET_SWITCHES): For 68000, 68302, subtract MASK_68881. + For 68303, 68332, cpu32, subtract MASK_68040_ONLY. + +Sun Sep 7 18:30:46 1997 Jason Merrill + + * 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. + +Sun Sep 7 14:19:39 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Sun Sep 7 14:17:36 1997 Torbjorn Granlund (tege@pdc.kth.se) + + * 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. + +Sun Sep 7 13:46:46 1997 Jeffrey A Law (law@cygnus.com) + + * final.c (shorten_branches): During first pass, assume worst + possible alignment for ADDR_VEC and ADDR_VEC_DIFF insns. + + * Makefile.in (distclean): Remove various things left around + by running the testsuite. + +Sun Sep 7 13:16:06 1997 Manfred Hollstein + + * configure.in (out_file): Emit definition to config.status in order + to have a defined value for configure.lang. + * configure: Re-built. + +Sun Sep 7 09:59:08 1997 Jan-Jaap van der Heijden (J.J.vanderHeijden@student.utwente.nl) + + * configure.in: Make symlink to as-new rather than as.new. Similarly + for ld-new. + * configure: Rebuilt. + +Fri Sep 5 16:54:55 1997 Jim Wilson + + * profile.c (output_func_start_profiler): Set DECL_EXTERNAL to zero. + +Fri Sep 5 16:16:44 1997 Christian Kuehnke + + * sparc/sparc.md: Add ultrasparc scheduling support. + * sparc/sparc.h (RTX_COSTS): For MULT give v9 a cost of 25 insns. + +Fri Sep 5 14:04:59 1997 Philippe De Muyter + + * integrate.c (save_for_inline_copying): Use 0, not NULL_PTR, + as initial value for real_label_map. + (copy_for_inline): Likewise. + +Fri Sep 5 13:36:44 1997 J"orn Rennecke + + * 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. + +Fri Sep 5 10:08:44 1997 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. + +Fri Sep 5 09:37:50 1997 Jim Wilson (wilson@cygnus.com) + + * sdbout.c (plain_type_1, case ARRAY_TYPE): Verify that TYPE_DOMAIN + has integer TYPE_{MAX,MIN}_VALUE before using them. + + * m68k/m68k.h (MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): Add + __HPUX_ASM__ versions. + +Fri Sep 5 09:08:44 1997 Jeffrey A Law (law@cygnus.com) + + * install.sh: Delete duplicate install script. + +Thu Sep 4 23:14:27 1997 Stan Cox (coxs@dg-rtp.dg.com) + + * reg-stack.c (subst_stack_regs): Pop the stack register for a + computed goto which sets the same stack register. + + * 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. + +Thu Sep 4 15:02:27 1997 Jim Wilson + + * mips.md (nonlocal_goto_receiver): Define. + + * profile.c (output_arc_profiler): Check next_insert_after for non + NULL before deferencing it. + + * i386/t-sol2 (TARGET_LIBGCC2_CFLAGS): Define to -fPIC. + +Thu Sep 4 14:51:57 1997 Jeffrey A Law (law@cygnus.com) + + * i386.h (CPP_CPU_DEFAULT): Avoid using #elif. + +Thu Sep 4 15:01:49 1997 Michael Meissner + + * toplev.c (rest_of_compilation): For passes starting with + flow_analysis, use print_rtl_with_bb instead of print_rtl. + + * print-rtl.c (print_rtl_single): Print a single rtl value to a + file. + + * 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. + +Thu Sep 4 11:51:43 1997 Jim Wilson + + * toplev.c (main): Change #elif to #else/#ifdef + + * tlink.c: Include ctype.h. + * ginclude/va-mips.h: Add _VA_MIPS_H_ENUM ifdef/define/endif. + +Thu Sep 4 11:17:16 1997 Mikeael Meissner (meissner@cygnus.com) + + * bitmap.c: Conditionally include stdlib.h. + (free): Provide a declaration if NEED_DECLARATION_FREE. + +Thu Sep 4 09:58:53 1997 Joel Sherrill (joel@OARcorp.com) + + * i960/i960.h: Added default for SUBTARGET_SWITCHES macro. + +Thu Sep 4 09:53:20 1997 Jim Wilson (wilson@cygnus.com) + + * profile.c (output_arc_profiler): Verify next_insert_after is an + INSN before and after skipping a stack pop. + +Thu Sep 4 07:39:19 1997 J"orn Rennecke + + * final.c (shorten_branches): Don't count the lengths of deleted + instructions. + +Thu Sep 4 09:43:01 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + +Thu Sep 4 11:04:21 1997 Michael Meissner + + * bitmap.h (EXECUTE_IF_AND_IN_BITMAP): New macro, to iterate over + two bitmaps ANDed together. + (bitmap_print): Declare. + + * 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. + + * basic-block.h (EXECUTE_IF_AND_IN_REG_SET): New macro, invoke + EXECUTE_IF_AND_IN_BITMAP. + +Wed Sep 3 10:39:42 1997 Jim Wilson + + * alias.c (true_dependence): Address with AND can alias scalars. + (anti_dependence, output_dependence): Likewise. + + * alias.c (true_dependence): Test x for BLKmode, in addition to mem. + +Wed Sep 3 09:28:50 CDT 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, sh/rtems.h, + sparc/rtems.h (subtarget_switches): Removed SUBTARGET_SWITCHES + definitions. Use -qrtems instead of -mrtems. + +Wed Sep 3 09:05:41 1997 Robert Lipe (robert@dgii.com) + + * xm-sco5.h (sys_siglist): Define. + (SYS_SIGLIST_DECLARED): Likewise. + +Tue Sep 2 23:33:33 1997 Jeffrey A Law (law@cygnus.com) + + * expr.c (convert_move): Handle truncation from TQFmode to QFmode. + +Wed Sep 3 02:09:30 1997 Torbjorn Granlund + + * except.c (eh_outer_context): Expand masking operation using + expand_binop. + +Tue Sep 2 18:09:39 1997 Jim Wilson + + * alpha.md (floatdisf2-1): New pattern. + +Tue Sep 2 18:41:55 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * mn10200.h (INITIALIZE_TRAMPOLINE): PC relative instructions + are relative to the next instruction, not the current instruction. + +Tue Sep 2 14:22:43 1997 Jim Wilson + + * 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. + +Tue Sep 2 12:48:11 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * 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. + +Tue Sep 2 12:00:36 1997 Jim Wilson + + * 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. + +Tue Sep 2 13:42:38 1997 Paul N. Hilfinger + + * fixincludes: Permits spaces between # and define. Discard C++ + comments in sys/pci.h on HP/UX 10.20. + +Mon Sep 1 22:13:18 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for snapshot. + + * 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. + + * haifa-sched.c (move_insn): Handle notes correctly for insns + with SCHED_GROUP_P set. + +Mon Sep 1 16:58:57 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * alpha/xm-linux.h (USE_BFD): Undef before define. + +Mon Sep 1 16:25:34 1997 Jim Wilson + + * cse.c (cse_insn): Don't record BLKmode values. + +Mon Sep 1 11:25:47 1997 Stephen Williams (steve@icarus.icarus.com) + + * i960.h (LINK_SPEC): Handle "-mjX" and "-mrp" switches. + +Mon Sep 1 08:29:46 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * Makefile.in: Add several missing "else true" clauses. + + * 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. + +Sat Aug 30 22:54:26 1997 Jim Wilson + + * unroll.c (calculate_giv_inc): Handle increment with code PLUS. + +Sat Aug 30 10:49:46 1997 David Edelsohn + + * rs6000.md: Make DF fused-add operations pay attention to + -mno-fused-add. + +Fri Aug 29 19:19:54 1997 Jim Wilson + + * i386/xm-sysv4.h (DONT_DECLARE_SYS_SIGLIST): Define. + +Fri Aug 29 16:13:51 1997 Jeffrey A Law (law@cygnus.com) + + * pa.md (reload_peepholes): Make sure operand is a REG before + examining REGNO. Allow general registers too. + +Fri Aug 29 11:42:04 1997 Jim Wilson + + * varasm.c (mark_constants): Don't look inside CONST_DOUBLEs. + +Fri Aug 29 09:33:20 1997 Philipp Thomas (kthomas@lxi165.gwdg.de) + + * dwarf2out.c (build_abbrev_table): Use xrealloc, not xmalloc + to reallocate abbrev_die_table. + +Thu Aug 28 15:14:46 1997 Jim Wilson + + * m68k/m68k.md (iorsi_zexthi_ashl16): Disable. + +1997-08-27 Andreas Schwab + + * Makefile.in (config.status): Depend on version.c + + * expr.h (insn_gen_function): Reenable prototype. + + * expr.c (move_by_pieces_1, clear_by_pieces_1): Fix prototype of + first parameter. + +Thu Aug 28 13:01:43 1997 Jim Wilson + + * i386.c (ix86_expand_epilogue): Emit blockage instruction when pic. + +Thu Aug 28 07:03:15 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for latest snapshot. + + * 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. + + * configure: Rebuilt. + +Wed Aug 27 21:32:20 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + +Wed Aug 27 18:08:51 1997 Bob Manson (manson@cygnus.com) + + * 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. + +Wed Aug 27 16:35:29 1997 Richard Henderson + + * alpha/xm-alpha.h (alloca): Define alloca to builtin_alloca for GNUC + if not already defined, and USE_C_ALLOCA not defined. + +Wed Aug 27 16:08:43 1997 Jim Wilson + + * config.guess: Replace with script that uses ../config.guess. + + * config/alpha/elf.h (DEFAULT_VTABLE_THUNKS): New. Defined as 1 + if USE_GNULIBC_1 is not defined. + +Wed Aug 27 15:49:12 1997 Richard Henderson + + * 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. + +Wed Aug 27 11:52:58 1997 Jim Wilson + + * m68k.md (iorsi3_internal): Readd ! TARGET_5200 check lost in + last change. + +Wed Aug 27 01:56:18 1997 Doug Evans + + * loop.c (combine_movables): Earlier insns don't match later ones. + +Wed Aug 27 01:24:25 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * config/linux.h (CC1_SPEC): Define it only if not defined. + + * config/m68k/linux.h (CC1_SPEC): Undefine it before include + + + * config/linux.h (DEFAULT_VTABLE_THUNKS): New. Defined as 1 if + USE_GNULIBC_1 is not defined. + + * config/rs6000/linux.h (DEFAULT_VTABLE_THUNKS): New. Defined as 1. + + * config/sparc/linux.h (DEFAULT_VTABLE_THUNKS): New. Defined + as 1 if USE_GNULIBC_1 is not defined. + +Wed Aug 27 00:49:14 1997 Jeffrey A Law (law@cygnus.com) + + * 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. + + * 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. + +Wed Aug 27 00:30:00 1997 Bernd Schmidt + + * 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. + +Tue Aug 26 18:50:32 1997 Jim Wilson + + * reload.c (find_reloads, case '0'): Reject matching a non-offsettable + address where an offsettable address is required. + +Tue Aug 26 17:54:56 1997 Michael P. Hayes (michaelh@ongaonga.chch.cri.nz> + + * loop.c (check_final_value): Don't miss a biv increment in a + parallel. + +Tue Aug 26 12:03:49 1997 Jim Wilson (wilson@cygnus.com) + + * dwarfout.c (dwarfout_file_scope_decl, case TYPE_DECL): Check + TYPE_DECL_IS_STUB instead of DECL_NAME. + +Mon Aug 25 23:27:10 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * objc/Make-lang.in ($(OBJC_O)): Also depend on cc1obj. + +Mon Aug 25 23:27:10 1997 Jim Meyering + + * objc/Make-lang.in ($(OBJC_O)): Also depend on $(GCC_PASSES). + +Mon Aug 25 13:12:24 1997 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (find_pre_sched_live): Remove #if 0 code. + (find_post_sched_live): Likewise. + + * haifa-sched.c (schedule_block): Remove old code to get arguments + from hard regs into pseudos early. + +Mon Aug 25 08:55:00 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for new snapshot. + + * 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. + + * pa.c (secondary_reload_class): (mem (mem ... )) does not need + secondary reloads. + + * pa.c (hppa_builtin_saveregs): Emit a blockage insn after the + store of the argument registers. + +Mon Aug 25 08:39:02 1997 Craig Burley (burley@gnu.ai.mit.edu) + + * fold-const.c (multiple_of_p): New function. + (fold): Turn some cases of *_DIV_EXPR into EXACT_DIV_EXPR. + +Mon Aug 25 01:47:41 1997 Jeffrey A Law (law@cygnus.com) + + * expr.h (insn_gen_function): Temporarily remove prototype. + +Sun Aug 24 17:22:21 1997 Jim Wilson + + * Makefile.in (install-info): Don't cd into srcdir. Add srcdir to + filenames. Use sed to extract base filename for install. + +Sat Aug 23 18:19:40 1997 John F. Carr + + * unroll.c (find_splittable_givs): Only share if two givs have the + same add and multiply values. + +Sat Aug 23 14:36:27 1997 Jim Wilson + + * m68k/next.h (GO_IF_INDEXABLE_BASE): Fix typo in undef. + * m68k/m68kemb.h (LIB_SPEC): Add missing comment end before it. + +Sat Aug 23 00:18:22 1997 Jeffrey A Law (law@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. + +Fri Aug 22 14:05:55 1997 Jim Wilson + + * alias.c (true_dependence): Pass x_addr not x to varies. + + * 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. + +Thu Aug 21 23:52:16 1997 John F. Carr + + * 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. + +Thu Aug 21 20:17:37 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump for new snapshot. + +Thu Aug 21 17:28:00 1997 Jim Wilson + + * 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. + +Thu Aug 21 10:22:19 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (install-common): Put gcov comment at start of line. + +Wed Aug 20 22:47:33 1997 Jeffrey A Law (law@cygnus.com) + + * alias.c (init_alias_analysis): When simplifying the reg_base_value + array, simplify entries for hard registers too. + +Wed Aug 20 12:35:47 1997 Dave Love + + * dwarf2.h (enum dwarf_call_frame_info): Remove trailing comma from + list. + +Wed Aug 20 11:58:33 1997 Jim Wilson + + * stmt.c (start_cleanup_deferal, end_cleanup_deferal): Test + block_stack before dereferencing it. + +Wed Aug 20 11:57:11 1997 Michael Meissner + + * rs6000.h (ISSUE_RATE): Define instead of MACHINE_issue_rate. + +Tue Aug 19 17:10:56 1997 Jason Merrill + + * cplus-dem.c: Add 'extern' to prepends_underscore. + +Tue Aug 19 09:34:57 1997 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (ISSUE_RATE): Renamed from MACHINE_issue_rate. + (get_issue_rate): Delete. + * pa.h (ISSUE_RATE): Define. + + * configure.in: Turn on haifa by default for the PA. + * 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. + + * haifa-sched.c (debug_dependencies): Fix thinko. + + * Makefile.in (EXPECT, RUNTEST, RUNTESTFLAGS): Define. + (site.exp, check, check-g++, check-gcc): New targets. + + * haifa-sched.c: Make lots of variables static. + +Tue Aug 19 07:18:34 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * expr.h, real.h: Finish prototyping. + +Mon Aug 18 21:49:02 1997 Jim Wilson + + * 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. + +Mon Aug 18 17:39:02 1997 Mike Meissner + + * configure.in ({powerpc,rs6000}*-*-*, --with-cpu): Remove single + quotes around the name. + * configure: Regenerate. + +Mon Aug 18 13:46:47 1997 Jim Wilson + + * Makefile.in (stmp-multilib-sub): Fix typo in last change. + +Thu Aug 7 10:33:13 1997 Manfred Hollstein + + * 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. + +Sun Aug 17 15:42:17 1997 Dave Love (d.love@dl.ac.uk) + + * configure.in: Expurgate `broken_install' (install is + autoconfed). + + * configure.lang: Substitute autoconfed ${INSTALL} (not currently + relevant). + +Sat Aug 16 01:08:12 1997 Jeffrey A Law (law@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. + +Fri Aug 15 23:48:32 1997 Jeffrey A Law (law@cygnus.com) + + * haifa-sched.c (find_post_sched_live): Call FREE_REG_SET as needed. + (schedule_region): Likewise. + (schedule_insns): Likewise. + + * PROJECTS: Update with Haifa stuff. + +Fri Aug 15 12:49:56 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Change the version string to look like: + egcs-2.90.00 970814 (gcc2-970802 experimental). + + * loop.c (is_conditional_branch): Make definition match declaration. + + * gcc.c: Take out experimental snapshot warning message. + +Fri Aug 15 13:43:39 1997 Michael Meissner + + * 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. + +Wed Aug 13 17:32:38 1997 Jason Merrill + + * expr.c (expand_expr, case TARGET_EXPR): Call mark_addressable + again for the slot after we give it RTL. + +Wed Aug 13 01:03:37 1997 Doug Evans + + * configure.in (haifa configury): Fix typo. + * configure: Regenerate. + +Tue Aug 12 10:20:36 1997 Jeffrey A Law (law@cygnus.com) + + * version.c: Bump version to "gcc-3.0.0 970802 experimental". + + * gcc.info*: Rebuilt. + + * 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. + +Mon Aug 11 14:50:55 1997 Jeffrey A Law (law@cygnus.com) + + * Integrate Haifa instruction scheduler. + * Makefile.in (ALL_CFLAGS): Add SCHED_CFLAGS. Prefix all references + to sched with $(SCHED_CFLAGS. + * configure.in: Handle --enable-haifa. + * 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. + +Local Variables: +add-log-time-format: current-time-string +End: diff --git a/contrib/gcc/LANGUAGES b/contrib/gcc/LANGUAGES new file mode 100644 index 0000000..bce134c --- /dev/null +++ b/contrib/gcc/LANGUAGES @@ -0,0 +1,79 @@ +Right now there is no documentation for the GCC tree -> rtl interfaces +(or more generally the interfaces for adding new languages). + +Such documentation would be of great benefit to the project. Until such +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. + +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 + declaration is: int lang_decode_option (int argc, char** argv). It now + returns the number of input strings processed, or 0 if the option is + unknown. + +Jun 7, 1998: + Front-ends must now define lang_init_options. It is safe for this + function to do nothing. See c-lang.c. + +Apr 21, 1998: + Front ends which link with c-common or other files from the C/C++ + front-ends may need to handle TI types. Look for references to + [unsigned]int_DI_type_node in your front end. If you have references + to these variables, you'll need up update the front end. + + To update the front end you must mirror all the code which currently + deals with intDI_type_node to also handle intTI_type_node. + + +Apr 7, 1998: + The interface between toplev.c and the language front ends for opening the + source file has changed: + + o init_lex() has been renamed to init_parse (char *filename) where filename + is the name of the source file. + o The code in toplev.c which opened the source file should be moved to + the new init_parse function. + o toplev.c now calls finish_parse() instead of closing the source file + using fclose(). This should now be done in finish_parse, if necessary. + +Apr 1, 1998: + Front-ends must now define lang_print_xnode. It is safe for this + function to do nothing. See c-lang.c. + +Feb 1, 1998: + + GCC used to store structure sizes & offsets to elements as bitsize + quantities. This causes problems because a structure can only be + (target memsize / 8) bytes long (this may effect arrays too). This + is particularly problematical on machines with small address spaces. + + So: + + All trees that represent sizes in bits should have a TREE_TYPE of + bitsizetype (rather than sizetype). + + Accordingly, when such values are computed / initialized, care has to + be takes to use / compute the proper type. + + When a size in bits is converted into a size in bytes, which is expressed + in trees, care should be taken to change the tree's type again to sizetype. + + We've updated C, C++, Fortran & Objective-C to work with the new + scheme. Other languages will need to be updated accordingly. + Contact amylaar@cygnus.com for additional information. + +?? 1997: + + In an effort to decrease cache thrashing and useless loads we've changed the + third argument to the DEFTREECODE macro to be a single char. This will + effect languages that defined their own tree codes (usually in a .def file). + + Old way: + + DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", "d", 0) + + New way: + + DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0) diff --git a/contrib/gcc/Makefile.in b/contrib/gcc/Makefile.in index 7ab05ff..15a789e 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-94, 1995 Free Software Foundation, Inc. +# Copyright (C) 1987, 88, 90-97, 1998 Free Software Foundation, Inc. #This file is part of GNU CC. @@ -26,16 +26,24 @@ # Suppress smart makes who think they know how to automake Yacc files .y.c: +# Directory where sources are, from where we are. +srcdir = @srcdir@ +VPATH = @srcdir@ + # Variables that exist for you to override. # See below for how to change them for certain systems. # List of language subdirectories. # This is overridden by configure. -SUBDIRS = +SUBDIRS =@subdirs@ # Selection of languages to be made. # This is overridden by configure. -LANGUAGES = c objective-c proto +LANGUAGES = c proto gcov$(exeext) @all_languages@ + +# Selection of languages to be made during stage1 build. +# This is overridden by configure. +BOOT_LANGUAGES = c @all_boot_languages@ ALLOCA = ALLOCA_FLAGS = @@ -45,10 +53,17 @@ 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 +# 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. # XCFLAGS is used for most compilations but not when using the GCC just built. +# TCFLAGS is used for compilations with the GCC just built. XCFLAGS = +TCFLAGS = CFLAGS = -g -BOOT_CFLAGS = -O $(CFLAGS) +BOOT_CFLAGS = -O2 $(CFLAGS) +WARN_CFLAGS = # These exists to be overridden by the x-* and t-* files, respectively. X_CFLAGS = T_CFLAGS = @@ -56,24 +71,37 @@ T_CFLAGS = X_CPPFLAGS = T_CPPFLAGS = -CC = cc -BISON = bison +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 +# a full pathname. +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` BISONFLAGS = -LEX = flex +LEX = `if [ -f $(objdir)/../flex/flex ] ; then echo $(objdir)/../flex/flex ; else echo flex ; fi` LEXFLAGS = AR = ar -OLDAR_FLAGS = qc AR_FLAGS = rc +LN = @symbolic_link@ +DLLTOOL = dlltool SHELL = /bin/sh # on sysV, define this as cp. -INSTALL = install -c +INSTALL = @INSTALL@ +# Some systems may be missing symbolic links, regular links, or both. +# Allow configure to check this and use "ln -s", "ln", or "cp" as appropriate. +LN=@LN@ +LN_S=@LN_S@ # These permit overriding just for certain files. -INSTALL_PROGRAM = $(INSTALL) -INSTALL_DATA = $(INSTALL) +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ MAKEINFO = makeinfo +MAKEINFOFLAGS = TEXI2DVI = texi2dvi # For GNUmake: let us decide what gets passed to recursive makes. MAKEOVERRIDES = +@SET_MAKE@ # Define this as & to perform parallel make on a Sequent. # Note that this has some bugs, and it seems currently necessary @@ -97,10 +125,11 @@ CCLIBFLAGS = -O # Version of ar to use when compiling libgcc1.a. OLDAR = ar +OLDAR_FLAGS = qc # Target to use when installing include directory. Either # install-headers-tar or install-headers-cpio. -INSTALL_HEADERS_DIR = install-headers-tar +INSTALL_HEADERS_DIR = @build_install_headers_dir@ # Header files that are made available under the same name # to programs compiled with GCC. @@ -108,11 +137,15 @@ USER_H = $(srcdir)/ginclude/stdarg.h $(srcdir)/ginclude/stddef.h \ $(srcdir)/ginclude/varargs.h $(srcdir)/ginclude/va-alpha.h \ $(srcdir)/ginclude/va-h8300.h $(srcdir)/ginclude/va-i860.h \ $(srcdir)/ginclude/va-i960.h $(srcdir)/ginclude/va-mips.h \ - $(srcdir)/ginclude/va-m88k.h $(srcdir)/ginclude/va-pa.h \ + $(srcdir)/ginclude/va-m88k.h $(srcdir)/ginclude/va-mn10200.h \ + $(srcdir)/ginclude/va-mn10300.h $(srcdir)/ginclude/va-pa.h \ $(srcdir)/ginclude/va-pyr.h $(srcdir)/ginclude/va-sparc.h \ $(srcdir)/ginclude/va-clipper.h $(srcdir)/ginclude/va-spur.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 \ - $(srcdir)/ginclude/proto.h $(EXTRA_HEADERS) + $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) \ + $(srcdir)/ginclude/proto.h $(srcdir)/ginclude/stdbool.h # Target to use whe installing assert.h. Some systems may # want to set this empty. @@ -126,27 +159,62 @@ GCC_FOR_TARGET = ./xgcc -B./ # This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET. # It omits XCFLAGS, and specifies -B./. # It also specifies -I./include to find, e.g., stddef.h. -GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) -I./include - -# Special flags for compiling enquire. -# We disable optimization to make floating point more reliable. -ENQUIRE_CFLAGS = -DNO_MEM -DNO_LONG_DOUBLE_IO -O0 -ENQUIRE_LDFLAGS = $(LDFLAGS) +GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) -I./include $(TCFLAGS) # Sed command to transform gcc to installed name. Overwritten by configure. -program_transform_name = -e s,x,x, -program_transform_cross_name = -e s,^,$(target)-, +program_transform_name = @program_transform_name@ +program_transform_cross_name = s,^,$(target_alias)-, + +build_canonical = @build_canonical@ +host_canonical = @host_canonical@ # Tools to use when building a cross-compiler. # These are used because `configure' appends `cross-make' # to the makefile when making a cross-compiler. -TARGET_TOOLPREFIX = $(tooldir)/bin/ -AR_FOR_TARGET = $(TARGET_TOOLPREFIX)ar +# Use the tools from the build tree, if they are available. + +# objdir is set by configure. +objdir = @objdir@ + +AR_FOR_TARGET = ` \ + if [ -f $(objdir)/../binutils/ar ] ; then \ + echo $(objdir)/../binutils/ar ; \ + else \ + if [ "$(host_canonical)" = "$(target)" ] ; then \ + echo ar; \ + else \ + t='$(program_transform_name)'; echo ar | sed -e $$t ; \ + fi; \ + fi` AR_FOR_TARGET_FLAGS = rc -RANLIB_FOR_TARGET = $(TARGET_TOOLPREFIX)ranlib -RANLIB_TEST_FOR_TARGET = [ -f $(TARGET_TOOLPREFIX)ranlib ] - +RANLIB_FOR_TARGET = ` \ + if [ -f $(objdir)/../binutils/ranlib ] ; then \ + echo $(objdir)/../binutils/ranlib ; \ + else \ + if [ "$(host_canonical)" = "$(target)" ] ; then \ + echo ranlib; \ + else \ + t='$(program_transform_name)'; echo ranlib | sed -e $$t ; \ + fi; \ + fi` +RANLIB_TEST_FOR_TARGET = \ + [ -f $(RANLIB_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 @@ -163,57 +231,68 @@ LIMITS_H_TEST = [ -f $(SYSTEM_HEADER_DIR)/limits.h ] PREMADE_ATTRTAB_MD = Makefile # Guaranteed not to cmp equal to md. PREMADE_ATTRTAB = -target= ... `configure' substitutes actual target name here. -xmake_file= ... `configure' substitutes actual x- file name here. -tmake_file= ... `configure' substitutes actual t- file name here. -out_file= ... `configure' substitutes actual out file name here. -out_object_file= ... `configure' substitutes actual out object file name here. -md_file= ... `configure' substitutes actual md file name here. -tm_file= ... `configure' substitutes actual tm file name here. -build_xm_file= ... `configure' substitutes actual build xm- file name here. -host_xm_file= ... `configure' substitutes actual host xm- file name here. -lang_specs_files= ... `configure' substitutes actual lang spec file names here. -lang_options_files= ... `configure' puts actual lang options file names here. -version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c` +target=@target@ +target_alias=@target_alias@ +xmake_file=@dep_host_xmake_file@ +tmake_file=@dep_tmake_file@ +out_file=$(srcdir)/config/@out_file@ +out_object_file=@out_object_file@ +md_file=$(srcdir)/config/@md_file@ +tm_file=@tm_file_list@ +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@ +GCC_THREAD_FILE=@thread_file@ +GTHREAD_FLAGS=@gthread_flags@ +# Be prepared for gcc2 merges. +gcc_version=@gcc_version@ +gcc_version_trigger=@gcc_version_trigger@ +version=$(gcc_version) mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c` -# Directory where sources are, from where we are. -srcdir = . # Common prefix for installation directories. # NOTE: This directory must exist when you start installation. -prefix = /usr/local +prefix = @prefix@ # Directory in which to put localized header files. On the systems with # gcc as the native cc, `local_prefix' may not be `prefix' which is # `/usr'. # NOTE: local_prefix *should not* default from prefix. -local_prefix = /usr/local +local_prefix = @local_prefix@ # Directory in which to put host dependent programs and libraries -exec_prefix = $(prefix) +exec_prefix = @exec_prefix@ # Directory in which to put the executable for the command `gcc' -bindir = $(exec_prefix)/bin +bindir = @bindir@ # Directory in which to put the directories used by the compiler. -libdir = $(exec_prefix)/lib +libdir = @libdir@ # Directory in which the compiler finds executables, libraries, etc. -libsubdir = $(libdir)/gcc-lib/$(target)/$(version) +libsubdir = $(libdir)/gcc-lib/$(target_alias)/$(version) # Directory in which the compiler finds g++ includes. -gxx_include_dir= $(libdir)/g++-include +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 # 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 # where the info files go -infodir = $(prefix)/info +infodir = @infodir@ +# Where cpp should go besides $prefix/bin if necessary +cpp_install_dir = @cpp_install_dir@ # Extension (if any) to put in installed man-page filename. manext = .1 objext = .o -exeext = +exeext = @host_exeext@ +build_exeext = @build_exeext@ # Directory in which to put man pages. -mandir = $(prefix)/man/man1 +mandir = @mandir@/man1 # Directory in which to find other cross-compilation tools and headers. # Used in install-cross. -tooldir = $(exec_prefix)/$(target) +tooldir = $(exec_prefix)/$(target_alias) # Dir for temp files. tmpdir = /tmp @@ -224,6 +303,10 @@ CLIB= # system library. OBSTACK=obstack.o +# Configure will set these if you need vfprintf and possibly _doprnt support. +VFPRINTF=@vfprintf@ +DOPRINT=@doprint@ + # Specify the rule for actually making libgcc.a, LIBGCC = libgcc.a # and the rule for installing it. @@ -245,7 +328,9 @@ LIBGCC2 = libgcc2.a # -g1 causes output of debug info only for file-scope entities. # we use this here because that should be enough, and also # so that -g1 will be tested. -LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) -g1 +# +LIBGCC2_DEBUG_CFLAGS = -g1 +LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED @inhibit_libc@ # Additional options to use when compiling libgcc2.a. # Some targets override this to -Iinclude @@ -258,41 +343,39 @@ TARGET_LIBGCC2_CFLAGS = # Some targets override this to stmp-int-hdrs LIBGCC2_DEPS = -# Enquire target (This is a variable so that a target can choose not to -# build it.) -ENQUIRE = enquire - # libgcc1-test target (must also be overridable for a target) LIBGCC1_TEST = libgcc1-test # List of extra executables that should be compiled for this target machine # that are used for compiling from source code to object code. # The rules for compiling them should be in the t-* file for the machine. -EXTRA_PASSES = +EXTRA_PASSES =@extra_passes@ # Like EXTRA_PASSES, but these are used when linking. -EXTRA_PROGRAMS = +EXTRA_PROGRAMS = @extra_programs@ # List of extra object files that should be compiled for this target machine. # The rules for compiling them should be in the t-* file for the machine. -EXTRA_PARTS = +EXTRA_PARTS = @extra_parts@ # List of extra object files that should be compiled and linked with # compiler proper (cc1, cc1obj, cc1plus). -EXTRA_OBJS = +EXTRA_OBJS = @extra_objs@ # List of extra object files that should be compiled and linked with # the gcc driver. -EXTRA_GCC_OBJS = +EXTRA_GCC_OBJS =@host_extra_gcc_objs@ # List of additional header files to install. # Often this is edited directly by `configure'. -EXTRA_HEADERS = +EXTRA_HEADERS =@extra_headers_list@ -# Set this to `ld' to enable use of collect2. -# USE_COLLECT2 = +# Set this to `collect2' to enable use of collect2. +USE_COLLECT2 = @will_use_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. +USE_COLLECT2 = collect2$(exeext) # List of extra C and assembler files to add to libgcc1.a. # Assembler files should have names ending in `.asm'. @@ -302,8 +385,17 @@ LIB1FUNCS_EXTRA = # Assembler files should have names ending in `.asm'. LIB2FUNCS_EXTRA = +# Handle cpp installation. +INSTALL_CPP= +UNINSTALL_CPP= + # Default float.h source to use for cross-compiler. -CROSS_FLOAT_H=float.h-cross +# 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 # Program to convert libraries. LIBCONVERT = @@ -316,7 +408,7 @@ TAROUTOPTS = xpBf # Select which version of fixincludes to use (I.E. regular versus SVR4) # This value is overridden directly by configure. -FIXINCLUDES=fixincludes +FIXINCLUDES = @fixincludes@ # Additional directories of header files to run fixincludes on. # These should be directories searched automatically by default @@ -326,9 +418,13 @@ FIXINCLUDES=fixincludes # On most systems, this is empty. OTHER_FIXINCLUDES_DIRS= +# A list of all the language-specific executables. +# This is overridden by configure. +COMPILERS = cc1$(exeext) @all_compilers@ + # List of things which should already be built whenever we try to use xgcc # to compile anything (without linking). -GCC_PASSES=xgcc cc1 cpp $(EXTRA_PASSES) +GCC_PASSES=xgcc$(exeext) cc1$(exeext) cpp$(exeext) $(EXTRA_PASSES) # List of things which should already be built whenever we try to use xgcc # to link anything. @@ -358,12 +454,18 @@ HOST_CPPFLAGS=$(ALL_CPPFLAGS) HOST_ALLOCA=$(ALLOCA) HOST_MALLOC=$(MALLOC) HOST_OBSTACK=$(OBSTACK) +HOST_VFPRINTF=$(VFPRINTF) +HOST_DOPRINT=$(DOPRINT) # Actual name to use when installing a native compiler. -GCC_INSTALL_NAME = `t='$(program_transform_name)'; echo gcc | sed $$t` +GCC_INSTALL_NAME = `t='$(program_transform_name)'; echo gcc | 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` # Actual name to use when installing a cross-compiler. -GCC_CROSS_NAME = `t='$(program_transform_cross_name)'; echo gcc | sed $$t` +GCC_CROSS_NAME = `t='$(program_transform_cross_name)'; echo gcc | sed -e $$t` +PROTOIZE_CROSS_NAME = `t='$(program_transform_cross_name)'; echo protoize | sed -e $$t` +UNPROTOIZE_CROSS_NAME = `t='$(program_transform_cross_name)'; echo unprotoize | sed -e $$t` # Choose the real default target. ALL=all.internal @@ -371,8 +473,15 @@ ALL=all.internal # Choose the real install target. INSTALL_TARGET=install-normal -# Source for float.h. Overridden by cross-make. -FLOAT_H=float.h-nat +# Setup the testing framework, if you have one +EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \ + echo $${rootme}/../expect/expect ; \ + else echo expect ; fi` + +RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \ + echo $${srcdir}/../dejagnu/runtest ; \ + else echo runtest; fi` +RUNTESTFLAGS = # Extra symbols for fixproto to define when parsing headers. FIXPROTO_DEFINES = @@ -380,6 +489,12 @@ FIXPROTO_DEFINES = # Extra flags to use when compiling crt{begin,end}.o. CRTSTUFF_T_CFLAGS = +# Extra flags to use when compiling [m]crt0.o. +CRT0STUFF_T_CFLAGS = + +# "t" or nothing, for building multilibbed versions of, say, crtbegin.o. +T = + # End of variables for you to override. # Definition of `all' is here so that new rules inserted by sed @@ -393,50 +508,61 @@ all: all.indirect # sed inserts variable overrides after the following line. ####target overrides +@target_overrides@ + ####host overrides +@host_overrides@ + ####cross overrides +@cross_defines@ +@cross_overrides@ + ####build overrides - +@build_overrides@ +# # Now figure out from those variables how to compile and link. all.indirect: $(ALL) # IN_GCC tells obstack.h that we are using gcc's file. # ??? IN_GCC should be obsolete now. -INTERNAL_CFLAGS = $(CROSS) -DIN_GCC +INTERNAL_CFLAGS = $(CROSS) -DIN_GCC @extra_c_flags@ # This is the variable actually used when we compile. -ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS) +ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS) \ + @DEFS@ $(SCHED_CFLAGS) # Likewise. ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS) # Even if ALLOCA is set, don't use it if compiling with GCC. -USE_ALLOCA= ` case "${CC}" in "${OLDCC}") echo "${ALLOCA}" ;; esac ` -USE_HOST_ALLOCA= ` case "${HOST_CC}"@"${HOST_ALLOCA}" in "${OLDCC}"@?*) echo ${HOST_PREFIX}${HOST_ALLOCA} ;; esac ` +USE_ALLOCA= ${ALLOCA} +USE_HOST_ALLOCA= ` case "${HOST_ALLOCA}" in ?*) echo ${HOST_PREFIX}${HOST_ALLOCA} ;; esac ` USE_HOST_MALLOC= ` case "${HOST_MALLOC}" in ?*) echo ${HOST_PREFIX}${HOST_MALLOC} ;; esac ` USE_HOST_OBSTACK= ` case "${HOST_OBSTACK}" in ?*) echo ${HOST_PREFIX}${HOST_OBSTACK} ;; esac ` +USE_HOST_VFPRINTF= ` case "${HOST_VFPRINTF}" in ?*) echo ${HOST_PREFIX}${HOST_VFPRINTF} ;; esac ` +USE_HOST_DOPRINT= ` case "${HOST_DOPRINT}" in ?*) echo ${HOST_PREFIX}${HOST_DOPRINT} ;; esac ` # 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) +LIBDEPS= $(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_LIBDEPS= $(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) $(CLIB) +LIBS = $(OBSTACK) $(USE_ALLOCA) $(MALLOC) $(VFPRINTF) $(DOPRINT) $(CLIB) # 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) \ - $(HOST_CLIB) + $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) $(HOST_CLIB) -HOST_RTL = $(HOST_PREFIX)rtl.o +HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o HOST_RTLANAL = $(HOST_PREFIX)rtlanal.o HOST_PRINT = $(HOST_PREFIX)print-rtl.o @@ -453,14 +579,16 @@ INCLUDES = -I. -I$(srcdir) -I$(srcdir)/config # This tells GNU make version 3 not to export all the variables # defined in this file into the environment. .NOEXPORT: - +# # Support for additional languages (other than c and objc). # ??? objc can be supported this way too (leave for later). # These next lines are overridden by configure. -LANG_MAKEFILES = -LANG_STAGESTUFF = -LANG_DIFF_EXCLUDES = +LANG_MAKEFILES = @all_lang_makefiles@ +LANG_STAGESTUFF = @all_stagestuff@ +LANG_DIFF_EXCLUDES = @all_diff_excludes@ +LANG_LIB2FUNCS = @all_lib2funcs@ +LANG_EXTRA_HEADERS = @all_headers@ # Flags to pass to recursive makes. # CC is set by configure. Hosts without symlinks need special handling @@ -468,88 +596,88 @@ LANG_DIFF_EXCLUDES = # subdirectories. # ??? The choices here will need some experimenting with. FLAGS_TO_PASS = \ - "AR_FLAGS=$(AR_FLAGS)" \ + "AR_FLAGS=$(AR_FOR_TARGET_FLAGS)" \ "AR_FOR_TARGET=$(AR_FOR_TARGET)" \ "BISON=$(BISON)" \ "BISONFLAGS=$(BISONFLAGS)" \ - "CC=set-by-configure" \ + "CC=@cc_set_by_configure@" \ "CFLAGS=$(CFLAGS)" \ + "CLIB=$(CLIB)" \ "GCC_FOR_TARGET=$(GCC_FOR_TARGET)" \ "LDFLAGS=$(LDFLAGS)" \ "LEX=$(LEX)" \ "LEXFLAGS=$(LEXFLAGS)" \ + "LN=$(LN)" \ + "LN_S=$(LN_S)" \ "MAKEINFO=$(MAKEINFO)" \ "MAKEINFOFLAGS=$(MAKEINFOFLAGS)" \ "RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET)" \ "RANLIB_TEST_FOR_TARGET=$(RANLIB_TEST_FOR_TARGET)" \ "SHELL=$(SHELL)" \ + "STAGE_PREFIX=@stage_prefix_set_by_configure@" \ "exeext=$(exeext)" \ + "build_exeext=$(build_exeext)" \ "objext=$(objext)" \ "exec_prefix=$(exec_prefix)" \ "prefix=$(prefix)" \ + "local_prefix=$(local_prefix)" \ + "gxx_include_dir=$(gxx_include_dir)" \ "tooldir=$(tooldir)" \ "bindir=$(bindir)" \ "libsubdir=$(libsubdir)" - +# # Lists of files for various purposes. -# A list of all the language-specific executables. -# This is overridden by configure. -COMPILERS = cc1$(exeext) cc1obj$(exeext) +# Language-specific object files for C and Objective C. +C_AND_OBJC_OBJS = c-lex.o c-pragma.o c-decl.o c-typeck.o c-convert.o \ + c-aux-info.o c-common.o c-iterate.o @extra_c_objs@ # Language-specific object files for C. -C_OBJS = c-parse.o c-lang.o c-lex.o c-pragma.o \ - c-decl.o c-typeck.o c-convert.o c-aux-info.o c-common.o c-iterate.o - -# Language-specific object files for Objective C. -OBJC_OBJS = objc-parse.o objc-act.o c-lex.o c-pragma.o \ - c-decl.o c-typeck.o c-convert.o c-aux-info.o c-common.o c-iterate.o +C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC_OBJS) -# Files specific to the C interpreter bytecode compiler(s). -BC_OBJS = bc-emit.o bc-optab.o - -# Bytecode header files constructed at build time; vmsconfig.com wants this. -BC_ALL = bc-arity.h bc-opcode.h bc-opname.h +SCHED_PREFIX = @sched_prefix@ +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 expr.o calls.o expmed.o explow.o optabs.o varasm.o \ - rtl.o print-rtl.o rtlanal.o emit-rtl.o real.o \ - dbxout.o sdbout.o dwarfout.o xcoffout.o \ - integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o \ - regclass.o local-alloc.o global.o reload.o reload1.o caller-save.o \ - insn-peep.o reorg.o sched.o final.o recog.o reg-stack.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 \ + 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 \ + 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-attrtab.o $(out_object_file) getpwd.o convert.o $(EXTRA_OBJS) + profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \ + dyn-string.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 # them before rtl.o is compiled. -GEN= genemit genoutput genrecog genextract genflags gencodes genconfig genpeep +GEN= genemit genoutput genrecog genextract genflags gencodes genconfig \ + genpeep gengenrtl gencheck -CCCP=cccp -# Uncomment this line if you want to use cppmain (w/cpplib) as cpp. -#CCCP=cppmain +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 \ - stamp-flags stamp-config stamp-codes \ - stamp-output stamp-recog stamp-emit stamp-extract stamp-peep \ - stamp-attr stamp-attrtab stamp-opinit stamp-proto stamp-crt stamp-crtS \ - genemit$(exeext) genoutput$(exeext) genrecog$(exeext) genextract$(exeext) \ - genflags$(exeext) gencodes$(exeext) genconfig$(exeext) genpeep$(exeext) \ - genattrtab$(exeext) genattr$(exeext) genopinit$(exeext) \ - $(BC_ALL) \ - stamp-bcarity stamp-bcopcode stamp-bcopname \ - bi-arity$(exeext) bi-opcode$(exeext) bi-opname$(exeext) \ - $(GCC_PASSES) $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \ + insn-attr.h insn-attrtab.c insn-opinit.c genrtl.c genrtl.h 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 \ + genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \ + genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \ + 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) \ + $(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 \ + *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse \ *.[si] \ $(LANG_STAGESTUFF) @@ -569,9 +697,21 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \ _fixunsdfsi _fixunssfsi _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi \ _fixxfdi _fixunsxfdi _floatdixf _fixunsxfsi \ _fixtfdi _fixunstfdi _floatditf \ - __gcc_bcmp _varargs _eprintf _op_new _op_vnew _new_handler _op_delete \ - _op_vdel _bb _shtab _clear_cache _trampoline __main _exit _ctors _eh \ - _pure + __gcc_bcmp _varargs __dummy _eprintf \ + _bb _shtab _clear_cache _trampoline __main _exit \ + _ctors _pure + +LIB2FUNCS_EH = _eh + +FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \ + _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \ + _lt_sf _le_sf _si_to_sf _sf_to_si _negate_sf _make_sf \ + _sf_to_df + +DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \ + _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \ + _lt_df _le_df _si_to_df _df_to_si _negate_df _make_df \ + _df_to_sf # The files that "belong" in CONFIG_H are deliberately omitted # because having them there would not be useful in actual practice. @@ -581,10 +721,15 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \ # If it is, rm *.o is an easy way to do it. # CONFIG_H = $(host_xm_file) $(tm_file) CONFIG_H = -RTL_H = rtl.h rtl.def machmode.h machmode.def -TREE_H = tree.h real.h tree.def machmode.h machmode.def -BYTECODE_H = bytecode.h bc-emit.h bc-optab.h - +RTL_BASE_H = rtl.h rtl.def gansidecl.h 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 +EXPR_H = expr.h insn-codes.h +REGS_H = regs.h varray.h machmode.h machmode.def gansidecl.h +# # Language makefile fragments. # The following targets define the interface between us and the languages. @@ -601,57 +746,82 @@ BYTECODE_H = bytecode.h bc-emit.h bc-optab.h # Configure computes and adds these here. ####language hooks +@language_hooks@ # sed inserts language fragments after the following line. ####language fragments +@language_fragments@ # End of language makefile fragments. - -# Avoid a lot of time thinking about remaking Makefile.in and *.def. -.SUFFIXES: .in .def - -Makefile: $(srcdir)/Makefile.in $(srcdir)/configure $(srcdir)/version.c \ - $(srcdir)/config/$(xmake_file) $(srcdir)/config/$(tmake_file) \ - $(LANG_MAKEFILES) +# +# The only suffixes we want for implicit rules are .c and .o, so clear +# the list and add them. This speeds up GNU Make, and allows -r to work. +.SUFFIXES: +.SUFFIXES: .c .o + +Makefile: $(srcdir)/Makefile.in config.status $(srcdir)/version.c \ + $(xmake_file) $(tmake_file) $(LANG_MAKEFILES) + $(SHELL) $(srcdir)/configure.frag $(srcdir) "$(SUBDIRS)" \ + "$(xmake_file)" "$(tmake_file)" cp config.status config.run $(SHELL) config.run rm -f config.run +$(srcdir)/configure: $(srcdir)/configure.in + cd $(srcdir); autoconf + +# cstamp-h.in controls rebuilding of config.in. +# It is named cstamp-h.in and not stamp-h.in so the mostlyclean rule doesn't +# delete it. A stamp file is needed as autoheader won't update the file if +# nothing has changed. +# It remains in the source directory and is part of the distribution. +# This follows what is done in shellutils, fileutils, etc. +# "echo timestamp" is used instead of touch to be consistent with other +# packages that use autoconf (??? perhaps also to avoid problems with patch?). +# ??? Newer versions have a maintainer mode that may be useful here. +$(srcdir)/config.in: $(srcdir)/cstamp-h.in +$(srcdir)/cstamp-h.in: $(srcdir)/configure.in $(srcdir)/acconfig.h + cd $(srcdir) && autoheader + @rm -f $(srcdir)/cstamp-h.in + 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 + +# 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 +# config.status does not exist before failing. +config.status: configure version.c + @if [ ! -f config.status ] ; then \ + echo You must configure gcc. Look at the INSTALL file for details.; \ + false; \ + else \ + $(SHELL) config.status --recheck; \ + fi + all.internal: start.encap rest.encap # 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 $(LIBGCC) $(STMP_FIXPROTO) \ +all.cross: native gcc-cross specs stmp-headers $(STMP_FIXPROTO) $(LIBGCC) \ $(LIBGCC1_TEST) $(EXTRA_PARTS) lang.all.cross # This is what to compile if making gcc with a cross-compiler. -all.build: native xgcc $(EXTRA_PARTS) lang.all.build +all.build: native xgcc$(exeext) $(EXTRA_PARTS) lang.all.build # This is what must be made before installing GCC and converting libraries. -start.encap: native xgcc specs $(LIBGCC1) xlimits.h lang.start.encap +start.encap: native xgcc$(exeext) specs $(LIBGCC1) xlimits.h lang.start.encap # These can't be made until after GCC can run. -rest.encap: stmp-headers $(LIBGCC) $(STMP_FIXPROTO) $(EXTRA_PARTS) lang.rest.encap +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 cpp $(LANGUAGES) $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2) +native: config.status auto-host.h cpp$(exeext) $(LANGUAGES) \ + $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2) # Define the names for selecting languages in LANGUAGES. -C c: cc1 -OBJC objc: cc1obj objc-runtime -OBJECTIVE-C objective-c: cc1obj objc-runtime +C c: cc1$(exeext) PROTO: proto # Tell GNU make these are phony targets. -.PHONY: C c OBJC objc OBJECTIVE-C objective-c PROTO proto - -# 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 -# config.status does not exist before failing. -config.status: - @if [ ! -f config.status ] ; then \ - echo You must configure gcc. Look at the INSTALL file for details.; \ - false; \ - else \ - true; \ - fi +.PHONY: C c PROTO proto # On the target machine, finish building a cross compiler. # This does the things that can't be done on the host machine. @@ -663,7 +833,7 @@ libgcc1-test: libgcc1-test.o native $(GCC_PARTS) @echo "Testing libgcc1. Ignore linker warning messages." $(GCC_FOR_TARGET) $(GCC_CFLAGS) libgcc1-test.o -o libgcc1-test \ -nostartfiles -nostdlib `$(GCC_FOR_TARGET) --print-libgcc-file-name` -libgcc1-test.o: libgcc1-test.c native xgcc +libgcc1-test.o: libgcc1-test.c native xgcc$(exeext) $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) -c $(srcdir)/libgcc1-test.c # Recompile all the language-independent object files. @@ -672,55 +842,36 @@ compilations: ${OBJS} # Create a list of the language-independent object files so the language # subdirectories needn't mention their names explicitly. -stamp-objlist: Makefile $(OBJS) $(BC_OBJS) - echo " $(OBJS) $(BC_OBJS)" | sed -e 's, \([a-z]\), ../\1,g' -e 's/\.o/$(objext)/g' >stamp-objlist +stamp-objlist: $(OBJS) + echo " $(OBJS)" | sed -e 's, \([a-z0-9]\), ../\1,g' -e 's/\.o/$(objext)/g' >stamp-objlist # 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: gcc.o version.o $(LIBDEPS) $(EXTRA_GCC_OBJS) - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o version.o $(EXTRA_GCC_OBJS) $(LIBS) +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) # Dump a specs file to make -B./ read these specs over installed ones. -specs: xgcc +specs: xgcc$(exeext) $(GCC_FOR_TARGET) -dumpspecs > tmp-specs mv tmp-specs specs # We do want to create an executable named `xgcc', so we can use it to # compile libgcc2.a. # Also create gcc-cross, so that install-common will install properly. -gcc-cross: xgcc +gcc-cross: xgcc$(exeext) cp xgcc$(exeext) gcc-cross$(exeext) -cc1: $(P) $(C_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(OBJS) $(BC_OBJS) $(LIBS) - -cc1obj: $(P) $(OBJC_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJC_OBJS) $(OBJS) $(BC_OBJS) $(LIBS) +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 -# Create float.h source for the native machine. -float.h-nat: enquire - -./enquire -f > tmp-float.h - mv tmp-float.h float.h-nat - -# Create a dummy float.h source for a cross-compiler. -float.h-cross: - echo "#error float.h values not known for cross-compiler" > t-float.h-cross - mv t-float.h-cross float.h-cross - -# Used to compile enquire with standard cc, but have forgotten why. -# Let's try with GCC. -enquire: enquire.o $(GCC_PARTS) - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@ -enquire.o: $(srcdir)/enquire.c $(GCC_PASSES) stmp-int-hdrs -# Breaking this line caused a problem with one version of GNU make. - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(ENQUIRE_CFLAGS) -I. -c $(srcdir)/enquire.c - # Build the version of limits.h that we will install. xlimits.h: glimits.h limitx.h limity.h if $(LIMITS_H_TEST) ; then \ @@ -729,7 +880,7 @@ xlimits.h: glimits.h limitx.h limity.h cat $(srcdir)/glimits.h > tmp-xlimits.h; \ fi mv tmp-xlimits.h xlimits.h - +# # Build libgcc.a. # This is done in two parts because some functions, in libgcc1.c, # must be compiled with something other than GCC, @@ -744,7 +895,7 @@ libgcc1.conv: libgcc1.a # Use this as value of LIBGCC1 to inhibit use of libgcc1.c entirely. # Make an empty file instead. libgcc1.null: $(GCC_PASSES) - echo "__foo () {}" > dummy.c + echo "void __foo () {}" > dummy.c $(GCC_FOR_TARGET) $(GCC_CFLAGS) -c dummy.c $(OLDAR) $(OLDAR_FLAGS) libgcc1.null dummy$(objext) rm -f dummy$(objext) dummy.c @@ -760,6 +911,10 @@ libgcc1.cross: # Compile the library of arithmetic subroutines with the native compiler. # Don't compile it with GCC! # (That would cause most arithmetic functions to call themselves.) +# +# NOTE: If you modify these rules substantially, please be sure to +# check at least config/i386/t-sco5 and possibly other makefile +# fragments. libgcc1.a: libgcc1.c $(CONFIG_H) $(LIB1FUNCS_EXTRA) config.status -rm -f tmplibgcc1.a # Actually build it in tmplibgcc1.a, then rename at end, @@ -774,7 +929,7 @@ libgcc1.a: libgcc1.c $(CONFIG_H) $(LIB1FUNCS_EXTRA) config.status do \ echo $${name}; \ rm -f $${name}$(objext); \ - $(OLDCC) $(CCLIBFLAGS) $(INCLUDES) -c -DL$${name} $(srcdir)/libgcc1.c; \ + $(OLDCC) -DIN_LIBGCC1 $(CCLIBFLAGS) $(INCLUDES) -c -DL$${name} $(srcdir)/libgcc1.c; \ if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ mv libgcc1$(objext) $${name}$(objext); \ $(OLDAR) $(OLDAR_FLAGS) tmplibgcc1.a $${name}$(objext); \ @@ -794,7 +949,7 @@ libgcc1.a: libgcc1.c $(CONFIG_H) $(LIB1FUNCS_EXTRA) config.status if [ $${name}.asm = $${file} ]; then \ cp $${file} $${name}.s || exit 1; file=$${name}.s; \ else true; fi; \ - $(OLDCC) $(CCLIBFLAGS) $(INCLUDES) -c $${file}; \ + $(OLDCC) -DIN_LIBGCC1 $(CCLIBFLAGS) $(INCLUDES) -c $${file}; \ if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ $(OLDAR) $(OLDAR_FLAGS) tmplibgcc1.a $${name}$(objext); \ if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ @@ -840,7 +995,7 @@ libgcc1.S: libgcc1.c $(CONFIG_H) config.status for name in $(LIB1FUNCS); \ do \ echo $${name}; \ - $(OLDCC) $(CCLIBFLAGS) $(INCLUDES) -S -DL$${name} $(srcdir)/libgcc1.c; \ + $(OLDCC) -DIN_LIBGCC1 $(CCLIBFLAGS) $(INCLUDES) -S -DL$${name} $(srcdir)/libgcc1.c; \ if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ echo '#ifdef ' L$${name} >> libgcc1.S; \ cat libgcc1.s >> libgcc1.S; \ @@ -851,15 +1006,16 @@ libgcc1.S: libgcc1.c $(CONFIG_H) config.status # Compiling libgcc2.a requires making sure that cc1, etc. have been compiled. # But recompiling cc1 should not force recompilation of libgcc2.a. # If you want to force recompilation, delete libgcc2.a. -libgcc2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs +libgcc2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs $(STMP_FIXPROTO) -if [ -f libgcc2.ready ] ; then \ true; \ else \ touch libgcc2.ready; \ fi -libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(LIB2FUNCS_EXTRA) \ - machmode.h longlong.h gbl-ctors.h config.status +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 # 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 @@ -878,17 +1034,60 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(LIB2FUNCS_EXTRA) \ $(AR) $(AR_FLAGS) tmplibgcc2.a $${name}$(objext); \ rm -f $${name}$(objext); \ done + for name in $(LIB2FUNCS_EH); \ + do \ + echo $${name}; \ + $(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); \ + rm -f $${name}$(objext); \ + done + if [ x$(FPBIT) != x ]; then \ + for name in $(FPBIT_FUNCS); \ + do \ + echo $${name}; \ + $(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); \ + rm -f $${name}$(objext); \ + done; \ + else true; fi; + if [ x$(DPBIT) != x ]; then \ + for name in $(DPBIT_FUNCS); \ + do \ + echo $${name}; \ + $(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); \ + rm -f $${name}$(objext); \ + done; \ + else true; fi; # Some shells crash when a loop has no items. # So make sure there is always at least one--`..'. # Then ignore it. # We don't use -e here because there are if statements # that should not make the command give up when the if condition is false. # Instead, we test for failure after each command where it matters. - for file in .. $(LIB2FUNCS_EXTRA); \ - do \ - if [ x$${file} != x.. ]; then \ - name=`echo $${file} | sed -e 's/[.][cS]$$//' -e 's/[.]asm$$//'`; \ - oname=` echo $${name} | sed -e 's,.*/,,'`; \ + for file in $(LIB2ADD); do \ + name=`echo $${file} | sed -e 's/[.][cSo]$$//' -e 's/[.]asm$$//' -e 's/[.]txt$$//'`; \ + oname=` echo $${name} | sed -e 's,.*/,,'`; \ + 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)" \ + 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}; \ + rm -f $${f}; \ + else true; \ + fi; done; \ + else \ echo $${name}; \ if [ $${name}.asm = $${file} ]; then \ cp $${file} $${name}.s || exit 1; file=$${name}.s; \ @@ -897,7 +1096,6 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(LIB2FUNCS_EXTRA) \ if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ $(AR) $(AR_FLAGS) tmplibgcc2.a $${oname}$(objext); \ rm -f $${name}.s $${oname}$(objext); \ - else true; \ fi; \ done mv tmplibgcc2.a libgcc2.a @@ -931,21 +1129,31 @@ libgcc.a: $(LIBGCC1) $(LIBGCC2) # Use the genmultilib shell script to generate the information the gcc # driver program needs to select the library directory based on the # switches. -multilib.h: $(srcdir)/genmultilib Makefile - $(SHELL) $(srcdir)/genmultilib "$(MULTILIB_OPTIONS)" \ - "$(MULTILIB_DIRNAMES)" "$(MULTILIB_MATCHES)" > multilib.h +multilib.h: s-mlib; @true +s-mlib: $(srcdir)/genmultilib Makefile + $(SHELL) $(srcdir)/genmultilib \ + "$(MULTILIB_OPTIONS)" \ + "$(MULTILIB_DIRNAMES)" \ + "$(MULTILIB_MATCHES)" \ + "$(MULTILIB_EXCEPTIONS)" \ + "$(MULTILIB_EXTRA_OPTS)" > tmp-mlib.h + $(srcdir)/move-if-change tmp-mlib.h multilib.h + touch s-mlib # Build multiple copies of libgcc.a, one for each target switch. stmp-multilib: $(LIBGCC1) libgcc2.c libgcc2.ready $(CONFIG_H) \ - $(LIB2FUNCS_EXTRA) machmode.h longlong.h gbl-ctors.h config.status + frame.h gansidecl.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)" \ + LANGUAGES="$(LANGUAGES)" \ HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS) $${flags}" \ + MULTILIB_CFLAGS="$${flags}" \ LIBGCC1="$(LIBGCC1)" LIBGCC2="$(LIBGCC2)" \ dir="$${dir}" stmp-multilib-sub; \ if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ @@ -954,10 +1162,16 @@ stmp-multilib: $(LIBGCC1) libgcc2.c libgcc2.ready $(CONFIG_H) \ # Subroutine of stmp-multilib so make -n works. stmp-multilib-sub: - rm -f $(dir)/libgcc.a $(LIBGCC2) + rm -f $(LIBGCC2) + if [ -d $(dir) ]; then \ + cd $(dir); \ + rm -f libgcc.a $(EXTRA_MULTILIB_PARTS); \ + else true; \ + fi $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" \ HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + LANGUAGES="$(LANGUAGES)" \ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" $(LIBGCC2) if [ x$(LIBGCC1) != xlibgcc1-asm.a ]; \ then true; \ @@ -969,6 +1183,7 @@ stmp-multilib-sub: $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" \ HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + LANGUAGES="$(LANGUAGES)" \ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" $(LIBGCC1); \ fi rm -rf tmplibgcc.a tmpcopy @@ -983,65 +1198,57 @@ stmp-multilib-sub: if $(RANLIB_TEST) ; then $(RANLIB) tmplibgcc.a; else true; fi if [ -d $(dir) ]; then true; else mkdir $(dir); fi mv tmplibgcc.a $(dir)/libgcc.a - -objc-runtime: libobjc.a - -# Build the Objective C runtime library. -libobjc.a: cc1obj stmp-int-hdrs libgcc2.ready $(USE_COLLECT2) $(EXTRA_PARTS) - if [ -d objc ]; then true; else mkdir objc; fi - thisdir1=`pwd`; \ - srcdir1=`cd $(srcdir); pwd`; \ - cd objc; \ - $(MAKE) -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)" - -rm -f libobjc.a - ln objc/libobjc.a . >/dev/null 2>&1 || cp objc/libobjc.a . - -if $(RANLIB_TEST) ; then $(RANLIB) libobjc.a; else true; fi - -# This is used by objc/Makefile if the user runs that directly. -sublibobjc.a: cc1obj stmp-int-hdrs libgcc2.ready - thisdir1=`pwd`; \ - srcdir1=`cd $(srcdir); pwd`; \ - cd objc; \ - $(MAKE) -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)" + 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)" \ + HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + LANGUAGES="$(LANGUAGES)" \ + MULTILIB_CFLAGS="$(MULTILIB_CFLAGS)" T="t" t$${f}; \ + mv t$${f} $(dir)/$${f}; \ + else true; \ + fi; done # Compile two additional files that are linked with every program # linked using GCC on systems using COFF or ELF, for the sake of C++ # constructors. -crtbegin.o: stamp-crt ; @true -crtend.o: stamp-crt; @true - -stamp-crt: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ - -DCRT_BEGIN -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/crtstuff.c - mv crtstuff$(objext) crtbegin$(objext) - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ - -DCRT_END -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/crtstuff.c - mv crtstuff$(objext) crtend$(objext) - touch stamp-crt +$(T)crtbegin.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) \ + -c $(srcdir)/crtstuff.c -DCRT_BEGIN -o $(T)crtbegin$(objext) + +$(T)crtend.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) \ + -c $(srcdir)/crtstuff.c -DCRT_END -o $(T)crtend$(objext) # On some systems we also want to install versions of these files # compiled using PIC for use in shared libraries. -crtbeginS.o crtendS.o: stamp-crtS ; @true +crtbeginS.o crtendS.o: s-crtS ; @true -stamp-crtS: stamp-crt crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ - -DCRT_BEGIN -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/crtstuff.c -fPIC +s-crtS: crtstuff.c $(GCC_PASSES) $(CONFIG_H) \ + defaults.h frame.h gbl-ctors.h + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS_S) \ + -DCRT_BEGIN -DCRTSTUFFS_O -finhibit-size-directive -fno-inline-functions \ + -fno-exceptions -g0 -c $(srcdir)/crtstuff.c mv crtstuff$(objext) crtbeginS$(objext) - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ - -DCRT_END -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/crtstuff.c -fPIC - mv crtstuff$(objext) crtendS$(objext) - touch stamp-crtS - + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS_S) \ + -DCRT_END -DCRTSTUFFS_O -finhibit-size-directive -fno-inline-functions \ + -fno-exceptions -g0 -c $(srcdir)/crtstuff.c -o crtendS$(objext) + touch s-crtS + +# Compile the start modules crt0.o and mcrt0.o that are linked with every program +crt0.o: s-crt0 ; @true +mcrt0.o: s-crt0; @true + +s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \ + -o crt0.o -c $(CRT0_S) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \ + -o mcrt0.o -c $(MCRT0_S) + touch s-crt0 +# # Compiling object files from source files. # Note that dependencies on obstack.h are not written @@ -1050,15 +1257,16 @@ stamp-crtS: stamp-crt crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h # C language specific files. c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) c-lex.h \ - $(srcdir)/c-parse.h c-tree.h input.h flags.h + $(srcdir)/c-parse.h c-tree.h input.h flags.h system.h toplev.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 $(srcdir)/c-parse.y: c-parse.in + echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \ -e "/^ifc$$/d" -e "/^end ifc$$/d" \ - $(srcdir)/c-parse.in >tmp-c-parse.y + $(srcdir)/c-parse.in >>tmp-c-parse.y $(srcdir)/move-if-change tmp-c-parse.y $(srcdir)/c-parse.y $(srcdir)/c-gperf.h: c-parse.gperf @@ -1066,38 +1274,42 @@ $(srcdir)/c-gperf.h: c-parse.gperf $(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) $(TREE_H) c-tree.h c-lex.h flags.h output.h -c-typeck.o : c-typeck.c $(CONFIG_H) $(TREE_H) c-tree.h flags.h output.h -c-lang.o : c-lang.c $(CONFIG_H) $(TREE_H) -c-lex.o : c-lex.c $(CONFIG_H) $(TREE_H) c-lex.h c-tree.h $(srcdir)/c-parse.h \ - input.h flags.h $(srcdir)/c-gperf.h c-pragma.h -c-aux-info.o : c-aux-info.c $(CONFIG_H) $(TREE_H) c-tree.h flags.h -c-convert.o : c-convert.c $(CONFIG_H) $(TREE_H) flags.h -c-pragma.o: c-pragma.c $(CONFIG_H) $(TREE_H) c-pragma.h -c-iterate.o: c-iterate.c $(CONFIG_H) $(TREE_H) $(RTL_H) c-tree.h flags.h - -# To make a configuration always use collect2, set USE_COLLECT2 to ld. -ld: collect2 - rm -f ld$(exeext) - ln collect2$(exeext) ld$(exeext) > /dev/null 2>&1 \ - || cp collect2$(exeext) ld$(exeext) - -collect2 : collect2.o cplus-dem.o underscore.o version.o $(LIBDEPS) +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 +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 +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) + +collect2$(exeext): collect2.o tlink.o hash.o cplus-dem.o underscore.o \ + version.o choose-temp.o mkstemp.o $(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 \ - cplus-dem.o underscore.o version.o $(LIBS) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ collect2.o tlink.o hash.o \ + cplus-dem.o underscore.o version.o choose-temp.o mkstemp.o $(LIBS) -collect2.o : collect2.c $(CONFIG_H) gstab.h obstack.h demangle.h +collect2.o : collect2.c $(CONFIG_H) system.h gansidecl.h gstab.h obstack.h \ + $(DEMANGLE_H) $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ - -DTARGET_MACHINE=\"$(target)\" $(MAYBE_USE_COLLECT2) \ + -DTARGET_MACHINE=\"$(target_alias)\" $(MAYBE_USE_COLLECT2) \ -c `echo $(srcdir)/collect2.c | sed 's,^\./,,'` -cplus-dem.o: cplus-dem.c demangle.h +tlink.o: tlink.c $(DEMANGLE_H) hash.h $(CONFIG_H) system.h toplev.h +hash.o: hash.c hash.h system.h toplev.h +cplus-dem.o: cplus-dem.c $(DEMANGLE_H) -underscore.c: stamp-under ; @true +underscore.c: s-under ; @true -stamp-under: $(GCC_PASSES) +s-under: $(GCC_PASSES) echo "int xxy_us_dummy;" >tmp-dum.c $(GCC_FOR_TARGET) -S tmp-dum.c echo '/*WARNING: This file is automatically generated!*/' >tmp-under.c @@ -1108,164 +1320,202 @@ stamp-under: $(GCC_PASSES) fi $(srcdir)/move-if-change tmp-under.c underscore.c -rm -f tmp-dum.c tmp-dum.s - touch stamp-under - -# Objective C language specific files. - -objc-parse.o : $(srcdir)/objc-parse.c $(CONFIG_H) $(TREE_H) c-lex.h \ - c-tree.h input.h flags.h objc-act.h - $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c $(srcdir)/objc-parse.c -$(srcdir)/objc-parse.c : $(srcdir)/objc-parse.y - cd $(srcdir); $(BISON) $(BISONFLAGS) objc-parse.y -o objc-parse.c -$(srcdir)/objc-parse.y: $(srcdir)/c-parse.in - sed -e "/^ifc$$/,/^end ifc$$/d" \ - -e "/^ifobjc$$/d" -e "/^end ifobjc$$/d" \ - $(srcdir)/c-parse.in >tmp-objc-prs.y - $(srcdir)/move-if-change tmp-objc-prs.y $(srcdir)/objc-parse.y - -objc-act.o : objc-act.c $(CONFIG_H) $(TREE_H) $(RTL_H) c-tree.h c-lex.h \ - flags.h objc-act.h input.h function.h $(srcdir)/c-parse.h + touch s-under # A file used by all variants of C. -c-common.o : c-common.c $(CONFIG_H) $(TREE_H) c-tree.h c-lex.h flags.h +c-common.o : c-common.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-lex.h \ + flags.h toplev.h output.h # Language-independent files. -gcc.o: gcc.c $(CONFIG_H) multilib.h config.status $(lang_specs_files) - $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ +DRIVER_DEFINES = \ -DSTANDARD_STARTFILE_PREFIX=\"$(libdir)/\" \ -DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc-lib/\" \ -DDEFAULT_TARGET_VERSION=\"$(version)\" \ - -DDEFAULT_TARGET_MACHINE=\"$(target)\" \ - -DTOOLDIR_BASE_PREFIX=\"$(exec_prefix)/\" \ - $(MAYBE_TARGET_DEFAULT) \ + -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) + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(DRIVER_DEFINES) \ -c `echo $(srcdir)/gcc.c | sed 's,^\./,,'` +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) + $(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 + dumpvers: dumpvers.c version.o: version.c -obstack.o: obstack.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 + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + -DPREFIX=\"$(prefix)\" \ + -c `echo $(srcdir)/prefix.c | sed 's,^\./,,'` -convert.o: convert.c $(CONFIG_H) $(TREE_H) flags.h convert.h +convert.o: convert.c $(CONFIG_H) $(TREE_H) flags.h convert.h toplev.h -tree.o : tree.c $(CONFIG_H) $(TREE_H) flags.h function.h -print-tree.o : print-tree.c $(CONFIG_H) $(TREE_H) -stor-layout.o : stor-layout.c $(CONFIG_H) $(TREE_H) flags.h function.h -fold-const.o : fold-const.c $(CONFIG_H) $(TREE_H) flags.h -toplev.o : toplev.c $(CONFIG_H) $(TREE_H) $(RTL_H) bytecode.h bc-emit.h \ +tree.o : tree.c $(CONFIG_H) system.h $(TREE_H) flags.h function.h toplev.h except.h +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 +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 \ $(lang_options_files) - $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ - $(MAYBE_TARGET_DEFAULT) $(MAYBE_USE_COLLECT2) \ + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \ + -DTARGET_NAME=\"$(target_alias)\" \ -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'` -rtl.o : rtl.c $(CONFIG_H) $(RTL_H) - -print-rtl.o : print-rtl.c $(CONFIG_H) $(RTL_H) -rtlanal.o : rtlanal.c $(CONFIG_H) $(RTL_H) - -varasm.o : varasm.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h function.h \ - defaults.h insn-codes.h expr.h hard-reg-set.h regs.h xcoffout.h \ - output.h bytecode.h c-pragma.h -function.o : function.c $(CONFIG_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 bytecode.h -stmt.o : stmt.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h function.h \ - insn-flags.h insn-config.h insn-codes.h hard-reg-set.h expr.h loop.h \ - recog.h bytecode.h bc-typecd.h bc-typecd.def bc-opcode.h bc-optab.h \ - bc-emit.h -expr.o : expr.c $(CONFIG_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 bytecode.h bc-opcode.h bc-typecd.h bc-typecd.def bc-optab.h \ - bc-emit.h modemap.def -calls.o : calls.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h expr.h insn-codes.h \ - insn-flags.h -expmed.o : expmed.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \ - insn-flags.h insn-config.h insn-codes.h expr.h recog.h real.h -explow.o : explow.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h hard-reg-set.h \ - insn-config.h expr.h recog.h insn-flags.h insn-codes.h -optabs.o : optabs.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \ - insn-flags.h insn-config.h insn-codes.h expr.h recog.h reload.h -dbxout.o : dbxout.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h regs.h \ - insn-config.h reload.h gstab.h xcoffout.h defaults.h output.h -sdbout.o : sdbout.c $(CONFIG_H) $(TREE_H) $(RTL_H) gsyms.h flags.h \ - insn-config.h reload.h -dwarfout.o : dwarfout.c $(CONFIG_H) $(TREE_H) $(RTL_H) dwarf.h flags.h \ - insn-config.h reload.h output.h defaults.h -xcoffout.o : xcoffout.c $(CONFIG_H) $(TREE_H) $(RTL_H) xcoffout.h flags.h -emit-rtl.o : emit-rtl.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \ - function.h regs.h insn-config.h insn-codes.h real.h expr.h bytecode.h \ - bc-opcode.h bc-typecd.h bc-typecd.def bc-optab.h bc-emit.h bc-opname.h -real.o : real.c $(CONFIG_H) $(TREE_H) -getpwd.o : getpwd.c $(CONFIG_H) - -integrate.o : integrate.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h integrate.h \ - insn-flags.h insn-config.h insn-codes.h expr.h real.h function.h \ - bytecode.h - -jump.o : jump.c $(CONFIG_H) $(RTL_H) flags.h hard-reg-set.h regs.h \ - insn-config.h insn-flags.h insn-codes.h expr.h real.h -stupid.o : stupid.c $(CONFIG_H) $(RTL_H) regs.h hard-reg-set.h flags.h - -cse.o : cse.c $(CONFIG_H) $(RTL_H) regs.h hard-reg-set.h flags.h real.h \ - insn-config.h recog.h -loop.o : loop.c $(CONFIG_H) $(RTL_H) flags.h loop.h insn-config.h \ - insn-flags.h insn-codes.h regs.h hard-reg-set.h recog.h expr.h real.h -unroll.o : unroll.c $(CONFIG_H) $(RTL_H) insn-config.h insn-codes.h \ - integrate.h regs.h flags.h expr.h loop.h -flow.o : flow.c $(CONFIG_H) $(RTL_H) flags.h insn-config.h \ - basic-block.h regs.h hard-reg-set.h output.h -combine.o : combine.c $(CONFIG_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 -regclass.o : regclass.c $(CONFIG_H) $(RTL_H) hard-reg-set.h flags.h \ - basic-block.h regs.h insn-config.h recog.h reload.h real.h bytecode.h -local-alloc.o : local-alloc.c $(CONFIG_H) $(RTL_H) flags.h basic-block.h \ - regs.h hard-reg-set.h insn-config.h recog.h output.h -global.o : global.c $(CONFIG_H) $(RTL_H) flags.h \ - basic-block.h regs.h hard-reg-set.h insn-config.h output.h - -reload.o : reload.c $(CONFIG_H) $(RTL_H) flags.h output.h \ - reload.h recog.h hard-reg-set.h insn-config.h insn-codes.h regs.h real.h -reload1.o : reload1.c $(CONFIG_H) $(RTL_H) real.h flags.h expr.h \ - reload.h regs.h hard-reg-set.h insn-config.h insn-flags.h insn-codes.h \ - basic-block.h recog.h output.h -caller-save.o : caller-save.c $(CONFIG_H) $(RTL_H) flags.h \ - regs.h hard-reg-set.h insn-codes.h insn-config.h basic-block.h recog.h \ - reload.h expr.h -reorg.o : reorg.c $(CONFIG_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 -sched.o : sched.c $(CONFIG_H) $(RTL_H) basic-block.h regs.h hard-reg-set.h \ - flags.h insn-config.h insn-attr.h -final.o : final.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h regs.h \ - recog.h conditions.h insn-config.h insn-attr.h real.h output.h \ - hard-reg-set.h insn-flags.h insn-codes.h gstab.h xcoffout.h defaults.h -recog.o : recog.c $(CONFIG_H) $(RTL_H) \ - regs.h recog.h hard-reg-set.h flags.h insn-config.h insn-attr.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 +rtlanal.o : rtlanal.c $(CONFIG_H) system.h $(RTL_H) + +varasm.o : varasm.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h \ + function.h defaults.h $(EXPR_H) hard-reg-set.h $(REGS_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 +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 +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 +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 +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 +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 +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 +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 +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 \ + flags.h insn-config.h reload.h output.h defaults.h \ + hard-reg-set.h $(REGS_H) $(EXPR_H) toplev.h dwarf2out.h dyn-string.h +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 +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 + +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 + +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 +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 +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 +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 +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 +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 +regclass.o : regclass.c $(CONFIG_H) system.h $(RTL_H) hard-reg-set.h flags.h \ + $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h real.h toplev.h \ + output.h +local-alloc.o : local-alloc.c $(CONFIG_H) system.h $(RTL_H) flags.h \ + $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) output.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 \ + $(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 + +reload.o : reload.c $(CONFIG_H) system.h $(RTL_H) flags.h output.h $(EXPR_H) \ + reload.h $(RECOG_H) hard-reg-set.h insn-config.h insn-codes.h $(REGS_H) \ + real.h toplev.h +reload1.o : reload1.c $(CONFIG_H) system.h $(RTL_H) real.h flags.h $(EXPR_H) \ + reload.h $(REGS_H) hard-reg-set.h insn-config.h insn-flags.h insn-codes.h \ + $(BASIC_BLOCK_H) $(RECOG_H) output.h toplev.h +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) +alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \ + $(REGS_H) toplev.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 +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) $(RTL_H) $(TREE_H) \ - regs.h hard-reg-set.h flags.h insn-config.h +reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_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 $(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) \ - $(RTL_H) regs.h hard-reg-set.h real.h insn-config.h conditions.h \ - insn-flags.h output.h insn-attr.h insn-codes.h + $(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \ + insn-flags.h output.h insn-attr.h insn-codes.h system.h toplev.h $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(out_file) # Build auxiliary files that support ecoff format. mips-tfile: mips-tfile.o version.o $(LIBDEPS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tfile.o version.o $(LIBS) -mips-tfile.o : mips-tfile.c $(CONFIG_H) $(RTL_H) +mips-tfile.o : mips-tfile.c $(CONFIG_H) $(RTL_H) system.h machmode.h mips-tdump: mips-tdump.o version.o $(LIBDEPS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tdump.o version.o $(LIBS) -mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) +mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) system.h # Build file to support OSF/rose half-pic format. -halfpic.o: halfpic.c $(CONFIG_H) $(RTL_H) $(TREE_H) +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 @@ -1274,7 +1524,7 @@ alloca.o: alloca.c $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(ALLOCA_FLAGS) \ -c `echo $(srcdir)/alloca.c | sed 's,^\./,,'` $(ALLOCA_FINISH) - +# # Generate header and source files from the machine description, # and compile them. @@ -1289,7 +1539,7 @@ alloca.o: alloca.c # Each of the other insn-* files is handled by a similar pair of rules. # This causes an anomaly in the results of make -n -# because insn-* is older than stamp-* +# because insn-* is older than s-* # and thus make -n thinks that insn-* will be updated # and force recompilation of things that depend on it. # We use move-if-change precisely to avoid such recompilation. @@ -1301,84 +1551,84 @@ alloca.o: alloca.c # versions of make which don't like empty commands (nothing after the # trailing `;'), we call true for each. -insn-config.h: stamp-config ; @true -stamp-config : $(md_file) genconfig $(srcdir)/move-if-change +insn-config.h: s-config ; @true +s-config : $(md_file) genconfig $(srcdir)/move-if-change ./genconfig $(md_file) > tmp-config.h $(srcdir)/move-if-change tmp-config.h insn-config.h - touch stamp-config + touch s-config -insn-flags.h: stamp-flags ; @true -stamp-flags : $(md_file) genflags $(srcdir)/move-if-change +insn-flags.h: s-flags ; @true +s-flags : $(md_file) genflags $(srcdir)/move-if-change ./genflags $(md_file) > tmp-flags.h $(srcdir)/move-if-change tmp-flags.h insn-flags.h - touch stamp-flags + touch s-flags -insn-codes.h: stamp-codes ; @true -stamp-codes : $(md_file) gencodes $(srcdir)/move-if-change +insn-codes.h: s-codes ; @true +s-codes : $(md_file) gencodes $(srcdir)/move-if-change ./gencodes $(md_file) > tmp-codes.h $(srcdir)/move-if-change tmp-codes.h insn-codes.h - touch stamp-codes + 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 +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 $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-emit.c -insn-emit.c: stamp-emit ; @true -stamp-emit : $(md_file) genemit $(srcdir)/move-if-change +insn-emit.c: s-emit ; @true +s-emit : $(md_file) genemit $(srcdir)/move-if-change ./genemit $(md_file) > tmp-emit.c $(srcdir)/move-if-change tmp-emit.c insn-emit.c - touch stamp-emit + touch s-emit -insn-recog.o : insn-recog.c $(CONFIG_H) $(RTL_H) insn-config.h recog.h \ - real.h output.h flags.h +insn-recog.o : insn-recog.c $(CONFIG_H) $(RTL_H) insn-config.h $(RECOG_H) \ + real.h output.h flags.h system.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-recog.c -insn-recog.c: stamp-recog ; @true -stamp-recog : $(md_file) genrecog $(srcdir)/move-if-change +insn-recog.c: s-recog ; @true +s-recog : $(md_file) genrecog $(srcdir)/move-if-change ./genrecog $(md_file) > tmp-recog.c $(srcdir)/move-if-change tmp-recog.c insn-recog.c - touch stamp-recog + touch s-recog insn-opinit.o : insn-opinit.c $(CONFIG_H) $(RTL_H) insn-codes.h insn-flags.h \ - insn-config.h flags.h rtl.h recog.h expr.h reload.h + insn-config.h flags.h $(RECOG_H) $(EXPR_H) reload.h system.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-opinit.c -insn-opinit.c: stamp-opinit ; @true -stamp-opinit : $(md_file) genopinit $(srcdir)/move-if-change +insn-opinit.c: s-opinit ; @true +s-opinit : $(md_file) genopinit $(srcdir)/move-if-change ./genopinit $(md_file) > tmp-opinit.c $(srcdir)/move-if-change tmp-opinit.c insn-opinit.c - touch stamp-opinit + touch s-opinit -insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) +insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) system.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-extract.c -insn-extract.c: stamp-extract ; @true -stamp-extract : $(md_file) genextract $(srcdir)/move-if-change +insn-extract.c: s-extract ; @true +s-extract : $(md_file) genextract $(srcdir)/move-if-change ./genextract $(md_file) > tmp-extract.c $(srcdir)/move-if-change tmp-extract.c insn-extract.c - touch stamp-extract + touch s-extract -insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) regs.h output.h real.h +insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) $(REGS_H) output.h real.h system.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-peep.c -insn-peep.c: stamp-peep ; @true -stamp-peep : $(md_file) genpeep $(srcdir)/move-if-change +insn-peep.c: s-peep ; @true +s-peep : $(md_file) genpeep $(srcdir)/move-if-change ./genpeep $(md_file) > tmp-peep.c $(srcdir)/move-if-change tmp-peep.c insn-peep.c - touch stamp-peep + 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 +insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h output.h \ + insn-attr.h insn-config.h system.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-attrtab.c -insn-attr.h: stamp-attr ; @true -stamp-attr : $(md_file) genattr $(srcdir)/move-if-change +insn-attr.h: s-attr ; @true +s-attr : $(md_file) genattr $(srcdir)/move-if-change ./genattr $(md_file) > tmp-attr.h $(srcdir)/move-if-change tmp-attr.h insn-attr.h - touch stamp-attr + touch s-attr -insn-attrtab.c: stamp-attrtab ; @true -stamp-attrtab : $(md_file) genattrtab $(srcdir)/move-if-change +insn-attrtab.c: s-attrtab ; @true +s-attrtab : $(md_file) genattrtab $(srcdir)/move-if-change if cmp -s $(PREMADE_ATTRTAB_MD) $(md_file); \ then \ echo Using $(PREMADE_ATTRTAB); \ @@ -1387,19 +1637,30 @@ stamp-attrtab : $(md_file) genattrtab $(srcdir)/move-if-change ./genattrtab $(md_file) > tmp-attrtab.c; \ fi $(srcdir)/move-if-change tmp-attrtab.c insn-attrtab.c - touch stamp-attrtab + touch s-attrtab -insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) regs.h real.h conditions.h \ - hard-reg-set.h insn-config.h insn-flags.h insn-attr.h output.h recog.h \ - insn-codes.h +insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h conditions.h \ + hard-reg-set.h insn-config.h insn-flags.h insn-attr.h output.h $(RECOG_H) \ + insn-codes.h system.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-output.c -insn-output.c: stamp-output ; @true -stamp-output : $(md_file) genoutput $(srcdir)/move-if-change +insn-output.c: s-output ; @true +s-output : $(md_file) genoutput $(srcdir)/move-if-change ./genoutput $(md_file) > tmp-output.c $(srcdir)/move-if-change tmp-output.c insn-output.c - touch stamp-output - + touch s-output + +genrtl.o : genrtl.c $(CONFIG_H) $(RTL_H) system.h +genrtl.c genrtl.h : s-genrtl + @true # force gnu make to recheck modification times. + +s-genrtl: gengenrtl $(srcdir)/move-if-change $(RTL_BASE_H) + ./gengenrtl tmp-genrtl.h tmp-genrtl.c + $(srcdir)/move-if-change tmp-genrtl.h genrtl.h + $(srcdir)/move-if-change tmp-genrtl.c genrtl.c + touch s-genrtl + +# # Compile the programs that generate insn-* from the machine description. # They are compiled with $(HOST_CC), and associated libraries, # since they need to run on this machine @@ -1416,88 +1677,96 @@ $(MD_FILE): $(MD_DEPS) $(MD_CPP) $(MD_CPPFLAGS) $(md_file) | sed 's/^# /; /g' > tmp-$@ mv tmp-$@ $@ -genconfig : genconfig.o $(HOST_RTL) $(HOST_LIBDEPS) +genconfig : genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genconfig.o $(HOST_RTL) $(HOST_LIBS) + genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genconfig.o : genconfig.c $(RTL_H) $(build_xm_file) +genconfig.o : genconfig.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c -genflags : genflags.o $(HOST_RTL) $(HOST_LIBDEPS) +genflags : genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genflags.o $(HOST_RTL) $(HOST_LIBS) + genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genflags.o : genflags.c $(RTL_H) $(build_xm_file) +genflags.o : genflags.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c -gencodes : gencodes.o $(HOST_RTL) $(HOST_LIBDEPS) +gencodes : gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - gencodes.o $(HOST_RTL) $(HOST_LIBS) + gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -gencodes.o : gencodes.c $(RTL_H) $(build_xm_file) +gencodes.o : gencodes.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c -genemit : genemit.o $(HOST_RTL) $(HOST_LIBDEPS) +genemit : genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genemit.o $(HOST_RTL) $(HOST_LIBS) + genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genemit.o : genemit.c $(RTL_H) $(build_xm_file) +genemit.o : genemit.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c -genopinit : genopinit.o $(HOST_RTL) $(HOST_LIBDEPS) +genopinit : genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genopinit.o $(HOST_RTL) $(HOST_LIBS) + genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genopinit.o : genopinit.c $(RTL_H) $(build_xm_file) +genopinit.o : genopinit.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genopinit.c -genrecog : genrecog.o $(HOST_RTL) $(HOST_LIBDEPS) +genrecog : genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genrecog.o $(HOST_RTL) $(HOST_LIBS) + genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genrecog.o : genrecog.c $(RTL_H) $(build_xm_file) +genrecog.o : genrecog.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c -genextract : genextract.o $(HOST_RTL) $(HOST_LIBDEPS) +genextract : genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genextract.o $(HOST_RTL) $(HOST_LIBS) + genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genextract.o : genextract.c $(RTL_H) $(build_xm_file) insn-config.h +genextract.o : genextract.c $(RTL_H) $(build_xm_file) system.h insn-config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c -genpeep : genpeep.o $(HOST_RTL) $(HOST_LIBDEPS) +genpeep : genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genpeep.o $(HOST_RTL) $(HOST_LIBS) + genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genpeep.o : genpeep.c $(RTL_H) $(build_xm_file) +genpeep.o : genpeep.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c -genattr : genattr.o $(HOST_RTL) $(HOST_LIBDEPS) +genattr : genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genattr.o $(HOST_RTL) $(HOST_LIBS) + genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genattr.o : genattr.c $(RTL_H) $(build_xm_file) +genattr.o : genattr.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c genattrtab : genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_RTLANAL) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_RTLANAL) $(HOST_LIBS) -genattrtab.o : genattrtab.c $(RTL_H) $(build_xm_file) insn-config.h +genattrtab.o : genattrtab.c $(RTL_H) $(build_xm_file) system.h insn-config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c -genoutput : genoutput.o $(HOST_RTL) $(HOST_LIBDEPS) +genoutput : genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genoutput.o $(HOST_RTL) $(HOST_LIBS) + genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_LIBS) -genoutput.o : genoutput.c $(RTL_H) $(build_xm_file) +genoutput.o : genoutput.c $(RTL_H) $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genoutput.c - + +gengenrtl : gengenrtl.o $(HOST_LIBDEPS) + $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ + gengenrtl.o $(HOST_LIBS) + +gengenrtl.o : gengenrtl.c $(RTL_BASE_H) system.h + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gengenrtl.c + +# # Compile the libraries to be used by gen*. # If we are not cross-building, gen* use the same .o's that cc1 will use, # and HOST_PREFIX_1 is `foobar', just to ensure these rules don't conflict # with the rules for rtl.o, alloca.o, etc. -$(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(CONFIG_H) $(RTL_H) +$(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h rm -f $(HOST_PREFIX)rtl.c 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 @@ -1507,6 +1776,12 @@ $(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(CONFIG_H) $(RTL_H) 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 +$(HOST_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(CONFIG_H) system.h $(RTL_H) \ + flags.h $(BASIC_BLOCK_H) $(REGS_H) + rm -f $(HOST_PREFIX)bitmap.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/bitmap.c > $(HOST_PREFIX)bitmap.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)bitmap.c + $(HOST_PREFIX_1)rtlanal.o: $(srcdir)/rtlanal.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)rtlanal.c sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtlanal.c > $(HOST_PREFIX)rtlanal.c @@ -1522,6 +1797,16 @@ $(HOST_PREFIX_1)obstack.o: obstack.c sed -e 's/config[.]h/hconfig.h/' $(srcdir)/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 + rm -f $(HOST_PREFIX)vfprintf.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/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 + rm -f $(HOST_PREFIX)doprint.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/doprint.c > $(HOST_PREFIX)doprint.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)doprint.c + $(HOST_PREFIX_1)malloc.o: malloc.c rm -f $(HOST_PREFIX)malloc.c sed -e 's/config[.]h/hconfig.h/' $(srcdir)/malloc.c > $(HOST_PREFIX)malloc.c @@ -1531,158 +1816,94 @@ $(HOST_PREFIX_1)malloc.o: malloc.c # that does not need to compile alloca, malloc or whatever. $(HOST_PREFIX_1): touch $(HOST_PREFIX_1) - -# Remake bytecode files. -BI_OBJ=bi-parser.o bi-lexer.o bi-reverse.o - -bc-emit.o : bc-emit.c $(CONFIG_H) $(RTL_H) real.h $(BYTECODE_H) \ - bc-arity.h bc-opcode.h bc-typecd.h bc-typecd.def bi-run.h bytetypes.h -bc-optab.o : bc-optab.c $(CONFIG_H) $(REAL_H) $(BYTECODE_H) \ - bc-opcode.h bc-typecd.h bc-typecd.def -bi-arity: bi-arity.o $(BI_OBJ) $(HOST_LIBDEPS) - $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - bi-arity.o $(BI_OBJ) $(HOST_LIBS) -bi-opcode: bi-opcode.o $(BI_OBJ) $(HOST_LIBDEPS) - $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - bi-opcode.o $(BI_OBJ) $(HOST_LIBS) -bi-opname: bi-opname.o $(BI_OBJ) $(HOST_LIBDEPS) - $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - bi-opname.o $(BI_OBJ) $(HOST_LIBS) - -$(srcdir)/bi-parser.h: $(srcdir)/bi-parser.c -$(srcdir)/bi-parser.c: $(srcdir)/bi-parser.y - cd $(srcdir); $(BISON) $(BISONFLAGS) -d bi-parser.y -o bi-parser.c - -bi-parser.o: $(srcdir)/bi-parser.c bi-defs.h $(build_xm_file) - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ - $(srcdir)/bi-parser.c -bi-lexer.o: bi-lexer.c $(srcdir)/bi-parser.h $(build_xm_file) - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ - $(srcdir)/bi-lexer.c -bi-arity.o: bi-arity.c bi-defs.h $(build_xm_file) - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ - $(srcdir)/bi-arity.c -bi-opcode.o: bi-opcode.c bi-defs.h $(build_xm_file) - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ - $(srcdir)/bi-opcode.c -bi-opname.o: bi-opname.c bi-defs.h $(build_xm_file) - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ - $(srcdir)/bi-opname.c -bi-reverse.o: bi-reverse.c bi-defs.h - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ - $(srcdir)/bi-reverse.c - -bc-arity.h: stamp-bcarity ; @true -stamp-bcarity : $(srcdir)/bytecode.def bi-arity $(srcdir)/move-if-change - ./bi-arity < $(srcdir)/bytecode.def >tmp-bc-arity.h - $(srcdir)/move-if-change tmp-bc-arity.h bc-arity.h - touch stamp-bcarity - -bc-opcode.h: stamp-bcopcode ; @true -stamp-bcopcode : $(srcdir)/bytecode.def bi-opcode $(srcdir)/move-if-change - ./bi-opcode < $(srcdir)/bytecode.def >tmp-bcopcd.h - $(srcdir)/move-if-change tmp-bcopcd.h bc-opcode.h - touch stamp-bcopcode - -bc-opname.h: stamp-bcopname ; @true -stamp-bcopname : $(srcdir)/bytecode.def bi-opname $(srcdir)/move-if-change - ./bi-opname < $(srcdir)/bytecode.def >tmp-bcopnm.h - $(srcdir)/move-if-change tmp-bcopnm.h bc-opname.h - touch stamp-bcopname - -bytecode.mostlyclean: - -rm -f bc-arity.h bc-opcode.h bc-opname.h - -bytecode.distclean bytecode.clean: bytecode.mostlyclean - -rm -f bi-arity bi-opcode bi-opname bi-lexer - -bytecode.maintainer-clean: bytecode.clean - -rm -f bi-parser.c bi-parser.h - - +# # Remake cpp and protoize. # Making the preprocessor -cpp: $(CCCP) +cpp$(exeext): $(CCCP)$(exeext) -rm -f cpp$(exeext) - ln $(CCCP)$(exeext) cpp$(exeext) > /dev/null 2>&1 \ - || cp $(CCCP)$(exeext) cpp$(exeext) -cccp: cccp.o cexp.o version.o $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ cccp.o cexp.o \ + $(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) +cexp.o: $(srcdir)/cexp.c $(CONFIG_H) system.h gansidecl.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 -# The reason we use $(libdir)/g++-include rather than using libsubdir -# is for compatibility with the current version of libg++. +cccp.o: cccp.c $(CONFIG_H) pcp.h version.c config.status system.h gansidecl.h $(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)\" \ -DLOCAL_INCLUDE_DIR=\"$(includedir)\" \ - -DCROSS_INCLUDE_DIR=\"$(libsubdir)/sys-include\" \ + -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \ -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \ -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'` -cppmain: cppmain.o cpplib.o cpphash.o cppalloc.o cpperror.o cppexp.o \ - version.o $(LIBDEPS) +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 version.o $(LIBS) + cppalloc.o cpperror.o cppexp.o prefix.o version.o $(LIBS) -cpplib.o: cpplib.c $(CONFIG_H) cpplib.h cpphash.h config.status +cppmain.o: cppmain.c $(CONFIG_H) cpplib.h system.h gansidecl.h + +cpplib.o: cpplib.c $(CONFIG_H) cpplib.h cpphash.h config.status system.h \ + gansidecl.h $(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)\" \ -DLOCAL_INCLUDE_DIR=\"$(includedir)\" \ - -DCROSS_INCLUDE_DIR=\"$(libsubdir)/sys-include\" \ + -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 +cpperror.o: cpperror.c $(CONFIG_H) cpplib.h system.h gansidecl.h -cppexp.o: cppexp.c $(CONFIG_H) cpplib.h +cppexp.o: cppexp.c $(CONFIG_H) cpplib.h system.h gansidecl.h -cpphash.o: cpphash.c cpplib.h cpphash.h +cpphash.o: cpphash.c cpplib.h cpphash.h $(CONFIG_H) system.h gansidecl.h -cppalloc.o: cppalloc.c $(CONFIG_H) +cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h system.h gansidecl.h # Note for the stamp targets, we run the program `true' instead of # having an empty command (nothing following the semicolon). -proto: config.status protoize unprotoize SYSCALLS.c.X +proto: config.status protoize$(exeext) unprotoize$(exeext) SYSCALLS.c.X -protoize: protoize.o getopt.o getopt1.o getpwd.o version.o $(LIBDEPS) +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 $(LIBS) -protoize.o: stamp-proto ; @true + protoize.o getopt.o getopt1.o getpwd.o version.o \ + pexecute.o choose-temp.o mkstemp.o $(LIBS) -unprotoize: unprotoize.o getopt.o getopt1.o getpwd.o version.o $(LIBDEPS) +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 $(LIBS) -unprotoize.o: stamp-proto ; @true + unprotoize.o getopt.o getopt1.o getpwd.o version.o \ + pexecute.o choose-temp.o mkstemp.o $(LIBS) -stamp-proto: protoize.c getopt.h $(CONFIG_H) +protoize.o: protoize.c getopt.h $(CONFIG_H) system.h $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \ -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \ - -DCROSS_INCLUDE_DIR=\"$(libsubdir)/sys-include\" \ + -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \ -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \ -DLOCAL_INCLUDE_DIR=\"$(includedir)\" \ -DSTD_PROTO_DIR=\"$(libsubdir)\" \ - -DUNPROTOIZE $(srcdir)/protoize.c - mv protoize$(objext) unprotoize$(objext) + $(srcdir)/protoize.c + +unprotoize.o: unprotoize.c protoize.c getopt.h $(CONFIG_H) system.h $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \ -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \ - -DCROSS_INCLUDE_DIR=\"$(libsubdir)/sys-include\" \ + -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \ -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \ -DLOCAL_INCLUDE_DIR=\"$(includedir)\" \ -DSTD_PROTO_DIR=\"$(libsubdir)\" \ - $(srcdir)/protoize.c - touch stamp-proto + $(srcdir)/unprotoize.c getopt.o: getopt.c getopt.h $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/getopt.c @@ -1723,43 +1944,59 @@ test-protoize-simple: ./protoize ./unprotoize $(GCC_PASSES) @echo Expect zero differences. 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 + +# 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 $@ +# # Build the include directory. The stamp files are stmp-* rather than -# stamp-* so that mostlyclean does not force the include directory to +# s-* so that mostlyclean does not force the include directory to # be rebuilt. -# Build the include directory except for float.h (which depends upon +# Build the include directory including float.h (which no longer depends upon # enquire). -stmp-int-hdrs: stmp-fixinc $(USER_H) xlimits.h objc-headers +stmp-int-hdrs: stmp-fixinc $(USER_H) xlimits.h gfloat.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. # Using basename would be simpler, but some systems don't have it. - objdir=`pwd`; \ - cd $(srcdir); \ +# The touch command is here to workaround an AIX/Linux NFS bug. for file in .. $(USER_H); do \ if [ X$$file != X.. ]; then \ realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \ - rm -f $$objdir/include/$$realfile; \ - cp ginclude/$$realfile $$objdir/include; \ - chmod a+r $$objdir/include/$$realfile; \ + touch include/$$realfile; \ + rm -f include/$$realfile; \ + cp $$file include; \ + chmod a+r include/$$realfile; \ fi; \ done rm -f include/limits.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 && \ + chmod a+r include/float.h; \ + else :; fi # Install the README rm -f include/README cp $(srcdir)/README-fixinc include/README chmod a+r include/README - touch stmp-int-hdrs + touch $@ -# Build the complete include directory. -stmp-headers: stmp-int-hdrs gfloat.h - rm -f include/float.h - cp gfloat.h include/float.h - chmod a+r include/float.h - touch stmp-headers +# Now that gfloat.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 # Build fixed copies of system files. stmp-fixinc: $(FIXINCLUDES) gsyslimits.h @@ -1773,6 +2010,12 @@ stmp-fixinc: $(FIXINCLUDES) gsyslimits.h $(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 rm -f include/syslimits.h @@ -1784,35 +2027,27 @@ stmp-fixinc: $(FIXINCLUDES) gsyslimits.h chmod a+r include/syslimits.h touch stmp-fixinc -# copy objc header files into build directory -objc-headers: stmp-fixinc - if [ -d include ]; then true; else mkdir include; fi - if [ -d objc ]; then true; else mkdir objc; fi - thisdir1=`pwd`; \ - srcdir1=`cd $(srcdir); pwd`; \ - cd objc; \ - $(MAKE) -f $${srcdir1}/objc/Makefile copy-headers \ - srcdir=$${srcdir1} tooldir=$(tooldir) AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" \ - GCC_FOR_TARGET="$${thisdir1}/xgcc -B$${thisdir1}/" \ - GCC_CFLAGS="$(GCC_CFLAGS)" incinstalldir=$${thisdir1}/include - touch objc-headers - # Files related to the fixproto script. deduced.h: $(GCC_PASSES) $(srcdir)/scan-types.sh stmp-int-hdrs - CC="$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) -I. -I$(srcdir) -Iinclude -I${SYSTEM_HEADER_DIR}"; \ + if [ -d $(SYSTEM_HEADER_DIR) ]; \ + then \ + CC="$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) -I. -I$(srcdir) -Iinclude -I${SYSTEM_HEADER_DIR}"; \ export CC; \ - $(SHELL) $(srcdir)/scan-types.sh "$(srcdir)" >tmp-deduced.h - mv tmp-deduced.h deduced.h + $(SHELL) $(srcdir)/scan-types.sh "$(srcdir)" >tmp-deduced.h; \ + mv tmp-deduced.h deduced.h; \ + else \ + 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.o: gen-protos.c scan.h $(build_xm_file) +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 -scan.o: scan.c scan.h $(build_xm_file) +scan.o: scan.c scan.h $(build_xm_file) system.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/scan.c xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos Makefile @@ -1825,15 +2060,16 @@ 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 cpperror.o version.o + cpplib.o cpphash.o cppalloc.o cppexp.o prefix.o version.o $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ fix-header.o \ - scan-decls.o scan.o cpplib.o cpphash.o cppalloc.o version.o \ - cppexp.o $(HOST_LIBS) + scan-decls.o scan.o cpplib.o cpphash.o cppalloc.o prefix.o \ + version.o cppexp.o $(HOST_LIBS) -fix-header.o: fix-header.c obstack.h scan.h xsys-protos.h $(build_xm_file) +fix-header.o: fix-header.c 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) +scan-decls.o: scan-decls.c scan.h cpplib.h $(build_xm_file) system.h gansidecl.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/scan-decls.c # stmp-fixproto depends on this, not on fix-header directly. @@ -1857,38 +2093,46 @@ 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; \ - $(SHELL) ${srcdir}/fixproto include include $(SYSTEM_HEADER_DIR); \ + if [ -d $(SYSTEM_HEADER_DIR) ] ; then \ + $(SHELL) ${srcdir}/fixproto include include $(SYSTEM_HEADER_DIR); \ + else true; fi; \ touch include/fixed; \ fi touch stmp-fixproto - +# # Remake the info files. doc: info -info: $(srcdir)/cpp.info $(srcdir)/gcc.info lang.info +info: cpp.info gcc.info lang.info -$(srcdir)/cpp.info: cpp.texi - cd $(srcdir); $(MAKEINFO) cpp.texi +cpp.info: $(srcdir)/cpp.texi + $(MAKEINFO) $(MAKEINFOFLAGS) -I$(srcdir) -o cpp.info $(srcdir)/cpp.texi -$(srcdir)/gcc.info: gcc.texi extend.texi install.texi invoke.texi \ - md.texi rtl.texi tm.texi - cd $(srcdir); $(MAKEINFO) gcc.texi +gcc.info: $(srcdir)/gcc.texi $(srcdir)/extend.texi $(srcdir)/install.texi \ + $(srcdir)/invoke.texi $(srcdir)/md.texi $(srcdir)/rtl.texi \ + $(srcdir)/tm.texi $(srcdir)/gcov.texi + $(MAKEINFO) $(MAKEINFOFLAGS) -I$(srcdir) -o gcc.info $(srcdir)/gcc.texi -dvi: $(srcdir)/gcc.dvi $(srcdir)/cpp.dvi lang.dvi +dvi: gcc.dvi cpp.dvi lang.dvi # This works with GNU Make's default rule. -$(srcdir)/gcc.dvi: gcc.texi extend.texi install.texi invoke.texi \ - md.texi rtl.texi tm.texi - $(TEXI2DVI) $< +gcc.dvi: $(srcdir)/gcc.texi $(srcdir)/extend.texi $(srcdir)/install.texi \ + $(srcdir)/invoke.texi $(srcdir)/md.texi $(srcdir)/rtl.texi \ + $(srcdir)/tm.texi $(srcdir)/gcov.texi + TEXINPUTS=${texidir}:$(srcdir):$$TEXINPUTS tex gcc.texi + texindex gcc.?? + TEXINPUTS=${texidir}:$(srcdir):$$TEXINPUTS tex gcc.texi + +cpp.dvi: $(srcdir)/cpp.texi + TEXINPUTS=${texidir}:$(srcdir):$$TEXINPUTS tex cpp.texi + texindex cpp.?? + TEXINPUTS=${texidir}:$(srcdir):$$TEXINPUTS tex cpp.texi -# This works with GNU Make's default rule. -$(srcdir)/cpp.dvi: cpp.texi - $(TEXI2DVI) $< -$(srcdir)/INSTALL: install1.texi install.texi +INSTALL: $(srcdir)/install1.texi $(srcdir)/install.texi cd $(srcdir); $(MAKEINFO) -D INSTALLONLY --no-header \ - --no-split install1.texi -o INSTALL - + --no-split -o INSTALL install1.texi +# # Deletion of files made during compilation. # There are four levels of this: # `mostlyclean', `clean', `distclean' and `maintainer-clean'. @@ -1898,40 +2142,32 @@ $(srcdir)/INSTALL: install1.texi install.texi # `clean' deletes everything made by running `make all'. # `distclean' also deletes the files made by config. # `maintainer-clean' also deletes everything that could be regenerated -# automatically. We remove as much from the language subdirectories as we can +# automatically, except for `configure'. +# We remove as much from the language subdirectories as we can # (less duplicated code). -mostlyclean: bytecode.mostlyclean lang.mostlyclean +mostlyclean: lang.mostlyclean -rm -f $(STAGESTUFF) -# Clean the objc subdir if we created one. - if [ -d objc ]; then \ - srcdir1=`cd $(srcdir); pwd`; \ - cd objc; $(MAKE) -f $$srcdir1/objc/Makefile mostlyclean; \ - else true; fi - -rm -f libobjc.a # Delete the temporary source copies for cross compilation. -rm -f $(HOST_PREFIX_1)rtl.c $(HOST_PREFIX_1)rtlanal.c -rm -f $(HOST_PREFIX_1)alloca.c $(HOST_PREFIX_1)malloc.c -rm -f $(HOST_PREFIX_1)obstack.c # Delete the temp files made in the course of building libgcc.a. - -rm -f tmplibgcc* tmpcopy xlimits.h + -rm -f tmplibgcc* tmpcopy xlimits.h libgcc1-test for name in $(LIB1FUNCS); do rm -f $${name}.c; done -# Delete other temporary files. - -rm -f tmp-float.h tmp-gcc.xtar.gz - -rm -f tmp-foo1 tmp-foo2 tmp-proto.* tmp-unproto.1 tmp-SYSCALLS.s - -rm -f tmp-c-parse.y tmp-objc-prs.y tmp-gperf.h - -rm -f tmp-specs t-float.h-cross tmp-xlimits.h - -rm -f tmp-fixtmp.c xsys-protos.hT -# Delete the stamp files. - -rm -f stamp-* tmp-* +# Delete other built files. + -rm -f t-float.h-cross xsys-protos.hT fp-bit.c dp-bit.c +# Delete the stamp and temporary files. + -rm -f s-* tmp-* stamp-* stmp-* -rm -f */stamp-* */tmp-* # Delete debugging dump files. -rm -f *.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop - -rm -f *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack + -rm -f *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.addressof + -rm -f *.regmove *.mach *.bp *.gcse -rm -f */*.greg */*.lreg */*.combine */*.flow */*.cse */*.jump */*.rtl -rm -f */*.tree */*.loop */*.dbr */*.jump2 */*.sched */*.cse2 - -rm -f */*.sched2 */*.stack + -rm -f */*.sched2 */*.stack */*.regmove */*.gcse # Delete some files made during installation. -rm -f specs gfloat.h float.h-* enquire SYSCALLS.c.X SYSCALLS.c -rm -f collect collect2 mips-tfile mips-tdump alloca.s @@ -1945,10 +2181,11 @@ mostlyclean: bytecode.mostlyclean lang.mostlyclean -rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns # Delete core dumps. -rm -f core */core + -rm -f *.bp */*.bp # Delete all files made by compilation # that don't exist in the distribution. -clean: mostlyclean bytecode.clean lang.clean +clean: mostlyclean 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, @@ -1961,8 +2198,7 @@ clean: mostlyclean bytecode.clean lang.clean rm -f md ; \ fi # Delete the include directory. - -rm -rf stmp-* include objc-headers - -rm -f */stmp-* + -rm -rf include # Delete files used by the "multilib" facility (including libgcc subdirs). -rm -f multilib.h tmpmultilib* -if [ "x$(MULTILIB_DIRNAMES)" != x ] ; then \ @@ -1970,18 +2206,23 @@ clean: mostlyclean bytecode.clean lang.clean else if [ "x$(MULTILIB_OPTIONS)" != x ] ; then \ rm -rf `echo $(MULTILIB_OPTIONS) | sed -e 's/\// /g'`; \ fi ; fi + -rm -fr stage1 stage2 stage3 stage4 # Delete all files that users would normally create # while building and installing GCC. -distclean: clean bytecode.distclean lang.distclean - -rm -f tm.h config.h tconfig.h hconfig.h md - -rm -f config.status config.run +distclean: clean 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 -fr stage1 stage2 stage3 stage4 + -rm -f gthr-default.h -rm -f */stage1 */stage2 */stage3 */stage4 */include - -rm -f objc-parse.output -rm -f c-parse.output -rm -f *.asm + -rm -f float.h + -rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak + -rm -f testsuite/{gcc,g++}.{log,sum} # Delete anything likely to be found in the source directory # that shouldn't be in the distribution. @@ -1993,23 +2234,25 @@ extraclean: distclean lang.extraclean -rm -f *.dvi *.ps *.oaux *.d *.[zZ] *.gz -rm -f *.tar *.xtar *diff *.diff.* *.tar.* *.xtar.* *diffs -rm -f *lose config/*lose config/*/*lose - -rm -f *.s *.s[0-9] *.i install1.texi config/ChangeLog + -rm -f *.s *.s[0-9] *.i config/ChangeLog -rm -f */=* */"#"* */*~* -rm -f */patch* */*.orig */*.rej -rm -f */*.dvi */*.oaux */*.d */*.[zZ] */*.gz -rm -f */*.tar */*.xtar */*diff */*.diff.* */*.tar.* */*.xtar.* */*diffs -rm -f */*lose */*.s */*.s[0-9] */*.i -# Get rid of every file that's generated from some other file. +# 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. -maintainer-clean: distclean bytecode.maintainer-clean lang.maintainer-clean - -rm -f c-parse.y c-gperf.h objc-parse.y - -rm -f objc-parse.c objc-parse.output +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 + -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 -rm -f cpp.info* cpp.??s cpp.*aux -rm -f gcc.info* gcc.??s gcc.*aux - +# # Entry points `install' and `uninstall'. # Also use `install-collect2' to install collect2 when the config files don't. @@ -2022,7 +2265,8 @@ 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-libobjc install-man install-info lang.install-normal install-driver + $(INSTALL_CPP) install-man install-info lang.install-normal \ + install-driver # Do nothing while making gcc with a cross-compiler. The person who # makes gcc for the target machine has to know how to put a complete @@ -2034,9 +2278,28 @@ install-build: force # to finish installation of cross compiler. 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 + if [ x$(cpp_install_dir) != x ]; then \ + rm -f $(cpp_install_dir)/cpp; \ + $(INSTALL_PROGRAM) -m 755 cpp.sh $(cpp_install_dir)/cpp; \ + 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; \ + else true; fi + # Install float.h for cross compiler. # Run this on the target machine! -install-float-h-cross: install-dir +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. ./enquire -f > $(tmpdir)/float.h @@ -2045,15 +2308,18 @@ install-float-h-cross: install-dir -rm -f $(tmpdir)/float.h chmod a-x $(libsubdir)/include/float.h -# Create the installation directory. -install-dir: +# Create the installation directories. +installdirs: + -if [ -d $(prefix) ] ; then true ; else mkdir $(prefix) ; chmod a+rx $(prefix) ; fi + -if [ -d $(exec_prefix) ] ; then true ; else mkdir $(exec_prefix) ; chmod a+rx $(exec_prefix) ; fi -if [ -d $(libdir) ] ; then true ; else mkdir $(libdir) ; chmod a+rx $(libdir) ; fi -if [ -d $(libdir)/gcc-lib ] ; then true ; else mkdir $(libdir)/gcc-lib ; chmod a+rx $(libdir)/gcc-lib ; fi # This dir isn't currently searched by cpp. # -if [ -d $(libdir)/gcc-lib/include ] ; then true ; else mkdir $(libdir)/gcc-lib/include ; chmod a+rx $(libdir)/gcc-lib/include ; fi - -if [ -d $(libdir)/gcc-lib/$(target) ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target) ; chmod a+rx $(libdir)/gcc-lib/$(target) ; fi - -if [ -d $(libdir)/gcc-lib/$(target)/$(version) ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target)/$(version) ; chmod a+rx $(libdir)/gcc-lib/$(target)/$(version) ; fi - -if [ -d $(libdir)/gcc-lib/$(target)/$(version)/include ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target)/$(version)/include ; chmod a+rx $(libdir)/gcc-lib/$(target)/$(version)/include ; fi + -fdir= ; for dir in `echo $(libsubdir) | tr '/' ' '`; do \ + fdir=$${fdir}/$${dir}; \ + if [ -d $${fdir} ] ; then true ; else mkdir $${fdir}; chmod a+rx $${fdir}; fi ; \ + 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 @@ -2067,7 +2333,7 @@ install-dir: -if [ -d $(mandir) ] ; then true ; else mkdir $(mandir) ; chmod a+rx $(mandir) ; fi # Install the compiler executables built during cross compilation. -install-common: native install-dir $(EXTRA_PARTS) lang.install-common +install-common: native installdirs $(EXTRA_PARTS) lang.install-common for file in $(COMPILERS); do \ if [ -f $$file ] ; then \ rm -f $(libsubdir)/$$file; \ @@ -2085,30 +2351,46 @@ install-common: native install-dir $(EXTRA_PARTS) lang.install-common if [ x"$$file" != x.. ]; then \ rm -f $(libsubdir)/$$file; \ $(INSTALL_DATA) $$file $(libsubdir)/$$file; \ + chmod a-x $(libsubdir)/$$file; \ else true; fi; \ done # Don't mess with specs if it doesn't exist yet. -if [ -f specs ] ; then \ rm -f $(libsubdir)/specs; \ $(INSTALL_DATA) specs $(libsubdir)/specs; \ + chmod a-x $(libsubdir)/specs; \ fi # Install protoize if it was compiled. -if [ -f protoize$(exeext) ]; \ then \ - rm -f $(bindir)/protoize$(exeext); \ - $(INSTALL_PROGRAM) protoize$(exeext) $(bindir)/protoize$(exeext); \ - rm -f $(bindir)/unprotoize$(exeext); \ - $(INSTALL_PROGRAM) unprotoize$(exeext) $(bindir)/unprotoize$(exeext); \ + if [ -f gcc-cross$(exeext) ] ; then \ + rm -f $(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext); \ + $(INSTALL_PROGRAM) protoize$(exeext) $(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext); \ + rm -f $(bindir)/$(UNPROTOIZE_CROSS_NAME)$(exeext); \ + $(INSTALL_PROGRAM) unprotoize$(exeext) $(bindir)/$(UNPROTOIZE_CROSS_NAME)$(exeext); \ + else \ + rm -f $(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext); \ + $(INSTALL_PROGRAM) protoize$(exeext) $(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext); \ + rm -f $(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext); \ + $(INSTALL_PROGRAM) unprotoize$(exeext) $(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext); \ + fi ; \ rm -f $(libsubdir)/SYSCALLS.c.X; \ $(INSTALL_DATA) SYSCALLS.c.X $(libsubdir)/SYSCALLS.c.X; \ chmod a-x $(libsubdir)/SYSCALLS.c.X; \ fi -rm -f $(libsubdir)/cpp$(exeext) $(INSTALL_PROGRAM) cpp$(exeext) $(libsubdir)/cpp$(exeext) +# Install gcov if it was compiled. + -if [ -f gcov$(exeext) ]; \ + then \ + rm -f $(bindir)/gcov$(exeext); \ + $(INSTALL_PROGRAM) gcov$(exeext) $(bindir)/gcov$(exeext); \ + chmod a+x $(bindir)/gcov$(exeext); \ + fi -# Install the driver program as $(target)-gcc +# Install the driver program as $(target_alias)-gcc # and also as either gcc (if native) or $(tooldir)/bin/gcc. -install-driver: xgcc +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); \ @@ -2119,23 +2401,31 @@ install-driver: xgcc else \ rm -f $(bindir)/$(GCC_INSTALL_NAME)$(exeext); \ $(INSTALL_PROGRAM) xgcc$(exeext) $(bindir)/$(GCC_INSTALL_NAME)$(exeext); \ - rm -f $(bindir)/$(target)-gcc-1$(exeext); \ - ln $(bindir)/$(GCC_INSTALL_NAME)$(exeext) $(bindir)/$(target)-gcc-1$(exeext) \ - > /dev/null 2>&1 \ - || cp $(bindir)/$(GCC_INSTALL_NAME)$(exeext) $(bindir)/$(target)-gcc-1$(exeext); \ - mv $(bindir)/$(target)-gcc-1$(exeext) $(bindir)/$(target)-gcc$(exeext); \ + rm -f $(bindir)/$(target_alias)-gcc-1$(exeext); \ + $(LN) $(bindir)/$(GCC_INSTALL_NAME)$(exeext) $(bindir)/$(target_alias)-gcc-1$(exeext); \ + mv $(bindir)/$(target_alias)-gcc-1$(exeext) $(bindir)/$(target_alias)-gcc$(exeext); \ fi # Install the info files. -install-info: doc install-dir lang.install-info +# $(INSTALL_DATA) might be a relative pathname, so we can't cd into srcdir +# to do the install. +install-info: doc installdirs lang.install-info -rm -f $(infodir)/cpp.info* $(infodir)/gcc.info* - cd $(srcdir); for f in cpp.info* gcc.info*; \ - do $(INSTALL_DATA) $$f $(infodir)/$$f; done + for f in cpp.info* gcc.info*; do \ + $(INSTALL_DATA) $$f $(infodir)/$$f; \ + done + -if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \ + if [ -f $(infodir)/dir ] ; then \ + for f in cpp.info gcc.info; do \ + install-info --dir-file=$(infodir)/dir $(infodir)/$$f; \ + done; \ + else true; fi; \ + else true; fi; -chmod a-x $(infodir)/cpp.info* $(infodir)/gcc.info* # Install the man pages. -install-man: install-dir $(srcdir)/gcc.1 $(srcdir)/cccp.1 lang.install-man - -if [ -f gcc-cross ] ; then \ +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); \ @@ -2149,7 +2439,7 @@ install-man: install-dir $(srcdir)/gcc.1 $(srcdir)/cccp.1 lang.install-man -chmod a-x $(mandir)/cccp$(manext) # Install the library. -install-libgcc: libgcc.a install-dir +install-libgcc: libgcc.a installdirs -if [ -f libgcc.a ] ; then \ rm -f $(libsubdir)/libgcc.a; \ $(INSTALL_DATA) libgcc.a $(libsubdir)/libgcc.a; \ @@ -2159,31 +2449,24 @@ install-libgcc: libgcc.a install-dir else true; fi # Install multiple versions of libgcc.a. -install-multilib: stmp-multilib install-dir +install-multilib: stmp-multilib installdirs for i in `$(GCC_FOR_TARGET) --print-multi-lib`; do \ dir=`echo $$i | sed -e 's/;.*$$//'`; \ if [ -d $(libsubdir)/$${dir} ]; then true; else mkdir $(libsubdir)/$${dir}; fi; \ - rm -f $(libsubdir)/$${dir}/libgcc.a; \ - $(INSTALL_DATA) $${dir}/libgcc.a $(libsubdir)/$${dir}/libgcc.a; \ + for f in libgcc.a $(EXTRA_MULTILIB_PARTS); do \ + 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; \ chmod a-x $(libsubdir)/$${dir}/libgcc.a; \ done -# Install the objc run time library. -install-libobjc: install-dir - -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 - # Install all the header files built in the include subdirectory. install-headers: install-include-dir $(INSTALL_HEADERS_DIR) $(INSTALL_ASSERT_H) # Fix symlinks to absolute paths in the installed include directory to # point to the installed directory, not the build directory. +# Don't need to use LN_S here since we really do need ln -s and no substitutes. -files=`cd $(libsubdir)/include; find . -type l -print 2>/dev/null`; \ if [ $$? -eq 0 ]; then \ dir=`cd include; pwd`; \ @@ -2197,7 +2480,7 @@ install-headers: install-include-dir $(INSTALL_HEADERS_DIR) $(INSTALL_ASSERT_H) fi # Create or recreate the gcc private include file directory. -install-include-dir: install-dir +install-include-dir: installdirs -rm -rf $(libsubdir)/include mkdir $(libsubdir)/include -chmod a+rx $(libsubdir)/include @@ -2221,7 +2504,7 @@ install-headers-cpio: stmp-headers $(STMP_FIXPROTO) install-include-dir ## Don't replace the assert.h already there if it is not from GCC. ## This code would be simpler if it tested for -f ... && ! grep ... ## but supposedly the ! operator is missing in sh on some systems. -install-assert-h: assert.h install-dir +install-assert-h: assert.h installdirs if [ -f $(assertdir)/assert.h ]; \ then \ if grep "__eprintf" $(assertdir)/assert.h >/dev/null; \ @@ -2237,57 +2520,150 @@ install-assert-h: assert.h install-dir chmod a-x $(assertdir)/assert.h; \ fi -# Use this target to install the program `collect2' under the name `ld'. -install-collect2: collect2 install-dir - $(INSTALL_PROGRAM) collect2$(exeext) $(libsubdir)/ld$(exeext) +# Use this target to install the program `collect2' under the name `collect2'. +install-collect2: collect2 installdirs + $(INSTALL_PROGRAM) collect2$(exeext) $(libsubdir)/collect2$(exeext) # Install the driver program as $(libsubdir)/gcc for collect2. $(INSTALL_PROGRAM) xgcc$(exeext) $(libsubdir)/gcc$(exeext) # Cancel installation by deleting the installed files. -uninstall: lang.uninstall +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 -f $(infodir)/cpp.info* $(infodir)/gcc.info* +# +# These targets are for the dejagnu testsuites. The file site.exp +# contains global variables that all the testsuites will use. + +# Set to $(target_alias)/ for cross. +target_subdir = @target_subdir@ + +site.exp: ./config.status Makefile + @echo "Making a new config file..." + -@rm -f ./tmp? + @touch site.exp + -@mv site.exp site.bak + @echo "## these variables are automatically generated by make ##" > ./tmp0 + @echo "# Do not edit here. If you wish to override these values" >> ./tmp0 + @echo "# add them to the last section" >> ./tmp0 + @echo "set rootme \"`pwd`\"" >> ./tmp0 + @echo "set srcdir \"`cd ${srcdir}; pwd`\"" >> ./tmp0 + @echo "set host_triplet $(host_canonical)" >> ./tmp0 + @echo "set build_triplet $(build_canonical)" >> ./tmp0 + @echo "set target_triplet $(target)" >> ./tmp0 + @echo "set target_alias $(target_alias)" >> ./tmp0 +# CFLAGS is set even though it's empty to show we reserve the right to set it. + @echo "set CFLAGS \"\"" >> ./tmp0 + @echo "set CXXFLAGS \"-I$(objdir)/../$(target_subdir)libio -I\$$srcdir/../libg++/src -I\$$srcdir/../libio -I\$$srcdir/../libstdc++ -I\$$srcdir/../libstdc++/stl -L$(objdir)/../$(target_subdir)libg++ -L$(objdir)/../$(target_subdir)libstdc++\"" >> ./tmp0 +# If newlib has been configured, we need to pass -B to gcc so it can find +# newlib's crt0.o if it exists. This will cause a "path prefix not used" +# message if it doesn't, but the testsuite is supposed to ignore the message - +# it's too difficult to tell when to and when not to pass -B (not all targets +# have crt0's). We could only add the -B if ../newlib/crt0.o exists, but that +# seems like too selective a test. +# ??? Another way to solve this might be to rely on linker scripts. Then +# theoretically the -B won't be needed. +# We also need to pass -L ../ld so that the linker can find ldscripts. + @if [ -d $(objdir)/../$(target_subdir)newlib ] ; then \ + echo "set newlib_cflags \"-I$(objdir)/../$(target_subdir)newlib/targ-include -I\$$srcdir/../newlib/libc/include\"" >> ./tmp0; \ + echo "set newlib_ldflags \"-B$(objdir)/../$(target_subdir)newlib/\"" >> ./tmp0; \ + echo "append CFLAGS \" \$$newlib_cflags\"" >> ./tmp0; \ + echo "append CXXFLAGS \" \$$newlib_cflags\"" >> ./tmp0; \ + echo "append LDFLAGS \" \$$newlib_ldflags\"" >> ./tmp0; \ + else true; \ + fi + @if [ -d $(objdir)/../ld ] ; then \ + echo "append LDFLAGS \" -L$(objdir)/../ld\"" >> ./tmp0; \ + else true; \ + fi + echo "set tmpdir $(objdir)/testsuite" >> ./tmp0 + @echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./tmp0 + @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0 + @cat ./tmp0 > site.exp + @cat site.bak | sed \ + -e '1,/^## All variables above are.*##/ d' >> site.exp + -@rm -f ./tmp? + +CHECK_TARGETS = check-gcc check-g++ check-g77 + +check: $(CHECK_TARGETS) + +testsuite/site.exp: site.exp + if [ -d testsuite ]; then \ + true; \ + else \ + mkdir testsuite; \ + fi + rm -rf testsuite/site.exp + cp site.exp testsuite/site.exp + +check-g++: 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=$${srcdir}/../tcl/library ; \ + export TCL_LIBRARY ; fi ; \ + $(RUNTEST) --tool g++ $(RUNTESTFLAGS) + +check-gcc: 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=$${srcdir}/../tcl/library ; \ + export TCL_LIBRARY ; fi ; \ + $(RUNTEST) --tool gcc $(RUNTESTFLAGS) + +check-g77: 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=$${srcdir}/../tcl/library ; \ + export TCL_LIBRARY ; fi ; \ + $(RUNTEST) --tool g77 $(RUNTESTFLAGS) + # These exist for maintenance purposes. # Update the tags table. TAGS: force cd $(srcdir); \ - mkdir temp; \ - mv -f c-parse.[ch] objc-parse.c cexp.c =*.[chy] temp; \ + mkdir tmp-tags; \ + mv -f c-parse.[ch] cexp.c =*.[chy] tmp-tags; \ etags *.y *.h *.c; \ - mv temp/* .; \ - rmdir temp + mv tmp-tags/* .; \ + rmdir tmp-tags -# Create the distribution tar file. -#dist: gcc-$(version).tar.gz -dist: gcc.xtar.gz +# Create the distribution tar.gz file. +dist: tmp-gcc.xtar + gzip --best < tmp-gcc.xtar > tmp-gcc.xtar.gz + mv tmp-gcc.xtar.gz gcc-$(version).tar.gz -gcc.xtar.gz: gcc.xtar - gzip --best < gcc.xtar > tmp-gcc.xtar.gz - mv tmp-gcc.xtar.gz gcc.xtar.gz - -#gcc-$(version).tar.gz: gcc-$(version).tar -# gzip < gcc-$(version).tar > gcc-$(version).tar.gz - -#gcc-$(version).tar: -gcc.xtar: distdir +tmp-gcc.xtar: distdir # Make the distribution. - tar -chf gcc.xtar gcc-$(version) + tar -chf tmp-gcc.xtar gcc-$(version) + +distdir-cvs: force + if [ -d $(srcdir)/CVS ]; then 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)/objc-parse.y $(srcdir)/c-parse.c $(srcdir)/objc-parse.c \ - $(srcdir)/cexp.c + $(srcdir)/c-parse.c $(srcdir)/cexp.c $(srcdir)/config.in \ + $(srcdir)/version.c TAGS @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;\ @@ -2304,35 +2680,31 @@ distdir-start: doc $(srcdir)/INSTALL $(srcdir)/c-parse.y $(srcdir)/c-gperf.h \ mkdir tmp mkdir tmp/config mkdir tmp/ginclude - mkdir tmp/objc for file in *[0-9a-zA-Z+]; do \ - ln $$file tmp > /dev/null 2>&1 || cp $$file tmp; \ + $(LN) $$file tmp; \ done cd config; \ for file in *[0-9a-zA-Z+]; do \ - if test -d $$file && test "$$file" != RCS; then \ + 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 >/dev/null 2>&1 \ - || cp $$subfile ../../tmp/config/$$file; \ + $(LN) $$subfile ../../tmp/config/$$file; \ done; \ cd ..; \ else \ - ln $$file ../tmp/config >/dev/null 2>&1 \ - || cp $$file ../tmp/config; \ + $(LN) $$file ../tmp/config; \ fi; \ done cd ginclude; \ for file in *[0-9a-zA-Z+]; do \ - ln $$file ../tmp/ginclude >/dev/null 2>&1 \ - || cp $$file ../tmp/ginclude; \ + $(LN) $$file ../tmp/ginclude; \ done cd objc; \ for file in *[0-9a-zA-Z+]; do \ - ln $$file ../tmp/objc >/dev/null 2>&1 || cp $$file ../tmp/objc; \ + $(LN) $$file ../tmp/objc; \ done - ln .gdbinit tmp + $(LN) .gdbinit tmp # Finish making `distdir', after the languages have done their thing. distdir-finish: @@ -2340,112 +2712,117 @@ 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 + cd gcc-$(version); make extraclean VERSION_DEP= -distdir: distdir-start lang.distdir distdir-finish +distdir: distdir-cvs distdir-start lang.distdir distdir-finish # make diff oldversion=M.N # creates a diff file between an older distribution and this one. # The -P option assumes this is GNU diff. diff: diff -rc2P -x c-parse.y -x c-parse.c -x c-parse.h -x c-gperf.h \ - -x cexp.c -x bi-parser.c -x objc-parse.y -x objc-parse.c \ - -x TAGS \ + -x cexp.c -x -x TAGS -x INSTALL \ + -x configure -x config.in \ -x "gcc.??" -x "gcc.??s" -x gcc.aux -x "gcc.info*" \ -x "cpp.??" -x "cpp.??s" -x cpp.aux -x "cpp.info*" \ $(LANG_DIFF_EXCLUDES) \ - gcc-$(oldversion) gcc-$(version) > diffs + gcc-$(oldversion) gcc-$(version) > gcc-$(oldversion)-$(version).diff -bootstrap: force +bootstrap bootstrap-lean: force # Only build the C compiler for stage1, because that is the only one that # we can guarantee will build with the native compiler, and also it is the # only thing useful for building stage2. - $(MAKE) CC="$(CC)" libdir=$(libdir) LANGUAGES=c + $(MAKE) CC="$(CC)" libdir=$(libdir) LANGUAGES="$(BOOT_LANGUAGES)" $(MAKE) stage1 # This used to define ALLOCA as empty, but that would lead to bad results # for a subsequent `make install' since that would not have ALLOCA empty. # 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 -Bstage1/" CFLAGS="$(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ LANGUAGES="$(LANGUAGES)" + $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ LANGUAGES="$(LANGUAGES)" $(MAKE) stage2 - $(MAKE) CC="stage2/xgcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)" + -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)" -bootstrap2: force - $(MAKE) CC="stage1/xgcc -Bstage1/" CFLAGS="$(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ 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) stage2 - $(MAKE) CC="stage2/xgcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)" + -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)" + +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)" -bootstrap3: force - $(MAKE) CC="stage2/xgcc -Bstage2/" 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)" # Compare the object files in the current directory with those in the # stage2 directory. # ./ avoids bug in some versions of tail. -compare: force - for file in *$(objext); do \ - tail +16c ./$$file > tmp-foo1; \ - tail +16c stage2/$$file > tmp-foo2 2>/dev/null \ - && (cmp tmp-foo1 tmp-foo2 || echo $$file differs) || true; \ - done - for dir in tmp-foo $(SUBDIRS); do \ - if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \ - for file in $$dir/*$(objext); do \ - tail +16c ./$$file > tmp-foo1; \ - tail +16c stage2/$$file > tmp-foo2 2>/dev/null \ - && (cmp tmp-foo1 tmp-foo2 || echo $$file differs) || true; \ - done; \ - fi; \ - done - -rm -f tmp-foo* - -# Similar, but compare with stage3 directory -compare3: force +compare compare3 compare4 compare-lean compare3-lean compare4-lean: force + -rm -f .bad_compare + case "$@" in compare | compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^compare\([0-9][0-9]*\).*,\1,'` ;; esac; \ for file in *$(objext); do \ tail +16c ./$$file > tmp-foo1; \ - tail +16c stage3/$$file > tmp-foo2 2>/dev/null \ - && (cmp tmp-foo1 tmp-foo2 || echo $$file differs) || true; \ + tail +16c stage$$stage/$$file > tmp-foo2 \ + && (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 \ if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \ for file in $$dir/*$(objext); do \ - tail +16c ./$$file > tmp-foo1; \ - tail +16c stage3/$$file > tmp-foo2 2>/dev/null \ - && (cmp tmp-foo1 tmp-foo2 || echo $$file differs) || true; \ + 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; \ done; \ 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; \ + if [ -f .bad_compare ]; then \ + echo "Bootstrap comparison failure!"; \ + cat .bad_compare; \ + exit 1; \ + else \ + case "$@" in \ + *-lean ) rm -rf stage$$stage ;; \ + *) ;; \ + esac; true; \ + fi # Compare the object files in the current directory with those in the # stage2 directory. Use gnu cmp (diffutils v2.4 or later) to avoid # running tail and the overhead of twice copying each object file. -gnucompare: force +gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-lean: force + -rm -f .bad_compare + case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \ for file in *$(objext); do \ - cmp --ignore-initial=16 $$file stage2/$$file || true ; \ + (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 \ if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \ for file in $$dir/*$(objext); do \ - cmp --ignore-initial=16 $$file stage2/$$file || true ; \ - done; \ - fi; \ - done - -# Similar, but compare with stage3 directory -gnucompare3: force - for file in *$(objext); do \ - cmp --ignore-initial=16 $$file stage3/$$file || true ; \ - done - for dir in tmp-foo $(SUBDIRS); do \ - if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \ - for file in $$dir/*$(objext); do \ - cmp --ignore-initial=16 $$file stage3/$$file || true ; \ + 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; \ done; \ 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 \ + echo "Bootstrap comparison failure!"; \ + cat .bad_compare; \ + exit 1; \ + else \ + case "$@" in \ + *-lean ) rm -rf stage$$stage ;; \ + esac; true; \ + fi # Copy the object files from a particular stage into a subdirectory. stage1-start: @@ -2457,12 +2834,16 @@ stage1-start: -mv $(STAGESTUFF) stage1 # 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 || cp as$(exeext) stage1 ; else true ; fi - -if [ -f ld$(exeext) ] ; then ln -s ../ld$(exeext) stage1 || cp ld$(exeext) stage1 ; else true ; fi - -if [ -f collect-ld$(exeext) ] ; then ln -s ../collect-ld$(exeext) stage1 || cp collect-ld$(exeext) stage1 ; else true ; fi + -if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage1 ; else true ; fi + -if [ -f ld$(exeext) ] ; then $(LN_S) ../ld$(exeext) stage1 ; else true ; fi + -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 + -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ + cp stage1/$${f} . ; \ + else true; \ + fi; done stage1: force stage1-start lang.stage1 stage2-start: @@ -2474,12 +2855,16 @@ stage2-start: -mv $(STAGESTUFF) stage2 # 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 || cp as$(exeext) stage2 ; else true ; fi - -if [ -f ld$(exeext) ] ; then ln -s ../ld$(exeext) stage2 || cp ld$(exeext) stage2 ; else true ; fi - -if [ -f collect-ld ] ; then ln -s ../collect-ld$(exeext) stage2 || cp collect-ld$(exeext) stage2 ; else true ; fi + -if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage2 ; else true ; fi + -if [ -f ld$(exeext) ] ; then $(LN_S) ../ld$(exeext) stage2 ; else true ; fi + -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 + -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ + cp stage2/$${f} . ; \ + else true; \ + fi; done stage2: force stage2-start lang.stage2 stage3-start: @@ -2491,12 +2876,16 @@ stage3-start: -mv $(STAGESTUFF) stage3 # 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 || cp as$(exeext) stage3 ; else true ; fi - -if [ -f ld$(exeext) ] ; then ln -s ../ld$(exeext) stage3 || cp ld$(exeext) stage3 ; else true ; fi - -if [ -f collect-ld$(exeext) ] ; then ln -s ../collect-ld$(exeext) stage3 || cp collect-ld$(exeext) stage3 ; else true ; fi + -if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage3 ; else true ; fi + -if [ -f ld$(exeext) ] ; then $(LN_S) ../ld$(exeext) stage3 ; else true ; fi + -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 + -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ + cp stage3/$${f} . ; \ + else true; \ + fi; done stage3: force stage3-start lang.stage3 stage4-start: @@ -2508,19 +2897,23 @@ stage4-start: -mv $(STAGESTUFF) stage4 # 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 || cp as$(exeext) stage4 ; else true ; fi - -if [ -f ld$(exeext) ] ; then ln -s ../ld$(exeext) stage4 || cp ld$(exeext) stage4 ; else true ; fi - -if [ -f collect-ld$(exeext) ] ; then ln -s ../collect-ld$(exeext) stage4 || cp collect-ld$(exeext) stage4 ; else true ; fi + -if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage4 ; else true ; fi + -if [ -f ld$(exeext) ] ; then $(LN_S) ../ld$(exeext) stage4 ; else true ; fi + -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 + -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ + cp stage4/$${f} . ; \ + else true; \ + fi; done stage4: force stage4-start lang.stage4 # Copy just the executable files from a particular stage into a subdirectory, # and delete the object files. Use this if you're just verifying a version # that is pretty sure to work, and you are short of disk space. risky-stage1: stage1 - - make clean + -make clean risky-stage2: stage2 -make clean @@ -2536,3 +2929,57 @@ risky-stage4: stage4 .PHONY: risky-stage1 risky-stage2 risky-stage3 risky-stage4 force: + +# --- +# The enquire rules are still useful for building new float-anything.h. +# Special flags for compiling enquire. +# We disable optimization to make floating point more reliable. +ENQUIRE_CFLAGS = -DNO_MEM -DNO_LONG_DOUBLE_IO -O0 +ENQUIRE_LDFLAGS = $(LDFLAGS) + +# Enquire target (This is a variable so that a target can choose not to +# build it.) +ENQUIRE = enquire + +# Test to see whether exists in the system header files, +# and is not derived from GCC. +FLOAT_H_TEST = \ + [ -f $(SYSTEM_HEADER_DIR)/float.h ] && \ + if grep 'ifndef _FLOAT_H___' $(SYSTEM_HEADER_DIR)/float.h >/dev/null; \ + then false; \ + else :; fi +# We pretend to not having a usable , hence disable the FLOAT_H_TEST +# to ensure, we're emitting a full blown ourselves. +FLOAT_H_TEST = false + +# Used to compile enquire with standard cc, but have forgotten why. +# Let's try with GCC. +enquire: enquire.o $(GCC_PARTS) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@ +enquire.o: $(srcdir)/enquire.c $(GCC_PASSES) stmp-int-hdrs + if $(FLOAT_H_TEST); then \ + rm -f include/float.h; \ + SYS_FLOAT_H_WRAP=1; \ + else :; \ + SYS_FLOAT_H_WRAP=0; \ + fi; \ + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(ENQUIRE_CFLAGS) \ + -DSYS_FLOAT_H_WRAP=$$SYS_FLOAT_H_WRAP \ + -I. -c $(srcdir)/enquire.c + +# Create float.h source for the native machine. +# Make it empty if we can use the system float.h without changes. +float.h-nat: enquire + -./enquire -f > tmp-float.h + grep '#define [^_]' tmp-float.h >/dev/null || true > tmp-float.h + mv tmp-float.h float.h-nat + +# Create a dummy float.h source for a cross-compiler. +# ??? This isn't used anymore. Should we create config/float-unkn.h +# and make that the default float_format in configure? +float.h-cross: + echo "#ifndef __GCC_FLOAT_NOT_NEEDED" > t-float.h-cross + echo "#error float.h values not known for cross-compiler" >> t-float.h-cross + echo "#endif" >> t-float.h-cross + mv t-float.h-cross float.h-cross + diff --git a/contrib/gcc/NEWS b/contrib/gcc/NEWS index 9c23093..628b03c 100644 --- a/contrib/gcc/NEWS +++ b/contrib/gcc/NEWS @@ -1,13 +1,336 @@ -Noteworthy changes in GCC version 2.7.2.1: +Noteworthy changes in GCC for EGCS 1.1. +--------------------------------------- -This release fixes some serious bugs discovered since the 2.7.2 release. +The compiler now implements global common subexpression elimination (gcse) as +well as global constant/copy propagation. (link to gcse page). -Noteworthy changes in GCC version 2.7.2: +More major improvements have been made to the alias analysis code. A new +option to allow front-ends to provide alias information to the optimizers +has also been added (-fstrict-aliasing). -fstrict-aliasing is off by default +now, but will be enabled by default in the future. (link to alias page) + +Major changes continue in the exception handling support. This release +includes some changes to reduce static overhead for exception handling. It +also includes some major changes to the setjmp/longjmp based EH mechanism to +make it less pessimistic. And finally, major infrastructure improvements +to the dwarf2 EH mechanism have been made to make our EH support extensible. + +We have fixed the infamous security problems with temporary files. + +The "regmove" optimization pass has been nearly completely rewritten. It now +uses much more information about the target to determine profitability of +transformations. + +The compiler now recomputes register usage information immediately before +register allocation. Previously such information was only not kept up to +date after instruction combination which led to poor register allocation +choices by our priority based register allocator. + +The register reloading phase of the compiler has been improved to better +optimize spill code. This primarily helps targets which generate lots of +spills (like the x86 ports and many register poor embedded ports). + +A few changes in the heuristics used by the register allocator and scheduler +have been made which can significantly improve performance for certain +applications. + +The compiler's branch shortening algorithms have been significantly improved +to work better on targets which align jump targets. + +The compiler now supports the "ADDRESSOF" optimization which can significantly +reduce the overhead for certain inline calls (and inline calls in general). + +The compiler now supports a code size optimization switch (-Os). When enabled +the compiler will prefer optimizations which improve code size over those +which improve code speed. + +The compiler has been improved to completely eliminate library calls which +compute constant values. This is particularly useful on machines which +do not have integer mul/div or floating point support on-chip. + +GCC now supports a "--help" option to print detailed help information. + +cpplib has been greatly improved. It is probably useable for some sites now +(major missing feature is trigraphs). + +Memory footprint for the compiler has been significantly reduced for certain +pathalogical cases. + +Build time improvements for targets which support lots of sched parameters +(alpha and mips primarily). + +Compile time for certain programs using large constant initializers has been +improved (effects glibc significantly). + +Plus an incredible number of infrastructure changes, warning fixes, bugfixes +and local optimizations. + +Various improvements have been made to better support cross compilations. They +are still not easy, but they are improving. + +Target specific NEWS + + Sparc: Now includes V8 plus and V9 support, lots of tuning for Ultrasparcs + and uses the Haifa scheduler by default. + + Alpha: EV6 tuned, optimized expansion of memcpy/bzero. + + x86: Data in the static store is aligned per Intel recommendations. Jump + targets are aligned per Intel recommendations. Improved epilogue + sequences for Pentium chips. Backend improvements which should help + register allocation on all x86 variants. Support for PPro conditional + move instructions has been fixed and enabled. Random changes + throughout the port to make generated code more Pentium friendly. + Improved support for 64bit integer operations. + Unixware 7, a System V Release 5 target is now supported. + SCO OpenServer targets can support GAS. See gcc/INSTALL for details. + + RS6000/PowerPC: Includes AIX4.3 support as well as PowerPC64 support. + Haifa instruction scheduling is enabled by default now. + + MIPS: Multiply/Multiply-Add support has been largely rewritten to generate + more efficient code. Includes mips16 support. + + M68K: Various micro-optimizations and Coldfire fixes. + + M32r: Major improvements to this port. + + Arm: Includes Thumb and super interworking support. + +EGCS includes all gcc2 changes up to and including the June 9, 1998 snapshot. + + +Noteworthy changes in GCC version 2.8.1 +--------------------------------------- + +Numerous bugs have been fixed and some minor performance +improvements (compilation speed) have been made. + +Noteworthy changes in GCC version 2.8.0 +--------------------------------------- + +A major change in this release is the addition of a framework for +exception handling, currently used by C++. Many internal changes and +optimization improvements have been made. These increase the +maintainability and portability of GCC. GCC now uses autoconf to +compute many host parameters. + +The following lists changes that add new features or targets. + +See cp/NEWS for new features of C++ in this release. + +New tools and features: + + The Dwarf 2 debugging information format is supported on ELF systems, and + is the default for -ggdb where available. It can also be used for C++. + The Dwarf version 1 debugging format is also permitted for C++, but + does not work well. + + gcov.c is provided for test coverage analysis and branch profiling + analysis is also supported; see -fprofile-arcs, -ftest-coverage, + and -fbranch-probabilities. + + Support for the Checker memory checking tool. + + New switch, -fstack-check, to check for stack overflow on systems that + don't have such built into their ABI. + + New switches, -Wundef and -Wno-undef to warn if an undefined identifier + is evaluated in an #if directive. + + Options -Wall and -Wimplicit now cause GCC to warn about implicit int + in declarations (e.g. `register i;'), since the C Standard committee + has decided to disallow this in the next revision of the standard; + -Wimplicit-function-declarations and -Wimplicit-int are subsets of + this. + + Option -Wsign-compare causes GCC to warn about comparison of signed and + unsigned values. + + Add -dI option of cccp for cxref. + +New features in configuration, installation and specs file handling: + + New option --enable-c-cpplib to configure script. + + You can use --with-cpu on the configure command to specify the default + CPU that GCC should generate code for. + + The -specs=file switch allows you to override default specs used in + invoking programs like cc1, as, etc. + + Allow including one specs file from another and renaming a specs + variable. + + You can now relocate all GCC files with a single environment variable + or a registry entry under Windows 95 and Windows NT. + +Changes in Objective-C: + + The Objective-C Runtime Library has been made thread-safe. + + The Objective-C Runtime Library contains an interface for creating + mutexes, condition mutexes, and threads; it requires a back-end + implementation for the specific platform and/or thread package. + Currently supported are DEC/OSF1, IRIX, Mach, OS/2, POSIX, PCThreads, + Solaris, and Windows32. The --enable-threads parameter can be used + when configuring GCC to enable and select a thread back-end. + + Objective-C is now configured as separate front-end language to GCC, + making it more convenient to conditionally build it. + + The internal structures of the Objective-C Runtime Library have + changed sufficiently to warrant a new version number; now version 8. + Programs compiled with an older version must be recompiled. + + The Objective-C Runtime Library can be built as a DLL on Windows 95 + and Windows NT systems. + + The Objective-C Runtime Library implements +load. + +The following new targets are supported (see also list under each +individual CPU below): + + Embedded target m32r-elf. + Embedded Hitachi Super-H using ELF. + RTEMS real-time system on various CPU targets. + ARC processor. + NEC V850 processor. + Matsushita MN10200 processor. + Matsushita MN10300 processor. + Sparc and PowerPC running on VxWorks. + Support both glibc versions 1 and 2 on Linux-based GNU systems. + +New features for DEC Alpha systems: + + Allow detailed specification of IEEE fp support: + -mieee, -mieee-with-inexact, and -mieee-conformant + -mfp-trap-mode=xxx, -mfp-round-mode=xxx, -mtrap-precision=xxx + -mcpu=xxx for CPU selection + Support scheduling parameters for EV5. + Add support for BWX, CIX, and MAX instruction set extensions. + Support Linux-based GNU systems. + Support VMS. + +Additional supported processors and systems for MIPS targets: + + MIPS4 instruction set. + R4100, R4300 and R5000 processors. + N32 and N64 ABI. + IRIX 6.2. + SNI SINIX. + +New features for Intel x86 family: + + Add scheduling parameters for Pentium and Pentium Pro. + Support stabs on Solaris-x86. + Intel x86 processors running the SCO OpenServer 5 family. + Intel x86 processors running DG/UX. + Intel x86 using Cygwin32 or Mingw32 on Windows 95 and Windows NT. + +New features for Motorola 68k family: + + Support for 68060 processor. + More consistent switches to specify processor. + Motorola 68k family running AUX. + 68040 running pSOS, ELF object files, DBX debugging. + Coldfire variant of Motorola m68k family. + +New features for the HP PA RISC: + + -mspace and -mno-space + -mlong-load-store and -mno-long-load-store + -mbig-switch -mno-big-switch + + GCC on the PA requires either gas-2.7 or the HP assembler; for best + results using GAS is highly recommended. GAS is required for -g and + exception handling support. + +New features for SPARC-based systems: + + The ultrasparc cpu. + The sparclet cpu, supporting only a.out file format. + Sparc running SunOS 4 with the GNU assembler. + Sparc running the Linux-based GNU system. + Embedded Sparc processors running the ELF object file format. + -mcpu=xxx + -mtune=xxx + -malign-loops=xxx + -malign-jumps=xxx + -malign-functions=xxx + -mimpure-text and -mno-impure-text + + Options -mno-v8 and -mno-sparclite are no longer supported on SPARC + targets. Options -mcypress, -mv8, -msupersparc, -msparclite, -mf930, + and -mf934 are deprecated and will be deleted in GCC 2.9. Use + -mcpu=xxx instead. + +New features for rs6000 and PowerPC systems: + + Solaris 2.51 running on PowerPC's. + The Linux-based GNU system running on PowerPC's. + -mcpu=604e,602,603e,620,801,823,mpc505,821,860,power2 + -mtune=xxx + -mrelocatable-lib, -mno-relocatable-lib + -msim, -mmve, -memb + -mupdate, -mno-update + -mfused-madd, -mno-fused-madd + + -mregnames + -meabi + -mcall-linux, -mcall-solaris, -mcall-sysv-eabi, -mcall-sysv-noeabi + -msdata, -msdata=none, -msdata=default, -msdata=sysv, -msdata=eabi + -memb, -msim, -mmvme + -myellowknife, -mads + wchar_t is now of type long as per the ABI, not unsigned short. + -p/-pg support + -mcpu=403 now implies -mstrict-align. + Implement System V profiling. + + Aix 4.1 GCC targets now default to -mcpu=common so that programs + compiled can be moved between rs6000 and powerpc based systems. A + consequence of this is that -static won't work, and that some programs + may be slightly slower. + + You can select the default value to use for -mcpu=xxx on rs6000 and + powerpc targets by using the --with-cpu=xxx option when configuring the + compiler. In addition, a new options, -mtune=xxx was added that + selects the machine to schedule for but does not select the + architecture level. + + Directory names used for storing the multilib libraries on System V + and embedded PowerPC systems have been shortened to work with commands + like tar that have fixed limits on pathname size. + +New features for the Hitachi H8/300(H): + + -malign-300 + -ms (for the Hitachi H8/S processor) + -mint32 + +New features for the ARM: + + -march=xxx, -mtune=xxx, -mcpu=xxx + Support interworking with Thumb code. + ARM processor with a.out object format, COFF, or AOF assembler. + ARM on "semi-hosted" platform. + ARM running NetBSD. + ARM running the Linux-based GNU system. + +New feature for Solaris systems: + + GCC installation no longer makes a copy of system include files, + thus insulating GCC better from updates to the operating system. + + +Noteworthy changes in GCC version 2.7.2 +--------------------------------------- A few bugs have been fixed (most notably the generation of an invalid assembler opcode on some RS/6000 systems). -Noteworthy changes in GCC version 2.7.1: +Noteworthy changes in GCC version 2.7.1 +--------------------------------------- This release fixes numerous bugs (mostly minor) in GCC 2.7.0, but also contains a few new features, mostly related to specific targets. @@ -31,8 +354,9 @@ sequence used in GCC version 2.7.0. That calling sequence was based on the AIX calling sequence without function descriptors. To compile code for that older calling sequence, either configure the compiler for powerpc-*-eabiaix or use the -mcall-aix switch when compiling and linking. - -Noteworthy changes in GCC version 2.7.0: + +Noteworthy changes in GCC version 2.7.0 +--------------------------------------- GCC now works better on systems that use ".obj" and ".exe" instead of ".o" and no extension. This involved changes to the driver program, @@ -284,7 +608,7 @@ The following new configurations are supported: GNU on x86 (instead of treating it like MACH) NetBSD on Sparc and Motorola 68k AIX 4.1 on RS/6000 and PowerPC systems - Sequent DYNUX/ptx 1.x and 2.x. + Sequent DYNIX/ptx 1.x and 2.x. Both COFF and ELF configurations on AViiON without using /bin/gcc Windows/NT on x86 architecture; preliminary AT&T DSP1610 digital signal processor chips @@ -508,7 +832,7 @@ to declare complex data types. See the manual for details. * GCC now supports `long double' meaningfully on the Sparc (128-bit floating point) and on the 386 (96-bit floating point). The Sparc -support is enabled on on Solaris 2.x because earlier system versions +support is enabled on Solaris 2.x because earlier system versions (SunOS 4) have bugs in the emulation. * All targets now have assertions for cpu, machine and system. So you diff --git a/contrib/gcc/PROJECTS b/contrib/gcc/PROJECTS index ee9be02..2c2111a 100644 --- a/contrib/gcc/PROJECTS +++ b/contrib/gcc/PROJECTS @@ -1,12 +1,64 @@ -0. Improved efficiency. +C++ template friend functions (mmitchell@usa.net) -* Parse and output array initializers an element at a time, freeing -storage after each, instead of parsing the whole initializer first and -then outputting. This would reduce memory usage for large -initializers. +Haifa scheduler (haifa-sched.c, loop.[ch], unroll.[ch], genattrtab.c): +(contact law@cygnus.com before starting any serious haifa work) -* See if the techniques describe in Oct 1991 SIGPLAN Notices -(Frazer and Hanson) are applicable to GCC. + * Fix all the formatting problems. Simple, mindless work. + + * Fix/add comments throughout the code. Many of the comments are from + the old scheduler and are out of date and misleading. Many new hunks + of code don't have sufficient comments and documentation. Those which + do have comments need to be rewritten to use complete sentences and + proper formatting. + + * Someone needs make one (or more) passes over the scheduler as a whole to + just clean it up. Try to move the machine dependent bits into the target + files where they belong, avoid re-creating functions where or near + equivalents already exist (ie is_conditional_branch and friends), etc., etc. + + * Document the new scheduling options. Remove those options which are + not really useful (like reverse scheduling for example). In general + the haifa scheduler adds _way_ too many options. I'm definitely of the + opinion that gcc already has too many -foptions, and haifa doesn't help + that situation. + + * Testing and benchmarking. We've converted a few ports to using the + Haifa scheduler (hppa, sparc, ppc, alpha). We need to continue testing + and benchmarking the new scheduler on additional targets. + + We need to have some kind of docs for how to best describe a machine to + the haifa scheduler to get good performance. Some existing ports have + been tuned to deal with the old scheduler -- they may need to be tuned + to generate good schedules with haifa. + + + +Improvements to global cse and partial redundancy elimination: + +The current implementation of global cse uses partial redundancy elimination +as described in Chow's thesis. + +Long term we want to use lazy code motion as the basis for partial redundancy +elimination. lcm will find as many (or more) redunancies *and* it will +place the remaining computations at computationally optimal placement points +within the function. This reduces the number of redundant operations performed +as well as reducing register lifetimes. My experiments have shown that the +cases were the current PRE code hurts performance are greatly helped by using +lazy code motion. + +lcm also provides the underlying framework for several additional optimizations +such as shrink wrapping, spill code motion, dead store elimination, and generic +load/store motion (all the other examples are subcases of load/store motion). + +It can probably also be used to improve the reg-stack pass of the compiler. + +Contact law@cygnus.com if you're interested in working on lazy code motion. + +------------- + +The old PROJECTS file. Stuff I know has been done has been deleted. +Stuff in progress has a contact name associated with it. +has been 1. Better optimization. @@ -20,28 +72,6 @@ The difficulty is in finding a clean way for the RTL which refers to the constant (currently, only by an assembler symbol name) to point to the constant and cause it to be output. -* More cse - -The techniques for doing full global cse are described in the red -dragon book, or (a different version) in Frederick Chow's thesis from -Stanford. It is likely to be slow and use a lot of memory, but it -might be worth offering as an additional option. - -It is probably possible to extend cse to a few very frequent cases -without so much expense. - -For example, it is not very hard to handle cse through if-then -statements with no else clauses. Here's how to do it. On reaching a -label, notice that the label's use-count is 1 and that the last -preceding jump jumps conditionally to this label. Now you know it -is a simple if-then statement. Remove from the hash table -all the expressions that were entered since that jump insn -and you can continue with cse. - -It is probably not hard to handle cse from the end of a loop -around to the beginning, and a few loops would be greatly sped -up by this. - * Optimize a sequence of if statements whose conditions are exclusive. It is possible to optimize @@ -174,42 +204,8 @@ or outside of a particular loop where the variable is not used. (The latter is nice because it might let the variable be in a register most of the time even though the loop needs all the registers.) -It might not be very hard to do this in global.c when a variable -fails to get a hard register for its entire life span. - -The first step is to find a loop in which the variable is live, but -which is not the whole life span or nearly so. It's probably best to -use a loop in which the variable is heavily used. - -Then create a new pseudo-register to represent the variable in that loop. -Substitute this for the old pseudo-register there, and insert move insns -to copy between the two at the loop entry and all exits. (When several -such moves are inserted at the same place, some new feature should be -added to say that none of those registers conflict merely because of -overlap between the new moves. And the reload pass should reorder them -so that a store precedes a load, for any given hard register.) - -After doing this for all the reasonable candidates, run global-alloc -over again. With luck, one of the two pseudo-registers will be fit -somewhere. It may even have a much higher priority due to its reduced -life span. - -There will be no room in general for the new pseudo-registers in -basic_block_live_at_start, so there will need to be a second such -matrix exclusively for the new ones. Various other vectors indexed by -register number will have to be made bigger, or there will have to be -secondary extender vectors just for global-alloc. - -A simple new feature could arrange that both pseudo-registers get the -same stack slot if they both fail to get hard registers. - -Other compilers split live ranges when they are not connected, or -try to split off pieces `at the edge'. I think splitting around loops -will provide more speedup. - -Creating a fake binding block and a new like-named variable with -shorter life span and different address might succeed in describing -this technique for the debugger. +Contact meissner@cygnus.com before starting any work on live range +splitting. * Detect dead stores into memory? @@ -218,6 +214,10 @@ the same location; and, in between, there is no reference to anything that might be that location (including no reference to a variable address). +This can be modeled as a partial redundancy elimination/lazy code motion +problem. Contact law@cygnus.com before working on dead store elimination +optimizations. + * Loop optimization. Strength reduction and iteration variable elimination could be @@ -286,8 +286,9 @@ to the order in which to generate code for subexpressions of an expression. * More code motion. -Consider hoisting common code up past conditional branches or -tablejumps. +Consider hoisting common code up past conditional branches or tablejumps. + +Contact law@cygnus.com before working on code hoisting. * Trace scheduling. diff --git a/contrib/gcc/README b/contrib/gcc/README index 0923669..c606f65 100644 --- a/contrib/gcc/README +++ b/contrib/gcc/README @@ -1,10 +1,7 @@ -This directory contains the version 2.7.2.3 release of the GNU C +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. -The reason for the 2.7.2.3 release is to correct the support for GNU C -library version 2 on GNU/Linux systems. - The GNU C compiler is free software. See the file COPYING for copying permission. diff --git a/contrib/gcc/README-bugs b/contrib/gcc/README-bugs new file mode 100644 index 0000000..06e15bb --- /dev/null +++ b/contrib/gcc/README-bugs @@ -0,0 +1,144 @@ +The purpose of GCC pretesting is to verify that the new GCC +distribution, about to be released, works properly on your system *with +no change whatever*, when installed following the precise +recommendations that come with the distribution. + +Here are some guidelines on how to do pretesting so as to make it +helpful. All of them follow from common sense together with the +nature of the purpose and the situation. + +* It is absolutely vital that you mention even the smallest change or +departure from the standard sources and installation procedure. + +Otherwise, you are not testing the same program that I wrote. Testing +a different program is usually of no use whatever. It can even cause +trouble if you fail to tell me that you tested some other program +instead of what I know as GCC. I might think that GCC works, when in +fact it has not been properly tried, and might have a glaring fault. + +* Even changing the compilation options counts as a change in the +program. The GCC sources specify which compilation options to use. +Some of them are specified in makefiles, and some in machine-specific +configuration files. + +You have ways to override this--but if you do, then you are not +testing what ordinary users will do. Therefore, when pretesting, it +is vital to test with the default compilation options. + +(It is okay to test with nonstandard options as well as testing with +the standard ones.) + +* The machine and system configuration files of GCC are parts of +GCC. So when you test GCC, you need to do it with the +configuration files that come with GCC. + +If GCC does not come with configuration files for a certain machine, +and you test it with configuration files that don't come with GCC, +this is effectively changing GCC. Because the crucial fact about +the planned release is that, without changes, it doesn't work on that +machine. + +To make GCC work on that machine, I would need to install new +configuration files. That is not out of the question, since it is +safe--it certainly won't break any other machines that already work. +But you will have to rush me the legal papers to give the FSF +permission to use a large piece of text. + +* Look for recommendations for your system. + +You can find these recommendations in the Installation node of the +manual, and in the file INSTALL. (These two files have the same text.) + +These files say which configuration name to use for your machine, so +use the ones that are recommended. If you guess, you might guess +wrong and encounter spurious difficulties. What's more, if you don't +follow the recommendations then you aren't helping to test that its +recommendations are valid. + +These files may describe other things that you need to do to make GCC +work on your machine. If so, you should follow these recommendations +also, for the same reason. + +Also look at the Trouble chapter of the manual for items that +pertain to your machine. + +* Don't delay sending information. + +When you find a problem, please double check it if you can do so +quickly. But don't spend a long time double-checking. A good rule is +always to tell me about every problem on the same day you encounter +it, even if that means you can't find a solution before you report the +problem. + +I'd much rather hear about a problem today and a solution tomorrow +than get both of them tomorrow at the same time. + +* Make each bug report self-contained. + +If you refer back to another message, whether from you or from someone +else, then it will be necessary for anyone who wants to investigate +the bug to find the other message. This may be difficult, it is +probably time-consuming. + +To help me save time, simply copy the relevant parts of any previous +messages into your own bug report. + +In particular, if I ask you for more information because a bug report +was incomplete, it is best to send me the *entire* collection of +relevant information, all together. If you send just the additional +information, that makes me do extra work. There is even a risk that +I won't remember what question you are sending me the answer to. + +* Always be precise when talking about changes you have made. Show +things rather than describing them. Use exact filenames (relative to +the main directory of the distribution), not partial ones. For +example, say "I changed Makefile" rather than "I changed the +makefile". Instead of saying "I defined the MUMBLE macro", send a +diff that shows your change. + +* Always use `diff -c' to make diffs. If you don't include context, +it may be hard for me to figure out where you propose to make the +changes. I might have to ignore your patch because I can't tell what +it means. + +* When you write a fix, keep in mind that I can't install a change +that would break other systems. + +People often suggest fixing a problem by changing machine-independent +files such as toplev.c to do something special that a particular +system needs. Sometimes it is totally obvious that such changes would +break GCC for almost all users. I can't possibly make a change like +that. All I can do is send it back to you and ask you to find a fix +that is safe to install. + +Sometimes people send fixes that *might* be an improvement in +general--but it is hard to be sure of this. I can install such +changes some of the time, but not during pretest, when I am trying to +get a new version to work reliably as quickly as possible. + +The safest changes for me to install are changes to the configuration +files for a particular machine. At least I know those can't create +bugs on other machines. + +* Don't try changing GCC unless it fails to work if you don't change it. + +* Don't even suggest changes that would only make GCC cleaner. +Every change I install could introduce a bug, so I won't install +a change unless I see it is necessary. + +* If you would like to suggest changes for purposes other than fixing +serious bugs, don't wait till pretest time. Instead, send them just +after I make a release. That's the best time for me to install them. + +* In some cases, if you don't follow these guidelines, your +information might still be useful, but I might have to do more work to +make use of it. Unfortunately, I am so far behind in my work that I +just can't get the job done unless you help me to do it efficiently. + + + Thank you + rms + +Local Variables: +mode: text +End: diff --git a/contrib/gcc/README.DWARF b/contrib/gcc/README.DWARF index ac4719d..9745950 100644 --- a/contrib/gcc/README.DWARF +++ b/contrib/gcc/README.DWARF @@ -11,7 +11,7 @@ For general information about the DWARF debugging information language, you should obtain the DWARF version 1 specification document (and perhaps also the DWARF version 2 draft specification document) developed by the UNIX International Programming Languages Special Interest Group. A copy -of the the DWARF version 1 specification (in PostScript form) may be +of the DWARF version 1 specification (in PostScript form) may be obtained either from me or from the main Data General FTP server. (See below.) The file you are looking at now only describes known deviations from the DWARF version 1 specification, together with @@ -117,7 +117,7 @@ more of the formal parameter values, they may not have been "homed" yet, so you may get inaccurate answers (or perhaps even addressing errors). Some people may consider this simply a non-feature, but I consider it a -bug, and I hope to provide some some GNU-specific attributes (on function +bug, and I hope to provide some GNU-specific attributes (on function DIEs) which will specify the address of the end of the prologue and the address of the beginning of the epilogue in a future release. @@ -159,7 +159,7 @@ is required by the current DWARF draft specification. Specifically, the current DWARF draft specification seems to require that the type of an non-unsigned integral bit-field member of a struct or union type be represented as either a "signed" type or as a "plain" type, -depending upon the the exact set of keywords that were used in the +depending upon the exact set of keywords that were used in the type specification for the given bit-field member. It was felt (by the UI/PLSIG) that this distinction between "plain" and "signed" integral types could have some significance (in the case of bit-fields) because ANSI C diff --git a/contrib/gcc/README.g77 b/contrib/gcc/README.g77 new file mode 100644 index 0000000..f22f179 --- /dev/null +++ b/contrib/gcc/README.g77 @@ -0,0 +1,263 @@ +1998-08-11 + +This directory contains the egcs variant of version 0.5.24 of the +GNU Fortran compiler (g77). The GNU Fortran compiler is free software. +See the file COPYING.g77 for copying permission. + +Currently, two variants of g77 exist. One is the Free Software Foundation +(FSF) variant. The other is the egcs variant. As of egcs version 1.1, +these variants are kept fairly similar in most respects. Pertinent +differences, such as the layout of the source code, are specified below. + +Below, `[FSF]' denotes information applicable to only the FSF variant of +g77, while `[egcs]' denotes egcs-only information. + + +* IMPORTANT: Things you *must* do (or avoid) are marked with a * at the + beginning of the line in this file!!! + + +The email address to which bugs are to be reported is either +[FSF] or [egcs] . + +* *DO NOT* send any email (reporting bugs, asking questions, etc.) to + either of these addresses without *first* reading the g77 documentation. + Use `info', Info mode in GNU Emacs, or a text viewer such as `more' to + do this. + + The g77 documentation is in the source files named `g77.info', + `g77.info-1', `g77.info-2', and so on in the `f' subdirectory. If these + files are not present or you can't find them, contact the person or + organization that put together the g77 distribution you are using (probably + not the FSF or egcs), or ask your system administrator for help. + + +This README applies to only the g77-specific portions of the source-code +tree that contains it. These portions include: + + - The README.g77 and [FSF] COPYING.g77 files, in this directory, "this + directory" being [FSF] the top-level directory containing a g77 + distribution or [egcs] the gcc/ subdirectory of an egcs distribution. + + - The g77 front end, in the f/ subdirectory of this directory. + + - The libg2c library, in [FSF] the f/runtime/ subdirectory of this + directory or [egcs] the libf2c/ directory under the top-level + directory of the egcs distribution. + + +* To build g77, you must have a source distribution of [FSF] gcc + version 2.8 or [egcs] egcs version 1.1. Do not attempt to use + any other version of gcc or egcs, because this version of g77 is + designed to work with only those versions. + + Note that you must have *source* copies of the gcc or egcs distribution! + You cannot build g77 just using binaries of gcc or egcs. Also, unless + you are an expert, avoid using any distribution of gcc or egcs not + identical to the ones distributed by the FSF and Cygnus Support, + respectively. The primary FSF distribution site is: + + + + The primary egcs distribution site is: + + + + Both of these sites have approved mirror sites from which valid + distributions also may be obtained. + +* Do not attempt to combine the egcs version of g77 with the FSF + gcc distribution, or the FSF version of g77 with the egcs gcc + distribution. Although the differences are minor, they might + be sufficient to prevent g77 from building properly, or from + working properly if the build appears to succeed. + +[FSF] g77 is distributed as g77-/f/ so that unpacking the g77 +distribution is done in the normal GNU way, resulting in a directory having +the version number in the name. However, to build g77, the g77 distribution +must be merged with an appropriate gcc distribution, normally in a gcc +source directory, before configuring, building, and installing g77. + +[FSF] If you have just unpacked the g77 distribution, before proceeding, +you must merge the contents of the g77 distribution with the appropriate +gcc distribution on your system. + +* [FSF] Read and follow the instructions in f/INSTALL that + explain how to merge a g77 source directory into a gcc source + directory. You can use Info to read the same installation + instructions via: + + info -f f/g77.info -n Unpacking + +[FSF] The resulting directory layout includes the following, where gcc/ +might be a link to, for example, gcc-2.8.1/: + + gcc/ Non-g77 files in gcc + gcc/COPYING.g77 A copy of the GPL, under which g77 is licensed + gcc/README.g77 This file + gcc/f/ GNU Fortran front end + gcc/f/runtime/ libg2c configuration and g2c.h file generation + gcc/f/runtime/libF77/ Non-I/O portion of libg2c + gcc/f/runtime/libI77/ I/O portion of libg2c + gcc/f/runtime/libU77/ Additional interfaces to libc for libg2c + +[FSF] Applying g77 patches in the form of .diff files is done by typing +`patch -p1 -d gcc' (where gcc/ contains the f/ subdirectory). That is, +g77 patches are distributed in the same form, and at the same directory +level, as patches to the gcc distribution. (Note: make sure you're +using GNU patch, version 2.5 or later! Other versions of patch +have trouble with g77-related patches.) + +[egcs] The egcs version of g77 is distributed already merged with +the rest of egcs (such as the gcc back end). + +[egcs] The resulting directory layout includes the following, where egcs/ +might be a link to, for example, egcs-1.1/: + + egcs/gcc/ Non-g77 files in gcc + egcs/gcc/README.g77 This file + egcs/gcc/f/ GNU Fortran front end + egcs/libf2c/ libg2c configuration and g2c.h file generation + egcs/libf2c/libF77/ Non-I/O portion of libg2c + egcs/libf2c/libI77/ I/O portion of libg2c + egcs/libf2c/libU77/ Additional interfaces to libc for libg2c + +[egcs] Applying g77-specific patches to egcs is done the same way as +applying other egcs patches. + + +Below, `libf2c/' shall denote [FSF] gcc/f/runtime/ or [egcs] egcs/libf2c/, +while `f/' shall denote [FSF] the rest of gcc/f/ or [egcs] egcs/gcc/f/. + + +Components of note in g77 are described below. + +f/ as a whole contains the program GNU Fortran (g77), while libf2c/ +contains a portion of the separate program f2c. Note: The libf2c +code is not part of the program g77, just distributed with it. + +f/ contains text files that document the Fortran compiler, source +files for the GNU Fortran Front End (FFE), and some other stuff. +The g77 compiler code is placed in f/ because it, along with its contents, +is designed to be a subdirectory of a GNU CC (gcc) source directory, gcc/, +which is structured so that language-specific front ends can be "dropped +in" as subdirectories. The C++ front end (g++), is an example of this -- +it resides in the cp/ subdirectory. Note that the C front end (also +referred to as gcc) is an exception to this, as its source files reside +in the gcc/ directory itself. + +libf2c/ contains the run-time libraries for the f2c program, also used +by g77. These libraries normally referred to collectively as libf2c. +When built as part of g77, libf2c is installed under the name libg2c to avoid +conflict with any existing version of libf2c, and thus is often referred +to as libg2c when the g77 version is specifically being referred to. + +The netlib version of libf2c/ contains two distinct libraries, libF77 and +libI77, each in their own subdirectories. In g77, this distinction is not +made, beyond maintaining the subdirectory structure in the source-code tree. + +libf2c/ is not part of the program g77, just distributed with it. It +contains files not present in the official (netlib) version of libf2c, +and also contains some minor changes made from libf2c, to fix some bugs, +and to facilitate automatic configuration, building, and installation of +libf2c (as libg2c) for use by g77 users. + +* See libf2c/README for more information, including licensing conditions + governing distribution of programs containing code from libg2c. + +libg2c, g77's version of libf2c, adds Dave Love's implementation of +libU77, in the libf2c/libU77/ directory. This library is distributed +under the GNU Library General Public License (LGPL) -- see the +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 g77 are described below. + +f/BUGS lists some important bugs known to be in g77. Or: + + info -f f/g77.info -n "Actual Bugs" + +f/ChangeLog lists recent changes to g77 internals. + +libf2c/ChangeLog lists recent changes to libg2c internals. + +[FSF] f/INSTALL describes how to build and install GNU Fortran. Or: + + info -f f/g77.info -n Installation + +f/NEWS contains the per-release changes. These include the user-visible +changes described under "Changes" in the g77 documentation, plus internal +changes of import. Or: + + info -f f/g77.info -n News + +* All users of g77 (not just installers) should read f/g77.info* + as well, using the `more' command if neither the `info' command, + nor GNU Emacs (with its Info mode), are available, or if they + aren't yet accustomed to using these tools. Read f/BUGS and f/NEWS + plus, if you are planning on building or installing the FSF version + of g77, f/INSTALL, at the very least! All of these files are + readable as "plain text" files. + +* Also see for up-to-date information + regarding g77 bug reports, known bugs, bug-fixes, and new versions. + + +The rest of this file is of note to only those who wish to +debug, modify, or test the FFE (in conjunction with the gcc back end). + +If you want to explore the FFE code, which lives entirely in f/, here +are a few clues. The file g77spec.c contains the g77-specific source code +for the `g77' command only -- this just forms a variant of the `gcc' +command, so, just as the `gcc' command itself does not contain +the C front end, the `g77' command does not contain the Fortran front +end (FFE). The FFE code ends up in an executable named `f771', which +does the actual compiling, so it contains the FFE plus the gcc back end +(the latter to do most of the optimization, and the code generation). + +The file parse.c is the source file for main() for a stand-alone FFE and +yyparse() for f771. (Stand-alone building of the FFE doesn't work these days.) +The file top.c contains the top-level FFE function ffe_file and it (along +with top.h) define all ffe_[a-z].*, ffe[A-Z].*, and FFE_[A-Za-z].* symbols. +The file fini.c is a main() program that is used when building the FFE to +generate C header and source files for recognizing keywords. The files +malloc.c and malloc.h comprise a memory manager that defines all +malloc_[a-z].*, malloc[A-Z].*, and MALLOC_[A-Za-z].* symbols. All other +modules named are comprised of all files named *. and +define all ffe_[a-z].*, ffe[A-Z].*, and FFE_[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 grep patterns (such as they are). But it +does make it easy to find where a symbol is defined -- for example, +the symbol "ffexyz_set_something" would be defined in xyz.h and implemented +there (if it's a macro) or in xyz.c. + +The "porting" files of note currently are: proj.h, which defines the +"language" used by all the other source files (the language being +Standard C plus some useful things like ARRAY_SIZE and such) -- change +this file when you find your system doesn't properly define a Standard C +macro or function, for example; target.h and target.c, which describe +the target machine in terms of what data types are supported, how they are +denoted (what C type does an INTEGER*8 map to, for example), how to convert +between them, and so on (though as of 0.5.3, more and more of this information +is being dynamically configured by ffecom_init_0); com.h and com.c, which +interface to the target back end (currently only FFE stand-alone and the GBE); +ste.c, which contains code for implementing recognized executable statements +in the target back end (again currently either FFE or GBE); src.h and src.c, +which describe 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); and proj.c, which contains whatever code is needed to support +the language defined by proj.h. + +If you want to debug the f771 executable, for example if it crashes, +note that the global variables "lineno" and "input_filename" are 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 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 g77 until a fix is available.) + +Any questions or comments on these topics? Read the g77 documentation! diff --git a/contrib/gcc/SERVICE b/contrib/gcc/SERVICE index 11e266a..6404b7c 100644 --- a/contrib/gcc/SERVICE +++ b/contrib/gcc/SERVICE @@ -35,78 +35,243 @@ have nothing to go by. Please put each e-mail address inside "<>". Please put nothing else inside "<>". Thanks! For a current copy of this directory, or to have yourself listed, ask: - gnu@prep.ai.mit.edu + gnu@gnu.org ** Please keep the entries in this file alphabetical ** + +Alc?ve +12 place Indira Gandhi +92230 Gennevilliers +France + +http://www.alcove.fr +T?l.: +33 1 47 33 82 84 +Fax: +33 1 47 33 76 98 + +Alc?ve offers a comprehensive range of corporate-quality +Free Software related solutions, with technical support +via telephone, fax or email and remote system management. +We also offers consulting and training. +Rates approximately 3000FF per day, depending on the job. + +Updated: 1998-09-09  -Joseph Arceneaux -PO Box 460633 http://www.samsara.com/~jla -San Francisco, CA 94146-0633 -+1 415 648 9988 -+1 415 285 9088 +Altrasoft +4880 Stevens Creek Blvd., Suite 205 +San Jose, CA 95129-1034 ++1 408 243 3300 +http://www.altrasoft.com + +Altrasoft provides corporate-quality support, development and user +documentation for GNU Emacs, XEmacs and InfoDock. (InfoDock is a turnkey +information management and software development toolset built atop emacs, +written by one of our associates.) Emacs distributions for a variety of +platforms are also available, as is support for other emacs variants, such as +those often found on PCs. + +Our unique focus on emacs-related work allows us to attract expert talent in +this area to keep you on the leading edge of productivity, especially if you +do software development work. We do the porting, patching, coding, +integrating, debugging, documenting and testing so that your people spend +much more productive time on their mainline tasks. + +Standard support packages include help on all aspects of the packages +supported, including all tools shipped as a standard part of the original +package distribution. In general, we want to give you an unbelievably strong +level of support, so where we can, we will also answer questions concerning +any add-on Lisp code that is used at your site. Setup and customization +help, bug fixes, and announcements of new releases are, of course, included. + +Support rates start at $1,500 USD, for single user support for one year. +Discounts are available for group contracts. We also offer Golden Support +contracts for those who need the absolute best in mission-critical support; +contact us for details. Hourly development rates and fixed bid work are +available. + +Updated: 1997-05-12 + +Magnus Alvestad -Recently led the project making Wells Fargo Bank the first to provide -secure customer account access over the Internet. +GNU Emacs, GCC, the Unix tools, Linux, Jolt. -Former FSF staffmember. Performed X11 implementation of Emacs version -19, designed and implemented WYSIWYG Emacs. Installed and -administered FSF network. Maintainer of GNU indent. Over 15 years -experience with Unix and other systems, from writing ROM monitors to -UI design and system administration. +Rates: Free, or from $50/hour. + +Updated: 1997-05-09 + +AO UrbanSoft +St. Petersburg State University Science Campus +St. Petersburg, Russia +www.usoft.spb.ru + +AO UrbanSoft packages, markets and supports +industry standard free software products, +including the Linux operating system and +TeX document compiler. +The company also provides programming services +based on TeX, Tk, Python, HTML, Java, Perl and +Intranet. + +Rates approximately 15 USD per hour. + +Updated: 1997-05-25 + +Joseph Arceneaux +307 Chattanooga St. http://www.arceneaux.com +San Francisco, CA 94114 ++1 415 648 9988 + +I am a former FSF staffmember who made Wells Fargo Bank the first bank +to provide secure banking over the Internet. I have 20 years +experience with various computer systems. I performed the X11 +implementation of Emacs version 19, and designed and implemented +WYSIWYG features of Emacs. I also installed and administered FSF +network. Maintainer of GNU indent. I provide installation, porting, debugging and customization or -development of GNU and other Unix software. I also design and -implement free software projects and consult on software engineering -and systems design. Handholding and teaching services are also -available as well as things like LAN and compute--infrastructure design. +development of GNU and other software. I also design and implement +free software projects and consult on software engineering, security, +and intranet design. Time and material rates around $150 USD per hour, depending upon the particular job. I am also very interested in fixed-bid jobs. For selected non-profit organizations with worthy goals, I work for free. -Updated: 17Oct95 +Updated: 1998-06-24  -Gerd Aschemann +Dipl.-Inform. Gerd Aschemann Osannstr. 49 D-64285 Darmstadt Tel.: +49 6151 16 2259 -http://www.informatik.th-darmstadt.de/~ascheman/ +http://www.informatik.tu-darmstadt.de/VS/Mitarbeiter/Aschemann/ -- System Administrator (UNIX) at CS Department, TU Darmstadt, Germany -- 15 years expirience with CS, Systemadministration on different platforms -- 8 years with UNIX/Networking/FreeWare/GNU/X11 -- 6 years organizer of Operating Systems and Distributed Systems courses +- System Administrator (UNIX and NT) at CS Department, TU Darmstadt, Germany +- 18 years working in the CS field, System administration on different platforms +- 12 years with UNIX/Networking/FreeWare/GNU/X11 +- 9 years courses on Operating Systems and Distributed Systems - Lectures on System and Network Administration -- Platforms: Solaris, SunOS, Ultrix, OSF1, HP-UX, Linux, FreeBSD, AIX +- Platforms: Solaris, Linux, SunOS, Ultrix, HP-UX, Digital Unix, AIX, SCO, FreeBSDs +- Distributed Platforms and Information Systems (CORBA, WWW, Java) - Experience with parallel environments (Connection Machine, Meiko, Parsytec) -- Consultant for other UNIX users at TU Darmstadt +- Consultant -Rates are at 100,-- DM (~60 US$) per hour minimum, depending on the job. +Rates are at 150,-- DM (~85 US$) per hour minimum, depending on the job. I am willing to travel for sufficiently large jobs. -Updated: 17Oct95 +Updated: 1998-07-23 + + + Basis Technology Corp. + One Kendall Square, Bldg 200 + Cambridge, MA 02139 + U.S.A. + + Tel: +1-617-252-5636 + Fax: +1-617-252-9150 + E-mail: + Web: http://www.basistech.com + +Technical Expertise: + Multilingual software development + Internationalization and localization of software products + International character encodings, including Unicode, ISO-10646, + ISO-2022, ISO-8859-n, JIS, KSC5601, BIG5, GB2312 + Translation of technical materials into Japanese, Korean, and Chinese + including HTML, SGML, RTF, MIF, etc. + +GNU-related Services: + Custom internationalization and localization of GNU software, or + applications developed using GNU tools (GCC, G++, Emacs Lisp, etc.) + Custom multilingual application development based on MULE. + +GNU Contributions: + Organized 1992, 1993, and 1994 fund-raising seminars and lecture + tours for FSF in Japan. + Negotiated book royalty agreements with Japanese publishers on + behalf of the FSF. + Negotiated hardware contributions from Japanese PC vendors to + the FSF. + +Contacts: + Carl Hoffman, Steve Cohen, or Karen Watts + +Updated: 1998-07-23 + +Laurent Bernardin +16, rue Dicks +L-6944 Niederanven +Luxemburg + ++41 1 632 7469 + +Support and installation of all GNU software. + +Expertise: C, C++, Java, Motif, X, Unix administration, network security + +Rates: ~60 US$ / hour (Flux 2000.-) + +Updated: 1998-07-23  -Giuseppe Attardi -Dipartimento di Informatica -Corso Italia 40 -I-56125 Pisa, Italy -+39 50 887-244 +Dean Brettle Computer Consulting + + +http://www.brettle.com/ + +7485 Rush River Drive +Suite 710-193 +Sacramento, CA 95831 +916-422-8129 -GNU: help on obtaininig GNU, for italian sites. +I provide development, technical support, and training for free software +and open source systems including GNU/Linux, the GNU development suite, +Tcl/Tk, Emacs, and the GIMP. -Updated: 5Apr94 +I have over 9 years experience building and maintaining systems ranging +from computed tomography systems to airborne sensor control systems -- +all with free software. + +Rates range from $65.00/hr to $72.50/hr USD, depending upon work +location. I am also willing to work on fixed price contracts. + +Updated: 1998-07-07 + +Philip Brown + +(703) 893-8967 (prefer email) +Northern-VA, D.C. Area (world-wide via internet) +Rates: $45/Hr + extra for site visit; less for educational or charitable organizations + +Systems Supported: + + Sun boxes running Solaris 2.5-up + HP9000s running HP/UX 8.07 - 10.X + IBM RS6000 running AIX 3.2.X-up + Also SGI/Indy + +Software Supported: + Most all FSF (Gnu) software + esp. GCC, GDB, Emacs, Binutils, GS, et al... + +Statement: + I'd be more than happy to assist anyone in my area with acquiring, + installing, and configuring any FSF tools/utilities on any of the + above systems. I'm also willing to work with other UNIX systems not + listed above. In addition, I'm glad to share my many years of + experience with anyone having difficulty using or configuring these + tools. I've been installing and using them for about 5 years now + and I'll swear by their quality and the people/principles that made + them available. + + + Phil Brown + +Updated: 1998-07-23  James Craig Burley 97 Arrowhead Circle Ashland, MA 01721-1987 -508 881-6087, -4745 -(Please call only between 0900-1700 Eastern time, and only if you -are prepared to hire me -- ask me to help you for free only -via email, to which I might or might not respond.) -Email: --preferred-- - - +(Email and postal mail contacts only, please.) +Email: Expertise: Compiler Internals (author of GNU Fortran, for example) @@ -117,117 +282,280 @@ Expertise: Debugging (often asked to help debug Other People's Code) Documentation (authored many books and ran a few doc projects) Extensive experience with a variety of operating systems, hardware, - languages, and so on + languages, and so on -Rate: $70/hour -- willing to consider flat-fee arrangements +Rate: $100/hour -- willing to consider flat-fee arrangements -Updated: 14Aug95 +Updated: 1999-02-01  -Michael I. Bushnell -545 Technology Square, NE43-426 -Cambridge, MA 02139 -(617) 253-8568 +Thomas Bushnell, BSG +Becket House +66 Highland Ave. No. 8 +Somerville, MA 02143 +(617) 623-0654 All GNU software: Installation, customization, answering simple or - complex questions, bug fixing, extension. + complex questions, bug fixing, extension. -Experience: I have done Unix and GNU programming for several years, - I am the primary author of the Hurd (which provides most - kernel related facilities for the GNU OS). +Experience: I have done Unix and GNU programming for many years. + I am the primary author of the Hurd (which provides most + kernel related facilities for the GNU OS). I am easily available in the Cambridge/Boston area; work via email. I am willing to travel for sufficiently large jobs. -Rates: $100/hr, negotiable, less for non-profit organizaions. +Rates: $100/hr, negotiable, less for non-profit organizations. -Updated: 5Apr94 +Updated: 1998-07-27  -C2V Renaud Dumeur -82 bd Haussmann Michel Delval -75009 Paris Jean-Alain Le Borgne +C2V Michel Delval +82 bd Haussmann Jean-Alain Le Borgne +75008 Paris France -Tel (1) 40.08.07.07 -Fax (1) 43.87.35.99 +Tel (33 1) 40.08.07.07 +Fax (33 1) 43.87.35.99 +Compuserve 100413,1012 +http://www.c2v.com/freesoft.htm +e-mail: -We offer source or source+binary distribution, installation, training, -maintenance, technical support, consulting, specific development and -followup on the GNU software development environment: Emacs, gcc/g++, -binutils, gas, gdb. +Services: we offer source or source+binary distribution, +installation, training, maintenance, technical support, +consulting, specific development and followup on the GNU software +development environment: Emacs, gcc/g++, binutils, gas, gdb. -Experience: adapted gcc, gas and binutils to work as cross-development -tools for the Thomson st18950 DSP chip: GCC parser and typing system -have been augmented to allow the manipulation of variables located in -separated memory spaces. Porting on new platforms, and professionally -developing software with the GNU tools in the Unix/X11 environment -since they were first available. +Porting on new platforms, and professionally developing software +with the GNU tools in the Unix/X11 environment since they were +first available. + +Experience: GNU C Compilation toolchain for the SGS-Thomson D950 +and ST20 DSP chips. + +GNU C compilation toolchain (cross-compiler, compiler, linker, +assembler, debugger) for SparcV7 ERC32 based space systems +(Sextant Avionique / Alcatel Espace). + +Feasability study, analysis and prototyping of a complete +compilation toolchain based on the GNU programming tools for the +CSEM RISC microprocessor family. Rates: from 2000 FF/day to 150 000 FF/year, 40% discount for educational institutions, add taxes and expenses. Ask for list. -Entered: 5May94 - -Contributed Software -Graefestr. 76 -10967 Berlin, Germany -phone: (+49 30) 694 69 07 -FAX: (+49 30) 694 68 09 -modems: (+49 30) 694 60 55 (5xZyXEL ) -modems: (+49 30) 693 40 51 (8xUSR DS) -email: -internet: uropax.contrib.de [192.109.39.2], login as 'guest'. - -We distribute, install, port, teach and support free software -in general, i.e. X11, GNU, khoros etc. Rates are ECU 80,-- plus -tax per hour. We offer maintenance and support contracts for full -customer satisfaction. -Highlights are transparent development environments for multi-platform -sites and configuration management. Traveling is no problem. - -Free Archive login for downloading on above modem numbers. - -Updated: 5Apr94 - -Stuart Cracraft -25682 Cresta Loma -Laguna Niguel, Ca. -92677 -GNUline: 714-347-8106 -Rate: $75/hour +Updated: 1998-07-23 + +Bruce Dawson - +CodeMeta, Inc. +Manchester, NH USA +800-354-2209 + +Specializing in GNU tools such as guile, CVS, gnats, bash, gawk, fileutils... + +Services: + + o 800 phone support. + + o Modification and development. + + o Training. + +Rate: $75/hour or per quote. + +http://www.codemeta.com + +Updated: 1998-07-23 + +Kevin Cosgrove + + + I can help folks with porting & installation of many GNU + and X packages on a variety of Unix platforms. + + + My rates depend on the scope of each project but range + from $35 to $90 per hour. + +Updated: 1997-05-07 + +Couvares Consulting +1312 Chandler St. +Madison, WI 53715 +Phone: (608) 256-6901 +Email: +Contact: Peter F. Couvares + +Type of support: We offer phone/email support, installation, systems +integration, systems programming, training, and specialized consulting +services for free software in UNIX and NT environments. + +Sample prices: USD100/hour commercial, 50/hour non-profit, sliding +scale for individuals. + +Updated: 1998-07-23 + +Stuart Cracraft +P.O. Box 6752 +Laguna Niguel, CA, 92607, USA +Phone: 714-308-7900 +Website: http://home.earthlink.net/~cracraft/index.html +Rate: $50/hour, and as appropriate for the project. + Consultation topics: - Entire GNU suite - porting, compilation, installation, - user-training, administrator-training -Method: telephone line support, call-in via modem to your site, -or direct visit. - -Experience: supporting GNU since the mid-1980's, coordinator -of GNU Chess (original author), GNU Shogi, GNU Go. Ported GNU Emacs -to Solaris (System V Release 4). Expertise in C, Emacs Lisp, and Perl. -Customized programming also available. - -Entered: 5Apr94 - -Cygnus Support -1937 Landings Drive ...uunet!cygint!info -Mountain View, CA 94043 USA -+1 415 903 1400 voice -+1 415 903 0122 fax - -Cygnus Support -48 Grove Street -Somerville, MA 02144 -+1 617 629 3000 voice -+1 617 629 3010 fax - -Cygnus Support continues to provide supported, maintained versions of -the GNU toolset including GCC, G++, the GNU debugger with graphical -user interface, GNU linker, GNU macro-assembler and Emacs 19. In -keeping with the rapidly advancing needs of software developers, -Cygnus maintains a 90 day release cycle of the GNU toolset. Each -release is regression tested and includes substantial improvements and -additions to the existing matrix of over 65 supported platform -configurations. - -Updated: 2Feb95 +Entire GNU suite - porting, compilation, installation, +user-training, administrator-training. + +Method: via any combination of telephone, dialup, Internet, in-person, email. + +Experience: supporting GNU since project inception, original port of +GNU Emacs to Sun Solaris, original author of GNU Emacs online tutorial. +Expertise in C, Emacs Lisp, Perl, Expect, Oracle, Informix, SunOS, Solaris, +NIS, NFS, system-monitoring via paging. Unix System and Database +administration or development. Coordinator of the GNU mascots: GNU Chess, +GNU Shogi, GNU Go. + +Updated: 1998-07-23 + +Noel Cragg +6244 Aberdeen Av +Goleta CA 93117 +805-964-1892 + +I'll do installation, debugging, and extension of GNU tools on a +contract basis. CVS and configuration management are my current +specialties. Rate: $75/hour or per-project negotiated fee. + +Updated: 1998-07-22 + +Cygnus Solutions + +1325 Chesapeake Terrace +Sunnyvale, CA 94089 USA ++1 408 542 9600 voice ++1 408 542 9699 fax + +Cygnus Solutions provides supported and maintained versions of gcc, g++, gdb +with GUI, GNU linker and GNU macro assembler. In addition, Cygnus provides +these GNU software development tools for well over 100 host-target +configurations. Support includes bug fixes and semi-annual releases of the +toolset. Each release is regression tested and includes substantial +improvements and additions to the current release. Support is available for +groups of 5 or 25 on a wide range of standard, special and vintage +toolchains for native and embedded applications. New target processors are +being added regularly. Rates for support for standard products start at $7495. + +Cygnus Solutions contacts: + + Kathy Powers + ph: +1-206-888-6002 + fx: +1-206-888-6145 + email: + + + Erik Westcott + ph: +1 408 542 9637 + fx: +1 408 542 9699 + email: +Updated: 1997-09-02 by rms + +Marcus G. Daniels +1399 Hyde Park Road +Santa Fe, NM 87501 +(505)984-8800 x267 + +I can customize, extend, port, and repair many types of free software. +I have software maintenance experience (e.g. CLISP, Swarm), and have +contributed to several GNU packages (e.g. Emacs). Twelve years of C +and Unix experience. Consulting rates start at $60 US/hr. + +Updated: 1998-07-22 + +DSS Distributed Systems Software, Inc. +7500 Abercrombie Dr., Suite 103 +Richmond, British Columbia V6Y 3J9 http://www.dss.bc.ca +CANADA (604) 270-9559 + +GNU-related services: + We specialize in support for GCC (mainly C and C++), including porting, + retargeting, and customizing. + Also, GNU and other free software that falls within our areas of expertise. + +Expertise: + DSS provides software design, implementation, and consulting services. + + Distributed systems: + o Client/Server architectures, computer networking, communication +protocols + o Directory systems, including X.500 and LDAP + o High-performance and special-purpose distributed systems and databases: + scalability, reliability, availability, transactions + o Computer systems performance analysis + + Compilers, translators, and interpreters, including "small" and + special-purpose languages + +Rates: + Consulting rates are $85-$300 (Canadian dollars) per hour, plus + applicable taxes. Fixed-cost projects are also possible. + +Updated: 1998-06-24 + +Echo Labs +29 Weld St, http://www.iinet.net.au/~echo/ +Nedlands, WA 6009 +Perth, Australia ++61 (0) 41 985 9603 + +Echo Labs is a software consultancy that also provides support and +development skills. Specialising in GNU software, particularly Tcl/Tk +and Linux. We can deliver systems at a fraction of the cost of those +based on more traditional technologies. Internet/intranet and data +communications solutions, for all platforms are undertaken. GUI +front-ends done quickly. + +While typically involved in engineering and technical areas, any +GNU/Open Source software will be supported. + +For further details see: http://www.iinet.net.au/~echo/ + +Experience: 13+ years C/Unix, Sun, SCO, Linux, Win/NT. + Secure WWW servers (Apache SSL), Ecommerce solutions. + Systems programming, device drivers, hardware interfacing. + GNU tools/utilities, Embedded & realtime systems. + Communications protocols and implementation. + +Degrees: BAppSc (CS), Curtin University, Perth + +Rates: AUS $50-75/hr neg. + +Updated: 1998-07-23 + +Andrew Ford +Ford & Mason Ltd. http://www.ford-mason.co.uk/aford/ +South Wing, Compton House Tel: +44 1531 829900 +Compton Green, Redmarley Fax: +44 1531 829901 +Gloucester, United Kingdom + +Experience: + * 18 years in the computer industry + * 14 years Unix/C programming experience + * 10 years experience with GNU software + * 4 years web experience (author of the first book about setting up a web site) + +Services offered: + * Installing and customizing GNU and other free software + * GNU Emacs customization and emacs lisp coding + * Perl module development + * TeX and LaTeX macro development + * software development (especially in Perl, C, C++) + * web site setup (with Apache) + * web application development with mod_perl + * translation (German -> English) + * writing documentation + +Rates: + around 60 pounds/hour (approx US$80/hour) plus expenses + less for charities and non-profit organization + +Updated: 1998-06-24  Free Software Association of Germany Michaela Merz @@ -249,33 +577,33 @@ organizations : 40 US$ / hour ert (24h Emergency response team) : 300 US$ / hour -Entered: 14Apr94 +Entered: 1994-04-14  -Noah Friedman -Building 600, Suite 214 2002-A Guadalupe St. #214 -One Kendall Square Austin, TX 78705 -Cambridge, MA 02139 (Local, faster to reach me) -(Permanent) - +Noah Friedman +4463 Moraga Avenue +Oakland, CA 94611 +(permanent) -Author of several Emacs Lisp packages and parts of Emacs 19, as well as -numerous utilities written in shell script and perl. Co-maintained GNU -Texinfo and Autoconf for a couple of years. System administrator for a -network of heterogenous machines. FSF employee Feb 1991--Sep 1994. +Author of several Emacs Lisp packages and parts of Emacs, as well as +numerous network and unix system utilities. Co-maintained GNU Texinfo and +Autoconf for a couple of years. Experienced unix systems engineer. +FSF employee Feb 1991--Sep 1994. I can perform installation, porting, and enhancement of all GNU software -and any other free software; system administration for unix-type systems -and ethernet networks; and I am willing to teach shell programming and -Emacs Lisp. +and any other free software, especially for Linux/GNU systems; design +high-capacity hardware-redundant servers for production environments; +provide consulting on the use of version control management with CVS; and I +am willing to provide handholding for shell programming and Emacs Lisp +development. -Fees negotiable, averaging $60-$75/hour. I can work in the Austin, TX area -or anywhere accessible on the Internet. For larger jobs I may be willing -to travel. +Fees negotiable, averaging $100-$150/hour. I can work in the California +bay area or anywhere accessible on the Internet. For larger jobs I may be +willing to travel. -Updated: 16Aug95 +Updated: 1998-06-24  Ronald F. Guilmette -Infinite Monkeys & Co. +RG Consulting 1751 East Roseville Pkwy. #1828 Roseville, CA 95661 Tel: +1 916 786 7945 @@ -315,243 +643,564 @@ Other qualifications: Rates: Variable depending upon contract duration. Call for quote. -Updated: 23Sep95 - -Hundred Acre Consulting -1155 W Fourth St Ste 225 -PO Box 6209 -Reno NV 89513-6209 -(702)-348-7299 -Hundred Acre is a consulting group providing support and development -services to organizations of all sizes. We support GNU C++ and C in -particular, but also provide support for all other GNU software and -certain non-GNU public domain software as well. We work on a "service -contract" basis for support -- for a yearly fee, we provide multiple -levels of email and toll free telephone support, and free updates and -bug fixes. The highersupport levels have on-site support. Development -is charged on either an hourly or fixed bid basis. - -Consulting rates: $70 to $90 per hour, or fixed bid. -Support contracts: Several levels, from $495 to $90000 per year. - -Updated: 27Dec94 - -Interactive Information Limited - -Interactive Information Limited is an Edinburgh-based company that -specialises in WWW services and support for using the Internet for -marketing. - -Our staff have many years experience in using, and developing lisp packages -within, Emacs, and in using other GNU/Unix tools, particularly under public -domain UNIXes. - -We can provide services throughout the UK, at any level from general -consultancy through fetching, installing and customising software to -bespoke programming. Fees would be in the range #300 - #600 per day, -depending primarily on the size of the job. - -You can contact us - by email: - by phone: 0370 30 40 52 (UK) - (+44) 370 30 40 52 (International) - by post: 3, Lauriston Gardens, - Edinburgh EH3 9HH - Scotland - -Entered: 13Nov95 - -Scott D. Kalter +Dallas, Texas USA + +Entire GNU suite - porting, compilation, installation and maintenance +Platforms: Any unix variant (AIX, *BSD, Digital Unix, HP/UX, GNU/Linux, +Solaris, SunOS, et al) + +Method: Call-in via modem to your site, telnet, or on-site. + +Rates: US $0-75/hour depending upon client requirements -Qualifications: BS Math/CS 1985: Carnegie Mellon University - MS CS 1988: UCLA +Note: If you are an individual installing GNU software on your personal Linux +system, or are a non-profit organization, my hourly rate for you is simple: +FREE. You just have to pay for the phone calls and/or travel/lodging, if any is +required. - Very familiar with all levels of elisp programming. Taught - Emacs use and customization in universities and industry. Extensive - troubleshooting and user support experience. Co-developed an - object-oriented extension to Elisp that can be used for - projects. Extensive Elisp level modification for rapid - prototyping of designs used in groupware research. This - includes the development of an infrastructure to support - multiple, communicating Emacs processes. +Experience: I've used, supported and maintained GNU software on numerous unix +systems since 1989. -Updated: 6Apr94 +I have extensive experience in C, Emacs Lisp, Perl and general unix systems. + +Updated: 1998-06-24  -KAMAN SCIENCES CORPORATION -258 GENESEE STREET -UTICA NY 13502 -(315) 734-3600 +Michael P. Deignan +Ideamation, Inc. +136 Nelson Street +Providence, RI 02908 +(401) 331-3708 +(401) 272-6449 fax. -CONTACTS: Alan Piszcz (peesh) - : Dennis Fitzgerald +Rate: Varies depending on complexity of task. + Hourly and fixed-rate contracts are available. +Programs Supported: All +Updated: 1998-07-23 + + Interactive Information Limited is an Edinburgh-based company that + specialises in WWW services and in particular support for accessing + existing systems and information. + + Our staff have many years experience in using, and developing lisp packages + within, Emacs, and in using other GNU/Unix tools, particularly under public + domain UNIXes. + + We can provide services throughout the UK, at any level from general + consultancy through fetching, installing and customising software to + bespoke programming. Fees would be in the range #300 - #600 per day, + depending primarily on the size of the job. + + You can contact us + by email: + by phone: 0370 30 40 52 (UK) + (+44) 370 30 40 52 (International) + by post: 3, Lauriston Gardens, + Edinburgh EH3 9HH + Scotland + +Updated: 1998-07-24 + +Kaman Sciences Corporation +Griffiss Business & Technology Park +775 Daedalian Drive +Rome, NY 13441-4909 +(315) 334-4900 + +CONTACTS: + Dennis Fitzgerald + Tom Robbins + Kaman Sciences has performed a GNU port for a custom RISC processor. We have experience in the definition and description of the machine register transfer language to the GNU tool-set. This includes rewriting and modification of the necessary description and source files of gcc, gas, and gld and other binutils. Kaman also has services for installation and setup of GNU tools, (GAWK, GCC, EMACS, etc.) on Sun workstations. - + Work is on a "service contract" basis and development is charged either hourly or as a fixed price contract. - -Consulting rates: $70 to $200 per hour. - -Entered: 13Jan95 + +Consulting rates: $70 to $175 per hour. + +Updated: 1997-05-07  -Scott J. Kramer -P.O. Box 620207 -Woodside, CA 94062 -+1 415-941-0755 +Joseph R. Kiniry +Caltech Mailstop 256-80 http://www.cs.caltech.edu/~kiniry/ +Pasadena, CA 91125 +Phone: 626-395-4840 +Fax: 626-792-4257 + +Long-term high-level consultant with four advanced degrees in a +variety of domains. See http://www.cs.caltech.edu/~kiniry/resume.html +for more information on professional and academic background. + +I provide installation, porting, debugging, customization, design, and +development of GNU and other UNIX and non-UNIX software. I am or have +been a certified developer with Microsoft, SunSoft, NeXT, and Amiga. +I have a great deal of development and management experience and an +extremely broad background which contributes to my excellent system +integration capabilities. I have a special expertise and conduct +research in distributed systems and component/object technologies. + +Time and material rates for local work vary regionally, but are +currently $250 per hour on the west coast. Other rates apply for +long-term jobs (day rates, travel, etc.) and remote work (usually 1/2 +fee). I am interested in fixed-bid jobs and will work for lower rates +for non-profit organizations and educational institutions. + +Updated: 1998-08-27 + +Bradley M. Kuhn + +http://www.ebb.org/bkuhn -GNU Software: Tutoring, installations/upgrades, Emacs Lisp customizations, - general troubleshooting/support. Prefer that work I do - becomes part integrated into official Free Software Foundation - distributions. +I am available for Unix system administration and software development +consulting, including but not limited to installation, configuration and +integration of GNU tools and other copy-lefted software such as GNU/Linux +and the various distributions of GNU/Linux. -Systems Administration: Sun (SunOS & Solaris) and SGI (IRIX) - UNIX hardware/software platforms. +Please visit my homepage for more information on my background and skills. My +resume is also available there. -Rate: Task- and time-dependent; non-monetary offers accepted. +I am available for both 1099 (preferred) and W2 on-site contracting in the +Cincinnati, OH, USA metropolitan area, as well as remote consulting via dialup +or Internet connection anywhere in the USA. I have no interest in permanent +relocation at this time. -Updated: 12Apr94 - -Fen Labalme +CoMedia Consulting http://www.comedia.com/ +142 S. Lake Merced Hill WE ARE EVERYWHERE +San Francisco CA 94132 JUST SAY "KNOW" Consulting, installation, customization and training for GNU Emacs, -and selected other GNU & network software (but not G++). I have been -hacking Emacs since '76 when it was TECO and ^R macros (don't ask). +and selected other GNU & network software. Design & implementation +of free software projects, as well as software engineering & system +design. I have been hacking Emacs since '76 when it was TECO and ^R +macros (don't ask), and am inter/intra-network, UNIX & Web friendly. + +Rates: $150 hour & up, depending; flat rate jobs considered. + Lower rates, barter or free for selected non-profits. -Updated: 6Apr94 +Updated: 1998-06-24  Greg Lehey LEMIS -Schellnhausen 2 -36325 Feldatal -Germany +PO Box 460 +Echunga SA 5153 +Australia -Phone: +49-6637-919123 -Fax: +49-6637-919122 -Mail +Phone: +61-8-8388-8250 +Fax: +61-8-8388-8250 +Mobile: +61-41-739-7062 +Mail Services: Supply, porting, installation, consultation on all GNU products. -Experience: 20 years OS and compiler experience, portations of most -GNU products. Author of ported software CD-ROM for Unix 4.2. +Experience: 25 years OS and compiler experience, ports of most GNU +products. Author of ported software CD-ROM for UNIX System V.4.2, +"Porting UNIX Software" (O'Reilly), "Installing and Running FreeBSD" +and "The Complete FreeBSD" (both Walnut Creek). + +Rates: Choice of AUD 180 per hour or hotline rates AUD 3 per minute. +Outside Australia, $US 100 per hour or $US 2 per minute. Quick +questions may be free. Limited free support available for +purchasers of LEMIS CD-ROMs. + +Updated: 1998-08-26 + +Alan Lehotsky +Quality Software Management +634 West St +Carlisle, MA 01741 + +Phone: (978)287-0435 +Fax: (978)287-0436 + +Services: + - Support for GNU compilers, including rehost/retarget + - General system software work (SW tools, O/S, device drivers) + - runtime library (especially floating point) + - project management + - software process improvement + +Experience: 15+ years of design and implementation of optimizing + compilers. "Mr. Bliss" at Digital in the 70's and early + 80's. Experience with Motorola 68k, PowerPC, SPARC, x86, + NS32K, ADI SHARC DSP. Compilers for languages including + Ada, BLISS, C, C++, FORTRAN, Pascal, Modula/2, O/S + experience includes Unix (OSF/1, SunOS, Solaris, AIX, HP/UX), + VAX/VMS, Windows/NT, MacOS. + + 4 years experience with GCC internals, including major + changes to support 8 bit bytes on word-address SHARC DSP. + +References available -Rates: Choice of DM 150 per hour or hotline rates 3 DM per minute + 10 -DM per phone call. Quick questions may be free. Limited free support -available for purchasers of LEMIS CD-ROMs. +Rates: $100/hr + fixed price possible for well-defined deliverables -Updated: 21Feb95 +Updated: 1998-06-24  -Marty Leisner -332 Shaftsbury Road -Rochester, New York 14610 -Home:(716) 654-7931 +Rohan Lenard +32 Holtermann St. +Crows Nest, NSW 2065 +AUSTRALIA ++61 411250024 -Experience: 12 years C/Unix, 7 years DOS. - Extensive experience with GNU binary tools, cross-compilers, - embedded/hosted systems, realtime. -Degree : BS CS, Cornell University -Rates: $75/hr +* The human face behind the bug-g++@gnu.org mailing list - known + in the past as and - now + known as . +* Interested in providing first line support and development. +Experience: 10+ years C/Unix, 6+ years C++ + Extensive experience with GNU tools, cross-compilers, + embedded/hosted systems, realtime, simulations, + and military software. -marty - +Degrees: BSc (CS), BE (Comms), University of Melbourne -Updated: 15Apr94 +Rates: AUS $75+/hr neg. + +Updated: 1997-05-17 + +Reuven M. Lerner +17 Disraeli Street +Haifa 34333 +Israel + +Phone: 04-824-2265 (within Israel) + +972-4-824-2265 (outside of Israel) + +Fax: 04-826-1219 (within Israel) + +972-4-826-1219 (outside of Israel) + +WWW: http://www.netvision.net.il/php/reuven + +- System and network administration, especially Linux-based systems + and networks +- Administration, training, and programming for Internet nodes and + World-Wide Web sites +- Installation, support and training in the use of Linux, Emacs, Perl, + and other free software +- Expertise in C, Emacs Lisp, and Perl + +Consulting rates: $75/hour, less for educational institutions. + +Updated: 1998-06-24  Richard Levitte (in TeX: Richard Levitte -Södra Långgatan 39, II S\"odra L{\aa}nggatan 39, II -S-171 49 Solna S-171 49 Solna +Levitte Programming Levitte Programming +Spannvagen 38, I Spannv\"agen 28, I +S-168 35 Bromma S-168 35 Bromma Sweden Sweden) -Tel.nr.: +46 (8) 18 30 99 (there is an answering machine) -e-mail: (preferred) - +Tel.nr.: +46 (8) 26 52 47 (there is an answering machine) +Cellular: +46 (10) 222 64 05 +e-mail: What I do: - Primarly I work on GNU software for VMS, both VAX and AXP. I - also work on GNU stuff for Unix on occasion. I'm familiar with - SunOS (version 4.x.x), BSD (version 4.2 and up), - Ultrix (version 4.2 and up). - I've been porting GNU Emacs to VMS since spring 1991. This - includes versions 18.57 to 18.59 and version 19.22. - I maintain GNU vmslib. + Primarily I work on GNU software for VMS, both VAX and AXP. I've + been porting GNU Emacs to VMS since spring 1991. I've ported a + bunch of other GNU programs as well. I maintain GNU vmslib. + For further info, see http://www.lp.se/~levitte/prof/resume.html Programs supported: - GNU vmslib: extending, installation, upgrading aid, - simple and complex questions, you name it. - GNU Emacs: porting, extending, installation, upgrading aid, - customization, simple or complex questions, - training, you name it. - GNU autoconf: porting, extending, installation, upgrading aid. - GNU zip, diffutils, m4, patch, texinfo: - porting, installation, upgrading aid. - GNU C/C++: installation, upgrading aid. I might start to - hack at it some day. - -The list of programs I currently support represents both my interests and -current priorities. Your interest and funding can influence my priorities. + To a varying degree (ranging from extension and porting to + installation and simple questions) at the time of updating this + entry: + - GNU vmslib, emacs, autoconf, zip, diffutils, m4, patch, texinfo, + C/C++; on both VMS and Unix. + - Other GNU programs to a small degree; on Unix. + For further info, look at http://www.lp.se/products/gnu.html Experience: - Fluent in C, C++, Emacs Lisp, Pascal as well as assembler - on VAX, Motorola 680x0, Intel 8086 and 80x86. Modified key - elements in Emacs (e.g., memory and process management) to work - transparently on VMS. I have very good knowledge in the VMS - operating system, as well as MS-DOS and IBM PC compatibles. - I have worked for four and a half years as a VMS system manager. - I've also provided consulting services on IBM PC compatibles, - as well as held classes for IBM PC users. - A reference list is available on request. + Fluent in TeX/LaTeX and many programming languages. + Modified key elements in Emacs (e.g., memory and process management) + to work transparently on VMS. I have very good knowledge in the VMS + operating system. I'm also knowledged in the a few Unix flavors. + For further info, see http://www.lp.se/~levitte/prof/resume.html Your Rate: - $50-$80/hour (400-700 SEK in sweden), plus expenses. My rates + $70-$100/hour (500-800 SEK in sweden), plus expenses. My rates are negotiable, depending on how interesting the project is to me. +Updated: 1997-05-08 + +Sean Levy +352 Roup Ave http://www.StAlphonsos.COM/~attila/ +Pittsburgh, PA 15232 +1.412.361.7802 +USA + +I have been a professional hacker for over 15 years, and have worked on +everything from PDP-10's and -11's and early microcomputers to modern Unix +workstations of various kinds, at all levels. I've done every kind of +hacking, in many different languages (including some I designed and +implemented). Current efforts are focused on Linux, GNU software, WWW-based +systems, and security. My resume and PGP key are available via my web +pages. + +Based in Pittsburgh, PA, available anywhere via the Internet. Possibility +of travel for some jobs. Speak Spanish, have traveled in Europe and +Scandinavia. + +Rates: $100 USD/hour standard, lower for non-profits or other worthy causes, + $200 USD/hour for pager access and 24-hour support + +Updated: 1998-06-24 + +Lexa Software info@lexa.com +1590 The Alameda, Suite 102 +San Jose, CA 95126 + ++1 800 278-2040 ++1 408 278-2043 voice ++1 408 278-2045 fax -Entered: 18Aug94 +http://www.lexa.com + +Lexa Software provides support for GNU C/C++ including the GNU debugger +and linker. Lexa has extensive experience supporting GCC/G++ on SNI +and Pyramid as well as all other MIPS ABI platforms. We offer support +to 2, 5, 25 and larger number of users via phone, email, ftp. + +Updated: 1997-05-01  -Roland McGrath -545 Tech Sq, Rm 426 -Cambridge, MA 02139 -Work: (617) 253-8568 +Gord Matzigkeit +#15, 2105 Cornwall Street http://www.fig.org/~gord/ +Regina, Saskatchewan S4P 2K8 Voice: (306) 522-7884 +CANADA -Co-author of GNU Make (with Richard Stallman); maintainer of GNU Make. -Author and maintainer of the GNU C Library and co-author of the GNU Hurd. -Author of several GNU Emacs Lisp packages and parts of GNU Emacs 19. -FSF employee summer 1989, fall 1990 to the present. +I will gladly help novice and intermediate computer users to install, +understand, and use free software, whether or not I have prior +experience with that software. I know my limitations well, and will +freely give other contacts if I cannot solve your problem myself. -Installation, maintenance, porting, enhancement of all GNU software. I can -install GNU software and maintain its installation on call via the Internet. +I have over 3 years of experience with several of the major free OSes: +Linux/GNU (Red Hat, Debian, Slackware), NetBSD, FreeBSD, and GNU/Hurd. +Some of my specialties are networking, Emacs, Automake, Autoconf, C, +Perl, and shell script programming. -Fees negotiable; $75-$100/hour, higher for very short term projects. I can -work anywhere in the Boston or SF Bay Area, or anywhere on the Internet. I -am working full-time for the FSF on the GNU Hurd, so I am likely to take on -only jobs that either can be done entirely via the Internet and are -short-term, or that are very interesting. +My rates are negotiable depending on the task: usually $10-$40 +(Canadian) per hour. -Updated: 21Jan95 +Updated: 1998-10-19 + +Andrew McCallum +6623 Dalzell Place +Pittsburgh, PA 15217 +Home: (412) 422-0688 + +http://www.cs.rochester.edu/u/mccallum + +Services: Support, enhancements, new development in: + GNU Objective C + GNUstep, both graphical and non-graphical. + GNUstep Base Library: libgnustep-base + (especially Distributed Objects) + Interface between Objective-C and Guile or TCL: libguileobjc. + +Experience: 10+ years of UNIX experience. + Programming for NeXTSTEP since version 0.8, 1988. + MA and PhD in Computer Science. + Extensive work on GNU Objective C Runtime. + Author of GNUstep Base Library, including Distributed Objects + FSF Chief Maintainer of the GNUstep Project. + Contributor to GCC, Emacs, Guile. + C, Objective-C, Postscript, Scheme, Lisp, ELisp, Linux. + English and Francais. + +Rates: $90-$150 / hour, negotiable, depending on many variables. + +Updated: 1997-05-07 + +Mark P. Mitchell +3421 El Camino Real #35 +Atherton, CA 94027 +(650) 364-5360 +http://home.earthlink.net/~mbmitchell/consulting.html + +Experience +---------- +I am an experienced software engineer, with particular expertise in +the field of programming tools. I am responsible for the +implementation of member templates in currently available versions of +G++ as well as many other G++ bug-fixes, and continue to work actively on +improving G++. + +I am willing to work on any and all projects involving free software. + +Please see my resume at the above URL for further information on +my experience and qualifications. + +Rates +----- +My standard rate is $125/hr, but I am willing to negotiate flat fees, and +discounts for deserving organizations. + +Updated: 1998-02-13 + +NET-Community +526 NW 21st, #48 http://www.net-community.com +Portland, OR 97209 USA +1-503-279-8845 voice + +NET-Community provides support for the complete GNUstep toolset +including the Objective-C runtime within GCC, the GNUstep Base Library, +the Display Ghostscript system, the GNUstep GUI Library, the GNUstep +X/DPS GUI Backend, and the GNUstep Database Library. NET-Community also +provides support for its own MediaBook software including the MediaBook +Random Library and the MediaBook Speech Synthesis Library. +NET-Community actively supports and develops free software on all +GNUstep platforms; a portion of the proceeds, usually 20%, generated +from CD-ROM sales go towards additional development and enhancement of +GNUstep. + +Updated: 1998-09-08 + +Thi Nguyen +San Jose, CA, USA +1 408 314 3470 + +Expertise: Hardware Verification Tools and Environment + - simulators / transactors / stimulus generators + - scripts of all sorts / environment / flows + - elisp customizations + - speak: C, C++, elisp, Scheme, Perl, Verilog, sh + +Please see ftp://ftp.netcom.com/pub/tt/ttn/resume.html for resume. + +Rate: $100/hr, possibly less + +Updated: 1998-06-24 + +Peter Olsen +P.O. Box 410 +Simpsonville, MD 21150 + +pcolsen@acm.org + +What I do: Mathematical modeling and model building using Gnu + and other Free Software. Scientific and engineering + analysis, modeling, and programming in FORTRAN, C, LISP, + Java, and Smalltalk. Statistical analysis. + Emacs customization. + +Examples of my previous work: + 1. I built the model used predict the + amount of work required to clean up the Exxon Valdez oil + spill. Model was completed in ten days, used to allocate + resources for $2 billion summer cleanup, predictions were + accurate. + 2. I built a model applying commercial capital + investment standards to a Federal Agency budget, helped + support $250 Million budget increase. + +Credo: Engineering is the art of applying a professional + knowledge of mathematics and the physical sciences to + improve the quality of life. + +Rates: $225/hour (+ travel and expenses) on site, + $175/hour remote access. + +Notes: 1. Visiting Lecturer for Society for Industrial and Applied + Mathematics: Will speak without fee about Valdez model + (or other work) to Educational and not-for-profit + organizations (plus most-economical travel and living + expenses or travel or living arrangements in kind). + + 2. I do not accept offers which pose even the appearance + of conflict of interest with any present or former client + or employer. + +Updated: 1998-06-24 + + Open Systems Consultants a.s Open Systems Consultants a.s + St. Olavsgt. 24 Fabrikkvn 8 + N-0166 OSLO N-4033 FORUS + NORWAY NORWAY + + +Phone: Fax: + +47 22 20 40 50 +47 22 20 02 85 + +Web: E-mail: + http://www.osc.no + +Open Systems Consultants a.s can provide programming support for all +GNU software -- extending or adopting it to meet customer needs. +Prices vary with software and project. Hourly fees are in the $80-120 +range. Fixed-priced projects are also available. Phone support is +available only for customers with support contracts. + +Updated: 1998-08-26 + +Francesco Potorti` +Via S.Stefano, 8 +56123 Pisa, Italy +Tel. (050)560671 + +Emacs: installation and maintenance, training and tutorials, + customisation, extensions, troubleshooting. Author of some of + the packages in the emacs distribution, has made the porting + of emacs to the Motorola Delta architecture. + +Other: installation and maintenance of GNU software. Experience with + hylafax, RCS, gperf, etags, smail, indent, diff, gawk, gcc, + screen. Is the current maintainer of etags. + +Rates: 30-80 KL/hr, depending on experience on the particular task. + Average is 50 KL/hr $50/hr. + Prefer e-mail communication to telephone. + +Qualifications: Electronic Engineering degree, Pisa. Full time + researcher in CNUCE-CNR. + Familiar with elisp programming and porting of C programs. + +Updated: 1998-08-26 + +Dipl.-Inform. Klaus K?mpf +L?hnerstrasse 14 +D-90491 N?rnberg +Germany + +- 15 years C/Unix experience +- 6 years VMS experience +- Ported BFD library, Binutils, GNU Assembler, GNU C, GNU C++, + GNU C++ libraries, and GNU Make to openVMS/Alpha. + +I do a lot of cross-platform (Unix/Linux-OpenVMS-WindowsNT) development +mostly with the GNU compiler environment. I am actively supporting GNU +software on OpenVMS/Alpha and OpenVMS/VAX. + +Updated: 1998-08-26 + +Quiotix Corporation +Menlo Park, CA + +Contact: Jeffrey Siegal + jbs@quiotix.com + 415 324-0535 + +Area of focus: Embedded systems--using GNU software to develop for +embedded systems, porting GNU software to embedded systems, extending GNU +software to better support embedded environments, developing new tools and +utilities for embedded development using GNU software. + +Services: porting, development, support, project management, advisory +consulting. + +Rates: $125-$250/hour or fixed fees depending on services provided. + +Updated: 1997-05-16  Wolfgang S. Rupprecht 47 Esparito Ave. @@ -564,86 +1213,137 @@ author of the floating point additions in Emacs 19. Rates: $95/hr. -Updated: 14Apr94 +Updated: 1997-05-08 + +Stanislav Shalunov + +Email: shalunov@mccme.ru +Phones: on request + +Installing, configuring, helping learn any free software. +Handholding, trouble shooting. Making custom changes to free +software written in C. Teaching, lecturing, consulting. + +Want to have a free OS with free software serving your needs but do +not want to spend time yourself or not very skilled with the +computers? Cannot decide which free software suits your needs +better? Drop me a line. + +Well, essentially, anything else on special request. :-) + +Rate: $30/hour if you are in Moscow and I am there when you request +job done, $50 if the job may be done remotely (like configuring user +level program), $60/hour + travel expenses otherwise. (Negotiable, +significant discounts may apply.) + +Entered 1997-07-17 + +Vin Shelton +EtherSoft, Inc +781.488.5135 + + +I have been a professional programmer for 20 years, with most of that time +spent doing UNIX/C/C++ hacking. My specialties are (in no particular +order): system/kernel hacking, speech recognition, perl, object-oriented +design and analysis, FSF software (I have built nearly every FSF package on +several different platforms), small language design and implementation, and +HTML/web programming. Currently I'm a member of the XEmacs and egcs beta +teams. My rates vary from $60 - $100 per hour, depending on the size of the +project. + +Updated: 1998-06-24  Signum Support AB -Box 2044 _ ...!seunet!signum!info -S-580 02 Linkoping, Sweden +Teknikringen 8 +S-583 30 Linkoping, Sweden +46 13 21 46 00 voice +46 13 21 47 00 fax +http://www.signum.se/ -Signum Support AB is a company dedicated to supporting, developing -and distributing free software for, including but not limited to, -UNIX systems. The people behind Signum Support AB have many years -of general UNIX experience, both as system administrators and as -programmers, and also extensive experience in maintaining the GNU -programs, both administrating it and finding and fixing bugs. +Signum Support AB is a company dedicated to supporting, developing and +distributing free software for mainly UNIX systems. The people behind +Signum Support AB have many years of general UNIX and Internet +experience, both as system administrators and as programmers, and also +extensive experience in maintaining and administering the GNU programs +and Linux. + +Signum Support develops and markets the free GUI equipped Readynet +Internet server, the free PHTTPD http server and the easy to use Linux +based Fuego firewall. Services offered: - - Installation and customizing GNU and other free software. We will - make free software as easy to install and use as shrink wrapped + - Support on Internet service software, especially the free + Readynet Internet server we have developed for Linux. + - Support on Linux. + - Customization of Linux. + - Installation and customizing GNU and other free software. We are + making free software as easy to install and use as shrink wrapped programs. - Warranty protection. - - Customization and porting. - - Subscriptions to new versions which we will send monthly or with - any other interval. - Finding, Recommending and Investigation of free software in any - area of the customers choise. + area of the customer's choice. - Regular consulting. Rates: For software items, request our price list. - For consulting, 400-800 SEK/hour. + For consulting, 700-900 SEK/hour. -Updated: 14Apr94 +Updated: 1997-05-12  -Small Business Systems, Inc. -Box 17220, Route 104 -Esmond, RI 02917 -401.273.4669 - -Rate: Varies depending on complexity of task. - Hourly and fixed-rate contracts are available. -Programs Supported: All - -Updated: 14Apr94 - -Julian H. Stacey. -Vector Systems Ltd, Holz Strasse 27d, D 80469 Munich (Muenchen), GERMANY. -Tel. +49 89 268616 (089 268616 in Germany) 09:00-21:00 Timezone=GMT+01:00 - -Sources: All FSF/GNU, FreeBSD-current, X-Windows, XFree86, NetBSD, Mach, etc. - (Plus various other things, such as, but not limited to: - blas blt cflow CAD cnews crypt dvi2lj eispack elm encryption expect - ezd f2c flexfax gic gopher info-zip ingres inn jpeg kermit ksh - less lha linpack md5 mh mprof mtools mush nntp octave pbmplus - popper sather sc schemetoc slurp sml spreadsheet sup tcl tcl-dp - tcsh tcx term tex tiff tk top trn unarj ups urt wine xlock xv - xview xxgdb zmodem zip zircon zoo zsh.) -Media: QIC 1/4" Cartridge 525M, 150M, & 60M, TEAC CAS-60 60M Cassette, - CD-ROM, Floppies 1.4M & 1.2 & 720K & 360K. DAT arrangeable. - Postal Service C.O.D.(=`Nachnahme') or pre payment available. -Commercial Consultancy: - Custom Designs, Provision & support of FreeBSD or Unix, C, FSF tools, - X Windows, own tools, systems engineering, hardware interfacing, - multi lingual European, Cyrillic & Chinese tools & systems, - Unix, MSDOS, real time etc, communications & scientific & industrial. -DEUTSCH + FRANCAIS: - Man kann mir in Deutsch schreiben, (oder mich anrufen). - Je comprend Francais, mais je n'ecris pas des responses en Francais. - (Contact me in English, German, or French). -FREE for Symmetric Computer Systems Model 375 owners: - Free Binaries & sources on SCS/375's TEAC 50/60M Cassette, for: - GCC-1.40, UUCP-1.4, Ghostscript 2.3, Tar-1.08, Gzip-1.2.2 etc. - (Native SCS compiler can't compile GCC on this NSC32016 based BSD4.2) -On Request: Resume, Company Profile, Index of public & proprietary tools, -Rate: ~120 DM/hour. ~100DM/Cartridge. (1.5DM = $1 USA = 0.6 UK Pounds @4/'94) -Short enquiries free. (Kurze Anfragen Ohne Gebuhr). - -Updated: 14Jun94 - -Richard M. Stallman -UUCP: {mit-eddie,ucbvax,uunet,harvard,uw-beaver}!ai.mit.edu!rms + Jon Solomon + 235 Main St., Apt 3C-1 + East Hartford, Conn. 06118 + +1 860 895-8289 + + Maintains all GNU software... Available for General Consulting + (contact me if you are interested)... + Sendmail a specialty... Can answer questions pertaining to the + installation, maintenance, bug reporting and fixing for + most GNU products... Adhering to the FSF/GNU copyleft for all + work... (I only charge for the time it takes to do the above, + the software (and most GNU copyleft'd software) is free. + I can make tapes for you if you need that... + +Updated: 1997-05-09 + +Name: Julian Stacey +Location: Munich Germany, & on the Internet. +Qualifications: University Degree, BSc Hons Computer & Cybernetics, 1980. +Phone: +49.89.268616 Fax: +49.89.260812 Data: +49.89.26023276 +Resume: http://www.freebsd.org/~jhs/ +Time Zone: +01:00 +Rate: 130-170 DM/Hour. 2.7846 DM = 1 Pound = US $1.6332 +Commercial Independent Freelance Consultancy: + Any Unix (inc FreeBSD, Linux etc), C, X-Windows, FSF Tools, + Internet, Systems engineering, hardware interfacing, + real time, comms & scientific industrial, even Cyrillic & + Chinese interfaces etc. No Emacs. No Cobol. +Free Sources: FSF, FreeBSD & NetBSD CVS & current (daily!) & releases, + X-Windows, XFree86, Free dial in soon (details on web). + Media Copy Charge ~DM 100 QIC 1/4" 525M, 150M, & 60M; & CAS-60M. +Free GCC-1.40 For Symmetric Computer Systems Model 375 (native cc is broken). +Languages: Deutsch & Francais + Man kann mir in Deutsch schreiben, (oder mich anrufen). + Je comprend Francais, mais je n'ecris pas des responses en Fr. +! NO FREE HELP ! + - The Free Software Foundation do not pay me. + - I earn my living from professional consultancy fees. + - Though I write code for public domain ... + - I will Not solve stranger's complex problems for free ! +WHEN CONTACTING ME, DO THIS :- + 1) Tell me Immediately, Are You: + A) Expecting to pay my bill for professional consultancy. + B) Seeking a few minutes advice free of charge. + 2) Give me your email address, or that of a friend. + or Volunteer to phone back ~ 5 days later to collect follow-up + info. from the net. (No I will not incur bills phoning you back). + 3) Speak English if you want free advice ! I speak German, & + listen in French, but if you're not paying, make some effort too ! + +Updated: 1997-05-15 + +Richard M. Stallman 545 Tech Sq, Rm 430 Cambridge, MA 02139 @@ -654,104 +1354,141 @@ Original inventor of Emacs and main author of GNU Emacs and GCC. Rates: $6/min or $250/hr. -Updated: 14Apr94 +Updated: 1997-05-09  -JoS-Ware Comp Tech Johan Svensson -Box 739 -220 07 LUND -SWEDEN -Tel +46-46-104505 (Dept. of Economics, University of LUND) -Fax +46-46-188445 (JoS-Ware Comp Tech) - -What: We offer consulting services regarding installation, - customization, troubleshooting, porting and integration - of all free software, including GNU software. - -Spec.: Network integration, integration of public domain software - into commercial systems, WorldWideWeb, C, X-Windows, Linux, - networked information systems - -How: Remote login over internet, email, modem, phone, personal - visits (in southern Sweden mainly) - -Rates: 550SEK (+ tax) per hour within Sweden - 370SEK (+ tax) per hour within Sweden for educational org. - US $90 per hour outside Sweden - US $70 per hour outside Sweden for educational org. - Note: fees may vary and special arrangements may be considered - -Entered: 7Apr94 - -Kayvan Sylvan +Kayvan Sylvan Sylvan Associates 879 Lewiston Drive -San Jose, CA 95136 -Phone: 408-978-1407 +San Jose, CA 95136-1517 +Phone: (408) 978-1407 +Fax: (408) 978-1417 I will help you port, install and customize GNU Emacs, GCC, G++, -bison, and other GNU tools on almost any architechture and operating +bison, and other GNU tools on almost any architecture and operating system. Questions answered. GNU C and lisp hacking available. I will also do ongoing support and periodic upgrades if you get on my GNU software subscription list. -Rates: $60-$100/hour, depending on type of work. Substantial discounts +Rates: $70-$100/hour, depending on type of work. Substantial discounts for long-term contracts and also for educational or non-profit institutions. -Experience: Many different Unix systems (2.9BSD to 4.4BSD, SVR3 and -SVR4, Linux, Xenix). Systems programming and system administration on all +Experience: Many different Unix systems (2.9BSD to 4.4BSD, Xenix, SVR3 and +SVR4, Linux, FreeBSD). Systems programming and system administration on all brands of Unix. Kernel hacking experience. Lots of porting experience. -I can port anything to anything (within reason). -Updated: 14Apr94 +Updated: 1997-05-09  -Leonard H. Tower Jr. +TerraTel AB +Tankeg=E5ngen 4 +S-417 56 G=F6teborg, Sweden ++46 31 50 79 40 voice ++46 31 50 79 39 fax +http://www.netg.se + +TerraTel AB is a company that does consultant jobs and holds courses +in the fields of Unix software, TCP/IP networking and Internet +applications. The people behind TerraTel AB have many years +of general UNIX experience, both as system administrators and as +programmers, and also extensive experience in maintaining the GNU +programs; in administration as well as finding and fixing bugs. + +Services offered: + +- Installation and customizing GNU and other free software. We will + make free software as easy to install and use as shrink wrapped + programs. +- Service and support subscriptions. +- Warranty protection. +- Customization and porting. +- Subscriptions to new versions which we will send monthly or with + any other interval. +- Finding, recommending and investigating free software in any + area of the customers choice. +- Regular consulting. +- Support on Internet service software, especially the free +- Support on Linux. +- Freeware based courses in Unix usage, C, C++, or any GNU tools + +Rates: For courses, contact us for a quote, +For consulting, $60-120/hour, depending on contract length. + +Entered: 1997-05-12 + +Jonathan Thornburg / BKIS Consulting +E-mail: (preferred way to contact me) +Postal: Box 8-7, Thetis Island BC V0R 2Y0, Canada +Phone: (250) 246-3640 (somewhat unreliable) + +* B.Sc (Honors 1st Class) in Math+Physics+CS, M.Sc and Ph.D in Astronomy +* 20+ years computing experience using a wide range of software and + hardware environments + +* Very fluent in C (15+ years experience) +* Fluent in C++, Perl, sh, csh, Awk, Fortran, PL/I, Pascal, APL, Lisp, + Basic, Maple, Reduce, various machine languages +* Very fluent (10+ years experience) in general Unix toolset and programming +* Good knowledge (4+ years experience) of Unix system administration + (SunOS, Linux, SGI) +* Strong background (both theory and practical experience) in Unix/network + security, computer graphics, X and Motif GUI programming +* Good general knowledge of Unix (kernel) internals and device drivers +* Very fluent in LaTeX, TeX, also HTML, HTTP, and CGI programming +* Member of Usenix (professional and technical Unix association) and + SAGE (system administrator's guild) + +* Very strong background (extensive experience) in numerical analysis +* Strong backgrounds in hardware architecture, microprogramming, + programming language implementation, compiler theory, data structures, + OS design and internals, networking, symbolic manipulation, AI + +I'm available for Unix-based contract programming, software installation, +and/or general system administration. My recent projects include several +20K-50K 50K line C/Maple/Awk scientific applications, several small (1K line) +Perl/Awk text processors and "system glue" CGI programs, finding and fixing +bugs in a (free) 50K line graphics package, and a partially completed project +to port (really rewrite) the GUI of a 50K line C++ Netscape plugin from +Win32 to Unix/X/Motif. + +Unless otherwise required by a client, all the software I write is covered +by the GNU General Public License. My basic rate is Can$50/hour for work I +can do remotely over the Internet, more for on-site work, less for selected +non-profit organizations. + +Updated: 1997-05-19 + +Leonard H. Tower Jr. 36 Porter Street -Somerville, MA 02143, USA -+1 (617) 623-7739 +Somerville, MA 02143 +USA ++1-617-623-7739 Will work on most GNU software. Installation, handholding, trouble shooting, extensions, teaching. -Rates: 100.00/hour + travel expenses. Negotiable for non-profits. +Rates: $ 150.00/hour + travel expenses. Fixed fee quotes available. + Negotiable for non-profits. Experience: Have hacked on over a dozen architectures in many languages. Have -system mothered several varieties of Unixes. Assisted rms with the front end -of gcc and it's back-end support. Resume available on request. - -Entered: 14Apr94 - -UrbanSoft AO -68 Malooktinskii Prospect -St. Petersburg, Russia 195272 - -Custom GhostScript and TeX programming by e-mail. -Database documents, directories, standard forms. - -UrbanSoft uses a portion of its revenues to contribute -diskette distributions of GNU software to Russian -universities (most of which lack FTP access). - -Rates: 30,000 rubles (currently USD 16.80) per hour. - Fixed rate contracts also possible. - Payable by bank transfer. +system mothered too many varieties of Unixes. Assisted rms with the front end +of gcc and its back-end support. Resume available on request. -Updated: 20Apr94 +Updated: 1998-02-10  -noris network +noris network GmbH Matthias Urlichs Schleiermacherstrasse 12 90491 Nuernberg Germany -Phone: +49 911 9959621 -Fax: +49 911 5980150 +Phone: +49 911 59818-0 +Fax: +49 911 59818-11 http://info.noris.de/ (German) Expertise: OS internals, esp. Linux and BSD, esp. device drivers Network protocol / program design and coding - Utilities coding and maintainance + Utilities coding and maintenance Program debugging, testing User interface design and testing Several programming and tool languages @@ -766,87 +1503,107 @@ Services: Internet access Rates: - DM 110 (~$70) per hour - Support contracts start at DM 170/month + DM 30/supported system. + DM 150 (~$85) per hour + Support contracts start at DM 220/month + DM 30/supported system. Willing to travel for sufficiently large jobs. Rates don't include taxes. -Entered: 16Aug94 +Updated: 1997-08-04  -Joe Wells -Postal Address: - care of: Boston University Computer Science Department - 111 Cummington Street, Room 138 - Boston, Massachusetts 02215 -Work Telephone: (617) 353-3381 (sorry, but no answering machine or voice mail) -Home Telephone: (617) 739-7456 (until August 1995) -Finger "jbw@cs.bu.edu" for up-to-date contact information. +Paul C.A. van Gool + -Experience: - I have B.A. and M.A. degrees in Computer Science and have completed - all but the dissertation for a Ph.D. in C.S. My research for my - Ph.D. is in the areas of logic, type systems, and programming - language theory. My primary programming languages are Emacs Lisp, - Perl, and Bourne shell, but of course I can program in any language. - I have written numerous Emacs Lisp packages. I started the USENET - "List of Frequently Asked Questions about GNU Emacs with Answers" and - maintained it for more than two years. Most of my work has been - related to the telephone system (modems, voice mail, etc.), but I am - not limited to that. Send e-mail for my complete resume or curriculum - vita. +Address: Netherlands Organization for Applied Scientific Research + Physics and Electronics Laboratory + PO Box 96864, 2509 JG the Hague + The Netherlands -Programs supported: - GNU Emacs and Taylor UUCP: - Installation, training, customization, bug fixing, troubleshooting, - extension, development, porting, or answering any kind of question. - Any other GNU program: - The same things, but I don't necessarily have huge amounts of - experience with the particular program. - -Working conditions: - I am usually available for part-time work (less than 20 hours per week - including any travel time). I can sometimes make time for full-time - work for a month or two; please inquire. I can either work in or near - Boston or via the Internet or via telephone; travel outside the Boston - metropolitan area can be negotiated. My schedule is very flexible. - Any programs I write will normally have the copying conditions of the - GNU General Public License; this is negotiable. - -Rates: $65/hour as an independent contractor. - travel and telephone expenses. - higher rates if extensive travel is required. - -Updated: 27Sep94. - -Herb Wood -phone: 1-415-789-7173 -email: - -I'm a better "planner" than I am a hacker. A really good hacker will be able -to keep many pieces of information in their short-term memory and to memorize -new pieces of information at a fast rate. This is not my strong point. -Rather, I excel in domains that require knowledge of the slightly more -theoretical parts of computer science --for example, logic, formal methods of -program development, and functional programming. I can write, and I have -"tutoring" (teaching one-on-one) experience, an, unlike some programmers, -I enjoy doing these things. - -I have spend a lot of time looking at the Emacs Lisp sources and customizing -Emacs and VM. I think I can customize Emacs and its packages quickly and -effectively. - -Entered: 30Jul95 - -Yggdrasil Computing, Inc./ Freesoft, Inc. -4880 Stevens Creek Blvd. Ste. 205 -San Jose, CA 95129 -(408) 261-6630 -(800) 261 6630 - -Updated: 14Apr94 +Phone: +31-70-3740260 +Fax : +31-70-3740652 + +I would like to provide unpaid support for the following things: + +- C +- C++ +- f2c +- compilation and installation of most GNU packages + +Updated: 1998-06-24 + +Joel N. Weber II +185 Lowell St #2 +Somerville, MA 02144-2629 +devnull@gnu.org + +I can install GNU software, customize it, fix bugs, answer questions, +and teach. + +I am fluent in C, emacs lisp, Bourne shell, and awk. I also have a +good understanding of automake and autoconf. + +I have modified identd, cvs, and ftpd to change their security +procedures; I have modified the GNU fileutils to understand new flag +bits that were added to the Hurd. I have been involved in developing +Hurd translators. Long ago, I worked on developing a web browser; +that project was eventually killed, but I learned a lot in the +process. + +I am experienced in webmastering and system administration. + +Rate: $100/hour, negotiable. + +Arne Wichmann + +EMail: +Telephone on request. + +I support GNU software on the following platforms: + +Linux +SunOS 4.X 5.X +HPUX 9.X +other platforms on request. + +Usual rates: 20DM per hour. Free support for private people as time +permits. + +Updated: 1997-05-16 + +Jody Winston +xprt Computer Consulting, Inc. +731 Voyager +Houston, TX, 77058 +(281) 480-UNIX, + +We have supported, installed, and used the entire GNU software suite +for over 8 years on many different Unix platforms. We have written +character device drivers and proc file systems for custom hardware +running on Linux. In addition, we have developed a custom X11 server +and X input extensions. Our consulting rate is $150.00 US dollars per +hour, negotiable, plus a per diem for out of town work. + +Updated: 1997-05-12 + +Lige Zhou +Consultant +Open Technologies Corporation +Sun Lotus Bldg. 2nd Floor +2-9-1 Chuou, Nakano-ku, Tokyo 164 Japan +Tel: +81-3-3365-2911 Fax: +81-3-3365-2920 +E-mail: + +My profile is listed at: http://www.opentech.co.jp/~zhou/ + +I have two years of experience porting and supporting GNU C Compiler and +GNU Assembler at the Wingnut project of SRA, Inc., Tokyo. + +I can provide free consultation on these products if the problem is not +time-consuming. + +Updated: 1996-12-04  For a current copy of this directory, or to have yourself listed, ask: - gnu@prep.ai.mit.edu + gnu@gnu.org ** Please keep the entries in this file alphabetical ** diff --git a/contrib/gcc/acconfig.h b/contrib/gcc/acconfig.h new file mode 100644 index 0000000..e1ac384 --- /dev/null +++ b/contrib/gcc/acconfig.h @@ -0,0 +1,79 @@ +/* Define if printf supports "%p". */ +#undef HAVE_PRINTF_PTR + +/* Define if you want expensive run-time checks. */ +#undef ENABLE_CHECKING + +/* Define if your cpp understands the stringify operator. */ +#undef HAVE_CPP_STRINGIFY + +/* Define if your compiler understands volatile. */ +#undef HAVE_VOLATILE + +/* Define if your assembler supports specifying the maximum number + of bytes to skip when using the GAS .p2align command. */ +#undef HAVE_GAS_MAX_SKIP_P2ALIGN + +/* Define if your assembler supports .balign and .p2align. */ +#undef HAVE_GAS_BALIGN_AND_P2ALIGN + +/* Define if you have a working header file. */ +#undef HAVE_INTTYPES_H + +/* Whether malloc must be declared even if is included. */ +#undef NEED_DECLARATION_MALLOC + +/* Whether realloc must be declared even if is included. */ +#undef NEED_DECLARATION_REALLOC + +/* Whether calloc must be declared even if is included. */ +#undef NEED_DECLARATION_CALLOC + +/* Whether free must be declared even if is included. */ +#undef NEED_DECLARATION_FREE + +/* Whether bcopy must be declared even if is included. */ +#undef NEED_DECLARATION_BCOPY + +/* Whether bcmp must be declared even if is included. */ +#undef NEED_DECLARATION_BCMP + +/* Whether bzero must be declared even if is included. */ +#undef NEED_DECLARATION_BZERO + +/* Whether index must be declared even if is included. */ +#undef NEED_DECLARATION_INDEX + +/* Whether rindex must be declared even if is included. */ +#undef NEED_DECLARATION_RINDEX + +/* Whether getenv must be declared even if is included. */ +#undef NEED_DECLARATION_GETENV + +/* Whether atol must be declared even if is included. */ +#undef NEED_DECLARATION_ATOL + +/* Whether sbrk must be declared even if is included. */ +#undef NEED_DECLARATION_SBRK + +/* Whether abort must be declared even if is included. */ +#undef NEED_DECLARATION_ABORT + +/* Whether strerror must be declared even if is included. */ +#undef NEED_DECLARATION_STRERROR + +/* Whether getcwd must be declared even if is included. */ +#undef NEED_DECLARATION_GETCWD + +/* Whether getwd must be declared even if is included. */ +#undef NEED_DECLARATION_GETWD + +/* Whether getrlimit must be declared even if is included. */ +#undef NEED_DECLARATION_GETRLIMIT + +/* Whether setrlimit must be declared even if is included. */ +#undef NEED_DECLARATION_SETRLIMIT + +/* Define if you want expensive run-time checks. */ +#undef ENABLE_CHECKING +@TOP@ diff --git a/contrib/gcc/aclocal.m4 b/contrib/gcc/aclocal.m4 new file mode 100644 index 0000000..febe8a7 --- /dev/null +++ b/contrib/gcc/aclocal.m4 @@ -0,0 +1,221 @@ +dnl See whether we need a declaration for a function. +dnl GCC_NEED_DECLARATION(FUNCTION [, EXTRA-HEADER-FILES]) +AC_DEFUN(GCC_NEED_DECLARATION, +[AC_MSG_CHECKING([whether $1 must be declared]) +AC_CACHE_VAL(gcc_cv_decl_needed_$1, +[AC_TRY_COMPILE([ +#include +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifndef HAVE_RINDEX +#define rindex strrchr +#endif +#ifndef HAVE_INDEX +#define index strchr +#endif +$2], +[char *(*pfn) = (char *(*)) $1], +eval "gcc_cv_decl_needed_$1=no", eval "gcc_cv_decl_needed_$1=yes")]) +if eval "test \"`echo '$gcc_cv_decl_needed_'$1`\" = yes"; then + AC_MSG_RESULT(yes) + gcc_tr_decl=NEED_DECLARATION_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + AC_DEFINE_UNQUOTED($gcc_tr_decl) +else + AC_MSG_RESULT(no) +fi +])dnl + +dnl Check multiple functions to see whether each needs a declaration. +dnl GCC_NEED_DECLARATIONS(FUNCTION... [, EXTRA-HEADER-FILES]) +AC_DEFUN(GCC_NEED_DECLARATIONS, +[for ac_func in $1 +do +GCC_NEED_DECLARATION($ac_func, $2) +done +]) + +dnl Check if we have vprintf and possibly _doprnt. +dnl Note autoconf checks for vprintf even though we care about vfprintf. +AC_DEFUN(GCC_FUNC_VFPRINTF_DOPRNT, +[AC_FUNC_VPRINTF +vfprintf= +doprint= +if test $ac_cv_func_vprintf != yes ; then + vfprintf=vfprintf.o + if test $ac_cv_func__doprnt != yes ; then + doprint=doprint.o + fi +fi +AC_SUBST(vfprintf) +AC_SUBST(doprint) +]) + +dnl See if the printf functions in libc support %p in format strings. +AC_DEFUN(GCC_FUNC_PRINTF_PTR, +[AC_CACHE_CHECK(whether the printf functions support %p, + gcc_cv_func_printf_ptr, +[AC_TRY_RUN([#include + +main() +{ + char buf[64]; + char *p = buf, *q = NULL; + sprintf(buf, "%p", p); + sscanf(buf, "%p", &q); + exit (p != q); +}], gcc_cv_func_printf_ptr=yes, gcc_cv_func_printf_ptr=no, + gcc_cv_func_printf_ptr=no) +rm -f core core.* *.core]) +if test $gcc_cv_func_printf_ptr = yes ; then + AC_DEFINE(HAVE_PRINTF_PTR) +fi +]) + +dnl See if symbolic links work and if not, try to substitute either hard links or simple copy. +AC_DEFUN(GCC_PROG_LN_S, +[AC_MSG_CHECKING(whether ln -s works) +AC_CACHE_VAL(gcc_cv_prog_LN_S, +[rm -f conftestdata_t +echo >conftestdata_f +if ln -s conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN_S="ln -s" +else + if ln conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN_S=ln + else + gcc_cv_prog_LN_S=cp + fi +fi +rm -f conftestdata_f conftestdata_t +])dnl +LN_S="$gcc_cv_prog_LN_S" +if test "$gcc_cv_prog_LN_S" = "ln -s"; then + AC_MSG_RESULT(yes) +else + if test "$gcc_cv_prog_LN_S" = "ln"; then + AC_MSG_RESULT([no, using ln]) + else + AC_MSG_RESULT([no, and neither does ln, so using cp]) + fi +fi +AC_SUBST(LN_S)dnl +]) + +dnl See if hard links work and if not, try to substitute either symbolic links or simple copy. +AC_DEFUN(GCC_PROG_LN, +[AC_MSG_CHECKING(whether ln works) +AC_CACHE_VAL(gcc_cv_prog_LN, +[rm -f conftestdata_t +echo >conftestdata_f +if ln conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN="ln" +else + if ln -s conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN="ln -s" + else + gcc_cv_prog_LN=cp + fi +fi +rm -f conftestdata_f conftestdata_t +])dnl +LN="$gcc_cv_prog_LN" +if test "$gcc_cv_prog_LN" = "ln"; then + AC_MSG_RESULT(yes) +else + if test "$gcc_cv_prog_LN" = "ln -s"; then + AC_MSG_RESULT([no, using ln -s]) + else + AC_MSG_RESULT([no, and neither does ln -s, so using cp]) + fi +fi +AC_SUBST(LN)dnl +]) + +dnl See whether the stage1 host compiler accepts the volatile keyword. +AC_DEFUN(GCC_C_VOLATILE, +[AC_CACHE_CHECK([for volatile], gcc_cv_c_volatile, +[AC_TRY_COMPILE(, [volatile int foo;], + gcc_cv_c_volatile=yes, gcc_cv_c_volatile=no)]) +if test $gcc_cv_c_volatile = yes ; then + AC_DEFINE(HAVE_VOLATILE) +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), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +AC_MSG_CHECKING(for a BSD compatible install) +if test -z "$INSTALL"; then +AC_CACHE_VAL(ac_cv_path_install, +[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" +])dnl + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +dnl We do special magic for INSTALL instead of AC_SUBST, to get +dnl relative paths right. +AC_MSG_RESULT($INSTALL) +AC_SUBST(INSTALL)dnl + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' +AC_SUBST(INSTALL_PROGRAM)dnl + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +AC_SUBST(INSTALL_DATA)dnl +]) diff --git a/contrib/gcc/alias.c b/contrib/gcc/alias.c new file mode 100644 index 0000000..172b676 --- /dev/null +++ b/contrib/gcc/alias.c @@ -0,0 +1,1261 @@ +/* Alias analysis for GNU C + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by John Carr (jfc@mit.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 "config.h" +#include "system.h" +#include "rtl.h" +#include "expr.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "flags.h" +#include "toplev.h" + +static rtx canon_rtx PROTO((rtx)); +static int rtx_equal_for_memref_p PROTO((rtx, rtx)); +static rtx find_symbolic_term PROTO((rtx)); +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 rtx find_base_value PROTO((rtx)); + +/* 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)) + +/* Cap the number of passes we make over the insns propagating alias + information through set chains. + + 10 is a completely arbitrary choice. */ +#define MAX_ALIAS_LOOP_PASSES 10 + +/* reg_base_value[N] gives an address to which register N is related. + If all sets after the first add or subtract to the current value + or otherwise modify it so it does not point to a different top level + object, reg_base_value[N] is equal to the address part of the source + of the first set. + + A base address can be an ADDRESS, SYMBOL_REF, or LABEL_REF. ADDRESS + expressions represent certain special values: function arguments and + the stack, frame, and argument pointers. The contents of an address + expression are not used (but they are descriptive for debugging); + only the address and mode matter. Pointer equality, not rtx_equal_p, + determines whether two ADDRESS expressions refer to the same base + address. The mode determines whether it is a function argument or + other special value. */ + +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) + +/* Vector of known invariant relationships between registers. Set in + loop unrolling. Indexed by register number, if nonzero the value + is an expression describing this register in terms of another. + + The length of this array is REG_BASE_VALUE_SIZE. + + Because this array contains only pseudo registers it has no effect + after reload. */ +static rtx *alias_invariant; + +/* Vector indexed by N giving the initial (unchanging) value known + for pseudo-register N. */ +rtx *reg_known_value; + +/* Indicates number of valid entries in reg_known_value. */ +static int reg_known_value_size; + +/* Vector recording for each reg_known_value whether it is due to a + REG_EQUIV note. Future passes (viz., reload) may replace the + pseudo with the equivalent expression and so we account for the + dependences that would be introduced if that happens. */ +/* ??? This is a problem only on the Convex. The REG_EQUIV notes created in + assign_parms mention the arg pointer, and there are explicit insns in the + RTL that modify the arg pointer. Thus we must ensure that such insns don't + get scheduled across each other because that would invalidate the REG_EQUIV + notes. One could argue that the REG_EQUIV notes are wrong, but solving + the problem in the scheduler will likely give better code, so we do it + here. */ +char *reg_known_equiv_p; + +/* True when scanning insns from the start of the rtl to the + NOTE_INSN_FUNCTION_BEG note. */ + +static int copying_arguments; + +/* Inside SRC, the source of a SET, find a base address. */ + +static rtx +find_base_value (src) + register rtx src; +{ + switch (GET_CODE (src)) + { + case SYMBOL_REF: + case LABEL_REF: + return src; + + case REG: + /* At the start of a function argument registers have known base + values which may be lost later. Returning an ADDRESS + expression here allows optimization based on argument values + even when the argument registers are used for other purposes. */ + if (REGNO (src) < FIRST_PSEUDO_REGISTER && copying_arguments) + return new_reg_base_value[REGNO (src)]; + + /* If a pseudo has a known base value, return it. Do not do this + for hard regs since it can result in a circular dependency + chain for registers which have values at function entry. + + 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 + && reg_base_value[REGNO (src)]) + return reg_base_value[REGNO (src)]; + + return src; + + case MEM: + /* Check for an argument passed in memory. Only record in the + copying-arguments block; it is too hard to track changes + otherwise. */ + if (copying_arguments + && (XEXP (src, 0) == arg_pointer_rtx + || (GET_CODE (XEXP (src, 0)) == PLUS + && XEXP (XEXP (src, 0), 0) == arg_pointer_rtx))) + return gen_rtx_ADDRESS (VOIDmode, src); + return 0; + + case CONST: + src = XEXP (src, 0); + if (GET_CODE (src) != PLUS && GET_CODE (src) != MINUS) + break; + /* fall through */ + + case PLUS: + case MINUS: + { + rtx temp, src_0 = XEXP (src, 0), src_1 = XEXP (src, 1); + + /* If either operand is a REG, then see if we already have + a known value for it. */ + if (GET_CODE (src_0) == REG) + { + temp = find_base_value (src_0); + if (temp) + src_0 = temp; + } + + if (GET_CODE (src_1) == REG) + { + temp = find_base_value (src_1); + if (temp) + src_1 = temp; + } + + /* Guess which operand is the base address. + + If either operand is a symbol, then it is the base. If + either operand is a CONST_INT, then the other is the base. */ + + if (GET_CODE (src_1) == CONST_INT + || GET_CODE (src_0) == SYMBOL_REF + || GET_CODE (src_0) == LABEL_REF + || GET_CODE (src_0) == CONST) + return find_base_value (src_0); + + if (GET_CODE (src_0) == CONST_INT + || GET_CODE (src_1) == SYMBOL_REF + || GET_CODE (src_1) == LABEL_REF + || GET_CODE (src_1) == CONST) + return find_base_value (src_1); + + /* This might not be necessary anymore. + + If either operand is a REG that is a known pointer, then it + is the base. */ + if (GET_CODE (src_0) == REG && REGNO_POINTER_FLAG (REGNO (src_0))) + return find_base_value (src_0); + + if (GET_CODE (src_1) == REG && REGNO_POINTER_FLAG (REGNO (src_1))) + return find_base_value (src_1); + + return 0; + } + + case LO_SUM: + /* The standard form is (lo_sum reg sym) so look only at the + second operand. */ + return find_base_value (XEXP (src, 1)); + + case AND: + /* If the second operand is constant set the base + address to the first operand. */ + if (GET_CODE (XEXP (src, 1)) == CONST_INT && INTVAL (XEXP (src, 1)) != 0) + return find_base_value (XEXP (src, 0)); + return 0; + + case ZERO_EXTEND: + case SIGN_EXTEND: /* used for NT/Alpha pointers */ + case HIGH: + return find_base_value (XEXP (src, 0)); + + default: + break; + } + + return 0; +} + +/* Called from init_alias_analysis indirectly through note_stores. */ + +/* while scanning insns to find base values, reg_seen[N] is nonzero if + register N has been set in this function. */ +static char *reg_seen; + +/* Addresses which are known not to alias anything else are identified + by a unique integer. */ +static int unique_id; + +static void +record_set (dest, set) + rtx dest, set; +{ + register int regno; + rtx src; + + if (GET_CODE (dest) != REG) + return; + + regno = REGNO (dest); + + if (set) + { + /* A CLOBBER wipes out any old value but does not prevent a previously + unset register from acquiring a base address (i.e. reg_seen is not + set). */ + if (GET_CODE (set) == CLOBBER) + { + new_reg_base_value[regno] = 0; + return; + } + src = SET_SRC (set); + } + else + { + if (reg_seen[regno]) + { + new_reg_base_value[regno] = 0; + return; + } + reg_seen[regno] = 1; + new_reg_base_value[regno] = gen_rtx_ADDRESS (Pmode, + GEN_INT (unique_id++)); + return; + } + + /* This is not the first set. If the new value is not related to the + old value, forget the base value. Note that the following code is + not detected: + extern int x, y; int *p = &x; p += (&y-&x); + ANSI C does not allow computing the difference of addresses + of distinct top level objects. */ + if (new_reg_base_value[regno]) + switch (GET_CODE (src)) + { + case LO_SUM: + case PLUS: + case MINUS: + if (XEXP (src, 0) != dest && XEXP (src, 1) != dest) + new_reg_base_value[regno] = 0; + break; + case AND: + if (XEXP (src, 0) != dest || GET_CODE (XEXP (src, 1)) != CONST_INT) + new_reg_base_value[regno] = 0; + break; + default: + new_reg_base_value[regno] = 0; + break; + } + /* If this is the first set of a register, record the value. */ + else if ((regno >= FIRST_PSEUDO_REGISTER || ! fixed_regs[regno]) + && ! reg_seen[regno] && new_reg_base_value[regno] == 0) + new_reg_base_value[regno] = find_base_value (src); + + reg_seen[regno] = 1; +} + +/* Called from loop optimization when a new pseudo-register is created. */ +void +record_base_value (regno, val, invariant) + int regno; + rtx val; + int invariant; +{ + if (regno >= reg_base_value_size) + return; + + /* If INVARIANT is true then this value also describes an invariant + relationship which can be used to deduce that two registers with + unknown values are different. */ + if (invariant && alias_invariant) + alias_invariant[regno] = val; + + if (GET_CODE (val) == REG) + { + if (REGNO (val) < reg_base_value_size) + { + reg_base_value[regno] = reg_base_value[REGNO (val)]; + } + return; + } + reg_base_value[regno] = find_base_value (val); +} + +static rtx +canon_rtx (x) + rtx x; +{ + /* Recursively look for equivalences. */ + if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER + && REGNO (x) < reg_known_value_size) + return reg_known_value[REGNO (x)] == x + ? x : canon_rtx (reg_known_value[REGNO (x)]); + else if (GET_CODE (x) == PLUS) + { + rtx x0 = canon_rtx (XEXP (x, 0)); + rtx x1 = canon_rtx (XEXP (x, 1)); + + if (x0 != XEXP (x, 0) || x1 != XEXP (x, 1)) + { + /* We can tolerate LO_SUMs being offset here; these + rtl are used for nothing other than comparisons. */ + if (GET_CODE (x0) == CONST_INT) + return plus_constant_for_output (x1, INTVAL (x0)); + else if (GET_CODE (x1) == CONST_INT) + return plus_constant_for_output (x0, INTVAL (x1)); + return gen_rtx_PLUS (GET_MODE (x), x0, x1); + } + } + /* This gives us much better alias analysis when called from + the loop optimizer. Note we want to leave the original + MEM alone, but need to return the canonicalized MEM with + all the flags with their original values. */ + else if (GET_CODE (x) == MEM) + { + rtx addr = canon_rtx (XEXP (x, 0)); + 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_ALIAS_SET (new) = MEM_ALIAS_SET (x); + x = new; + } + } + return x; +} + +/* Return 1 if X and Y are identical-looking rtx's. + + We use the data in reg_known_value above to see if two registers with + different numbers are, in fact, equivalent. */ + +static int +rtx_equal_for_memref_p (x, y) + rtx x, y; +{ + register int i; + register int j; + register enum rtx_code code; + register char *fmt; + + if (x == 0 && y == 0) + return 1; + if (x == 0 || y == 0) + return 0; + x = canon_rtx (x); + y = canon_rtx (y); + + if (x == y) + return 1; + + code = GET_CODE (x); + /* Rtx's of different codes cannot be equal. */ + if (code != GET_CODE (y)) + return 0; + + /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. + (REG:SI x) and (REG:HI x) are NOT equivalent. */ + + if (GET_MODE (x) != GET_MODE (y)) + return 0; + + /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */ + + if (code == REG) + return REGNO (x) == REGNO (y); + if (code == LABEL_REF) + return XEXP (x, 0) == XEXP (y, 0); + if (code == SYMBOL_REF) + return XSTR (x, 0) == XSTR (y, 0); + if (code == CONST_INT) + return INTVAL (x) == INTVAL (y); + if (code == ADDRESSOF) + return REGNO (XEXP (x, 0)) == REGNO (XEXP (y, 0)) && XINT (x, 1) == XINT (y, 1); + + /* 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') + return ((rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)) + && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1))) + || (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 1)) + && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 0)))); + else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2') + return (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)) + && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1))); + else if (GET_RTX_CLASS (code) == '1') + return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)); + + /* Compare the elements. If any pair of corresponding elements + fail to match, return 0 for the whole things. + + Limit cases to types which actually appear in addresses. */ + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + switch (fmt[i]) + { + case 'i': + if (XINT (x, i) != XINT (y, i)) + return 0; + break; + + case 'E': + /* Two vectors must have the same length. */ + if (XVECLEN (x, i) != XVECLEN (y, i)) + return 0; + + /* And the corresponding elements must match. */ + for (j = 0; j < XVECLEN (x, i); j++) + if (rtx_equal_for_memref_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) + return 0; + break; + + case 'e': + if (rtx_equal_for_memref_p (XEXP (x, i), XEXP (y, i)) == 0) + return 0; + break; + + /* This can happen for an asm which clobbers memory. */ + case '0': + 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. */ + default: + abort (); + } + } + return 1; +} + +/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within + X and return it, or return 0 if none found. */ + +static rtx +find_symbolic_term (x) + rtx x; +{ + register int i; + register enum rtx_code code; + register char *fmt; + + code = GET_CODE (x); + if (code == SYMBOL_REF || code == LABEL_REF) + return x; + if (GET_RTX_CLASS (code) == 'o') + return 0; + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + rtx t; + + if (fmt[i] == 'e') + { + t = find_symbolic_term (XEXP (x, i)); + if (t != 0) + return t; + } + else if (fmt[i] == 'E') + break; + } + return 0; +} + +static rtx +find_base_term (x) + register rtx x; +{ + switch (GET_CODE (x)) + { + case REG: + return REG_BASE_VALUE (x); + + case ZERO_EXTEND: + case SIGN_EXTEND: /* Used for Alpha/NT pointers */ + case HIGH: + case PRE_INC: + case PRE_DEC: + case POST_INC: + case POST_DEC: + return find_base_term (XEXP (x, 0)); + + case CONST: + x = XEXP (x, 0); + if (GET_CODE (x) != PLUS && GET_CODE (x) != MINUS) + return 0; + /* fall through */ + case LO_SUM: + case PLUS: + case MINUS: + { + rtx tmp = find_base_term (XEXP (x, 0)); + if (tmp) + return tmp; + return find_base_term (XEXP (x, 1)); + } + + case AND: + if (GET_CODE (XEXP (x, 0)) == REG && GET_CODE (XEXP (x, 1)) == CONST_INT) + return REG_BASE_VALUE (XEXP (x, 0)); + return 0; + + case SYMBOL_REF: + case LABEL_REF: + return x; + + default: + return 0; + } +} + +/* Return 0 if the addresses X and Y are known to point to different + objects, 1 if they might be pointers to the same object. */ + +static int +base_alias_check (x, y) + rtx x, y; +{ + rtx x_base = find_base_term (x); + rtx y_base = find_base_term (y); + + /* If the address itself has no known base see if a known equivalent + value has one. If either address still has no known base, nothing + is known about aliasing. */ + if (x_base == 0) + { + rtx x_c; + if (! flag_expensive_optimizations || (x_c = canon_rtx (x)) == x) + return 1; + x_base = find_base_term (x_c); + if (x_base == 0) + return 1; + } + + if (y_base == 0) + { + rtx y_c; + if (! flag_expensive_optimizations || (y_c = canon_rtx (y)) == y) + return 1; + y_base = find_base_term (y_c); + if (y_base == 0) + return 1; + } + + /* If the base addresses are equal nothing is known about aliasing. */ + 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. */ + if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS) + { + return GET_CODE (x) == AND || GET_CODE (y) == AND; + } + + /* If one address is a stack reference there can be no alias: + stack references using different base registers do not alias, + a stack reference can not alias a parameter, and a stack reference + can not alias a global. */ + if ((GET_CODE (x_base) == ADDRESS && GET_MODE (x_base) == Pmode) + || (GET_CODE (y_base) == ADDRESS && GET_MODE (y_base) == Pmode)) + return 0; + + if (! flag_argument_noalias) + return 1; + + if (flag_argument_noalias > 1) + return 0; + + /* Weak noalias assertion (arguments are distinct, but may match globals). */ + return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode); +} + +/* 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. + XSIZE is the size in bytes of the X reference, + similarly YSIZE is the size in bytes for Y. + + If XSIZE or YSIZE is zero, we do not know the amount of memory being + referenced (the reference was BLKmode), so make the most pessimistic + assumptions. + + If XSIZE or YSIZE is negative, we may access memory outside the object + being referenced as a side effect. This can happen when using AND to + align memory references, as is done on the Alpha. + + Nice to notice that varying addresses cannot conflict with fp if no + local variables had their addresses taken, but that's too hard now. */ + + +static int +memrefs_conflict_p (xsize, x, ysize, y, c) + register rtx x, y; + int xsize, ysize; + HOST_WIDE_INT c; +{ + if (GET_CODE (x) == HIGH) + x = XEXP (x, 0); + else if (GET_CODE (x) == LO_SUM) + x = XEXP (x, 1); + else + x = canon_rtx (x); + 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); + + if (rtx_equal_for_memref_p (x, y)) + { + if (xsize <= 0 || ysize <= 0) + return 1; + if (c >= 0 && xsize > c) + return 1; + if (c < 0 && ysize+c > 0) + return 1; + return 0; + } + + /* This code used to check for conflicts involving stack references and + globals but the base address alias code now handles these cases. */ + + if (GET_CODE (x) == PLUS) + { + /* The fact that X is canonicalized means that this + PLUS rtx is canonicalized. */ + rtx x0 = XEXP (x, 0); + rtx x1 = XEXP (x, 1); + + if (GET_CODE (y) == PLUS) + { + /* The fact that Y is canonicalized means that this + PLUS rtx is canonicalized. */ + rtx y0 = XEXP (y, 0); + rtx y1 = XEXP (y, 1); + + if (rtx_equal_for_memref_p (x1, y1)) + return memrefs_conflict_p (xsize, x0, ysize, y0, 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)); + else if (GET_CODE (y1) == CONST_INT) + return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); + + return 1; + } + else if (GET_CODE (x1) == CONST_INT) + return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1)); + } + else if (GET_CODE (y) == PLUS) + { + /* The fact that Y is canonicalized means that this + PLUS rtx is canonicalized. */ + rtx y0 = XEXP (y, 0); + rtx y1 = XEXP (y, 1); + + if (GET_CODE (y1) == CONST_INT) + return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); + else + return 1; + } + + if (GET_CODE (x) == GET_CODE (y)) + switch (GET_CODE (x)) + { + case MULT: + { + /* Handle cases where we expect the second operands to be the + same, and check only whether the first operand would conflict + or not. */ + rtx x0, y0; + rtx x1 = canon_rtx (XEXP (x, 1)); + rtx y1 = canon_rtx (XEXP (y, 1)); + if (! rtx_equal_for_memref_p (x1, y1)) + return 1; + x0 = canon_rtx (XEXP (x, 0)); + y0 = canon_rtx (XEXP (y, 0)); + if (rtx_equal_for_memref_p (x0, y0)) + return (xsize == 0 || ysize == 0 + || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)); + + /* Can't properly adjust our sizes. */ + if (GET_CODE (x1) != CONST_INT) + return 1; + xsize /= INTVAL (x1); + ysize /= INTVAL (x1); + c /= INTVAL (x1); + return memrefs_conflict_p (xsize, x0, ysize, y0, c); + } + + case REG: + /* Are these registers known not to be equal? */ + if (alias_invariant) + { + 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]; + i_y = r_y >= reg_base_value_size ? 0 : alias_invariant[r_y]; + + if (i_x == 0 && i_y == 0) + break; + + if (! memrefs_conflict_p (xsize, i_x ? i_x : x, + ysize, i_y ? i_y : y, c)) + return 0; + } + break; + + default: + break; + } + + /* 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). */ + 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 && GET_CODE (XEXP (y, 1)) == CONST_INT) + { + /* XXX: 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); + } + + if (CONSTANT_P (x)) + { + if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT) + { + c += (INTVAL (y) - INTVAL (x)); + return (xsize <= 0 || ysize <= 0 + || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)); + } + + if (GET_CODE (x) == CONST) + { + if (GET_CODE (y) == CONST) + return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)), + ysize, canon_rtx (XEXP (y, 0)), c); + else + return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)), + ysize, y, c); + } + if (GET_CODE (y) == CONST) + return memrefs_conflict_p (xsize, x, ysize, + canon_rtx (XEXP (y, 0)), c); + + if (CONSTANT_P (y)) + return (xsize < 0 || ysize < 0 + || (rtx_equal_for_memref_p (x, y) + && (xsize == 0 || ysize == 0 + || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)))); + + return 1; + } + return 1; +} + +/* Functions to compute memory dependencies. + + Since we process the insns in execution order, we can build tables + to keep track of what registers are fixed (and not aliased), what registers + are varying in known ways, and what registers are varying in unknown + ways. + + If both memory references are volatile, then there must always be a + dependence between the two references, since their order can not be + changed. A volatile and non-volatile reference can be interchanged + though. + + A MEM_IN_STRUCT reference at a non-QImode non-AND varying address can never + conflict with a non-MEM_IN_STRUCT reference at a fixed address. We must + allow QImode aliasing because the ANSI C standard allows character + pointers to alias anything. We are assuming that characters are + always QImode here. We also must allow AND addresses, because they may + generate accesses outside the object being referenced. This is used to + generate aligned addresses from unaligned addresses, for instance, the + alpha storeqi_unaligned pattern. */ + +/* Read dependence: X is read after read in MEM takes place. There can + only be a dependence here if both reads are volatile. */ + +int +read_dependence (mem, x) + rtx mem; + rtx x; +{ + return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem); +} + +/* True dependence: X is read after store in MEM takes place. */ + +int +true_dependence (mem, mem_mode, x, varies) + rtx mem; + enum machine_mode mem_mode; + rtx x; + int (*varies) PROTO((rtx)); +{ + register rtx x_addr, mem_addr; + + if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) + return 1; + + if (DIFFERENT_ALIAS_SETS_P (x, mem)) + return 0; + + /* If X is an unchanging read, then it can't possibly conflict with any + non-unchanging store. It may conflict with an unchanging write though, + because there may be a single store to this address to initialize it. + Just fall through to the code below to resolve the case where we have + both an unchanging read and an unchanging write. This won't handle all + cases optimally, but the possible performance loss should be + negligible. */ + if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem)) + return 0; + + if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0))) + 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)) + 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. */ + + /* 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; + } + + return 1; +} + +/* Anti dependence: X is written after read in MEM takes place. */ + +int +anti_dependence (mem, x) + rtx mem; + rtx x; +{ + rtx x_addr, mem_addr; + + if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) + return 1; + + /* 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)) + return 0; + + 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; + + 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))); +} + +/* Output dependence: X is written after store in MEM takes place. */ + +int +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))); +} + + +static HARD_REG_SET argument_registers; + +void +init_alias_once () +{ + register int i; + +#ifndef OUTGOING_REGNO +#define OUTGOING_REGNO(N) N +#endif + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + /* Check whether this register can hold an incoming pointer + argument. FUNCTION_ARG_REGNO_P tests outgoing register + numbers, so translate if necessary due to register windows. */ + if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i)) + && HARD_REGNO_MODE_OK (i, Pmode)) + SET_HARD_REG_BIT (argument_registers, i); +} + +void +init_alias_analysis () +{ + int maxreg = max_reg_num (); + int changed, pass; + register int i; + register rtx insn; + + reg_known_value_size = maxreg; + + reg_known_value + = (rtx *) oballoc ((maxreg - FIRST_PSEUDO_REGISTER) * sizeof (rtx)) + - FIRST_PSEUDO_REGISTER; + reg_known_equiv_p = + oballoc (maxreg - FIRST_PSEUDO_REGISTER) - FIRST_PSEUDO_REGISTER; + bzero ((char *) (reg_known_value + FIRST_PSEUDO_REGISTER), + (maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx)); + bzero (reg_known_equiv_p + FIRST_PSEUDO_REGISTER, + (maxreg - FIRST_PSEUDO_REGISTER) * sizeof (char)); + + /* Overallocate reg_base_value to allow some growth during loop + optimization. Loop unrolling can create a large number of + registers. */ + reg_base_value_size = maxreg * 2; + reg_base_value = (rtx *)oballoc (reg_base_value_size * sizeof (rtx)); + new_reg_base_value = (rtx *)alloca (reg_base_value_size * sizeof (rtx)); + reg_seen = (char *)alloca (reg_base_value_size); + bzero ((char *) reg_base_value, reg_base_value_size * sizeof (rtx)); + if (! reload_completed && flag_unroll_loops) + { + alias_invariant = (rtx *)xrealloc (alias_invariant, + reg_base_value_size * sizeof (rtx)); + bzero ((char *)alias_invariant, reg_base_value_size * sizeof (rtx)); + } + + + /* The basic idea is that each pass through this loop will use the + "constant" information from the previous pass to propagate alias + information through another level of assignments. + + This could get expensive if the assignment chains are long. Maybe + we should throttle the number of iterations, possibly based on + the optimization level or flag_expensive_optimizations. + + We could propagate more information in the first pass by making use + of REG_N_SETS to determine immediately that the alias information + for a pseudo is "constant". + + A program with an uninitialized variable can cause an infinite loop + here. Instead of doing a full dataflow analysis to detect such problems + we just cap the number of iterations for the loop. + + The state of the arrays for the set chain in question does not matter + since the program has undefined behavior. */ + + pass = 0; + do + { + /* Assume nothing will change this iteration of the loop. */ + changed = 0; + + /* We want to assign the same IDs each iteration of this loop, so + start counting from zero each iteration of the loop. */ + unique_id = 0; + + /* We're at the start of the funtion each iteration through the + loop, so we're copying arguments. */ + copying_arguments = 1; + + /* Wipe the potential alias information clean for this pass. */ + bzero ((char *) new_reg_base_value, reg_base_value_size * sizeof (rtx)); + + /* Wipe the reg_seen array clean. */ + bzero ((char *) reg_seen, reg_base_value_size); + + /* Mark all hard registers which may contain an address. + The stack, frame and argument pointers may contain an address. + An argument register which can hold a Pmode value may contain + an address even if it is not in BASE_REGS. + + The address expression is VOIDmode for an argument and + Pmode for other registers. */ + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (argument_registers, i)) + new_reg_base_value[i] = gen_rtx_ADDRESS (VOIDmode, + gen_rtx_REG (Pmode, i)); + + new_reg_base_value[STACK_POINTER_REGNUM] + = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx); + new_reg_base_value[ARG_POINTER_REGNUM] + = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx); + new_reg_base_value[FRAME_POINTER_REGNUM] + = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx); +#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM + new_reg_base_value[HARD_FRAME_POINTER_REGNUM] + = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx); +#endif + if (struct_value_incoming_rtx + && GET_CODE (struct_value_incoming_rtx) == REG) + new_reg_base_value[REGNO (struct_value_incoming_rtx)] + = gen_rtx_ADDRESS (Pmode, struct_value_incoming_rtx); + + if (static_chain_rtx + && GET_CODE (static_chain_rtx) == REG) + new_reg_base_value[REGNO (static_chain_rtx)] + = gen_rtx_ADDRESS (Pmode, static_chain_rtx); + + /* Walk the insns adding values to the new_reg_base_value array. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') + { + rtx note, set; + /* If this insn has a noalias note, process it, Otherwise, + scan for sets. A simple set will have no side effects + which could change the base value of any other register. */ + + if (GET_CODE (PATTERN (insn)) == SET + && (find_reg_note (insn, REG_NOALIAS, NULL_RTX))) + record_set (SET_DEST (PATTERN (insn)), NULL_RTX); + else + note_stores (PATTERN (insn), record_set); + + set = single_set (insn); + + if (set != 0 + && GET_CODE (SET_DEST (set)) == REG + && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER + && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 + && REG_N_SETS (REGNO (SET_DEST (set))) == 1) + || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0) + && GET_CODE (XEXP (note, 0)) != EXPR_LIST + && ! reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0))) + { + int regno = REGNO (SET_DEST (set)); + reg_known_value[regno] = XEXP (note, 0); + reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV; + } + } + else if (GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) + copying_arguments = 0; + } + + /* Now propagate values from new_reg_base_value to reg_base_value. */ + for (i = 0; i < reg_base_value_size; i++) + { + 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])) + { + reg_base_value[i] = new_reg_base_value[i]; + changed = 1; + } + } + } + while (changed && ++pass < MAX_ALIAS_LOOP_PASSES); + + /* Fill in the remaining entries. */ + for (i = FIRST_PSEUDO_REGISTER; i < maxreg; i++) + if (reg_known_value[i] == 0) + reg_known_value[i] = regno_reg_rtx[i]; + + /* Simplify the reg_base_value array so that no register refers to + another register, except to special registers indirectly through + ADDRESS expressions. + + In theory this loop can take as long as O(registers^2), but unless + there are very long dependency chains it will run in close to linear + time. + + This loop may not be needed any longer now that the main loop does + a better job at propagating alias information. */ + pass = 0; + do + { + changed = 0; + pass++; + for (i = 0; i < reg_base_value_size; i++) + { + rtx base = reg_base_value[i]; + if (base && GET_CODE (base) == REG) + { + int base_regno = REGNO (base); + if (base_regno == i) /* register set from itself */ + reg_base_value[i] = 0; + else + reg_base_value[i] = reg_base_value[base_regno]; + changed = 1; + } + } + } + while (changed && pass < MAX_ALIAS_LOOP_PASSES); + + new_reg_base_value = 0; + reg_seen = 0; +} + +void +end_alias_analysis () +{ + reg_known_value = 0; + reg_base_value = 0; + reg_base_value_size = 0; + if (alias_invariant) + { + free ((char *)alias_invariant); + alias_invariant = 0; + } +} diff --git a/contrib/gcc/alloca.c b/contrib/gcc/alloca.c index 7020f32..8f98b73 100644 --- a/contrib/gcc/alloca.c +++ b/contrib/gcc/alloca.c @@ -25,6 +25,13 @@ #include #endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + #ifdef emacs #include "blockinput.h" #endif @@ -66,7 +73,9 @@ typedef void *pointer; typedef char *pointer; #endif +#ifndef NULL #define NULL 0 +#endif /* Different portions of Emacs need to call different versions of malloc. The Emacs executable needs alloca to call xmalloc, because @@ -171,7 +180,7 @@ alloca (size) #endif /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ + was allocated from deeper in the stack than currently. */ { register header *hp; /* Traverses linked list. */ @@ -209,6 +218,9 @@ alloca (size) register pointer new = malloc (sizeof (header) + size); /* Address of header. */ + if (new == 0) + abort(); + ((header *) new)->h.next = last_alloca_header; ((header *) new)->h.deep = depth; @@ -338,7 +350,7 @@ struct stk_trailer #ifdef CRAY2 /* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ + I doubt that "lint" will like this much. */ static long i00afunc (long *address) diff --git a/contrib/gcc/basic-block.h b/contrib/gcc/basic-block.h index 3755388..552f74a 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 Free Software Foundation, Inc. + Copyright (C) 1987, 1997, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,26 +19,82 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Number of bits in each actual element of a regset. */ +#include "bitmap.h" -#define REGSET_ELT_BITS HOST_BITS_PER_WIDE_INT +typedef bitmap regset; /* Head of register set linked list. */ -/* Type to use for a regset element. Note that lots of code assumes - that the initial part of a regset that contains information on the - hard registers is the same format as a HARD_REG_SET. */ +/* Clear a register set by freeing up the linked list. */ +#define CLEAR_REG_SET(HEAD) bitmap_clear (HEAD) -#define REGSET_ELT_TYPE unsigned HOST_WIDE_INT +/* Copy a register set to another register set. */ +#define COPY_REG_SET(TO, FROM) bitmap_copy (TO, FROM) -/* Define the type for a pointer to a set with a bit for each - (hard or pseudo) register. */ +/* `and' a register set with a second register set. */ +#define AND_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_AND) -typedef REGSET_ELT_TYPE *regset; +/* `and' the complement of a register set with a register set. */ +#define AND_COMPL_REG_SET(TO, FROM) \ + bitmap_operation (TO, TO, FROM, BITMAP_AND_COMPL) -/* Size of a regset for the current function, - in (1) bytes and (2) elements. */ +/* Inclusive or a register set with a second register set. */ +#define IOR_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_IOR) -extern int regset_bytes; -extern int regset_size; +/* Or into TO the register set FROM1 `and'ed with the complement of FROM2. */ +#define IOR_AND_COMPL_REG_SET(TO, FROM1, FROM2) \ + bitmap_ior_and_compl (TO, FROM1, FROM2) + +/* Clear a single register in a register set. */ +#define CLEAR_REGNO_REG_SET(HEAD, REG) bitmap_clear_bit (HEAD, REG) + +/* Set a single register in a register set. */ +#define SET_REGNO_REG_SET(HEAD, REG) bitmap_set_bit (HEAD, REG) + +/* Return true if a register is set in a register set. */ +#define REGNO_REG_SET_P(TO, REG) bitmap_bit_p (TO, REG) + +/* Copy the hard registers in a register set to the hard register set. */ +#define REG_SET_TO_HARD_REG_SET(TO, FROM) \ +do { \ + int i_; \ + CLEAR_HARD_REG_SET (TO); \ + for (i_ = 0; i_ < FIRST_PSEUDO_REGISTER; i_++) \ + if (REGNO_REG_SET_P (FROM, i_)) \ + SET_HARD_REG_BIT (TO, i_); \ +} while (0) + +/* Loop over all registers in REGSET, starting with MIN, setting REGNUM to the + register number and executing CODE for all registers that are set. */ +#define EXECUTE_IF_SET_IN_REG_SET(REGSET, MIN, REGNUM, CODE) \ + EXECUTE_IF_SET_IN_BITMAP (REGSET, MIN, REGNUM, CODE) + +/* Loop over all registers in REGSET1 and REGSET2, starting with MIN, setting + REGNUM to the register number and executing CODE for all registers that are + set in the first regset and not set in the second. */ +#define EXECUTE_IF_AND_COMPL_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, CODE) \ + EXECUTE_IF_AND_COMPL_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, CODE) + +/* Loop over all registers in REGSET1 and REGSET2, starting with MIN, setting + REGNUM to the register number and executing CODE for all registers that are + set in both regsets. */ +#define EXECUTE_IF_AND_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, CODE) \ + EXECUTE_IF_AND_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, CODE) + +/* Allocate a register set with oballoc. */ +#define OBSTACK_ALLOC_REG_SET(OBSTACK) BITMAP_OBSTACK_ALLOC (OBSTACK) + +/* Allocate a register set with alloca. */ +#define ALLOCA_REG_SET() BITMAP_ALLOCA () + +/* Do any cleanup needed on a regset when it is no longer used. */ +#define FREE_REG_SET(REGSET) BITMAP_FREE(REGSET) + +/* Do any one-time initializations needed for regsets. */ +#define INIT_ONCE_REG_SET() BITMAP_INIT_ONCE () + +/* 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) /* Number of basic blocks in the current function. */ @@ -52,11 +108,20 @@ extern rtx *basic_block_head; extern rtx *basic_block_end; +/* Index by basic block number, determine whether the block can be reached + through a computed jump. */ + +extern char *basic_block_computed_jump_target; + /* Index by basic block number, get address of regset describing the registers live at the start of that block. */ extern regset *basic_block_live_at_start; +/* What registers are live at the setjmp call. */ + +extern regset regs_live_at_setjmp; + /* Indexed by n, gives number of basic block that (REG n) is used in. If the value is REG_BLOCK_GLOBAL (-2), it means (REG n) is used in more than one basic block. @@ -66,4 +131,136 @@ extern regset *basic_block_live_at_start; #define REG_BLOCK_UNKNOWN -1 #define REG_BLOCK_GLOBAL -2 -extern int *reg_basic_block; + +#define REG_BASIC_BLOCK(N) (VARRAY_REG (reg_n_info, N)->basic_block) + +/* List of integers. + These are used for storing things like predecessors, etc. + + This scheme isn't very space efficient, especially on 64 bit machines. + The interface is designed so that the implementation can be replaced with + something more efficient if desirable. */ + +typedef struct int_list { + struct int_list *next; + int val; +} int_list; + +typedef int_list *int_list_ptr; + +/* Integer list elements are allocated in blocks to reduce the frequency + of calls to malloc and to reduce the associated space overhead. */ + +typedef struct int_list_block { + struct int_list_block *next; + int nodes_left; +#define INT_LIST_NODES_IN_BLK 500 + struct int_list nodes[INT_LIST_NODES_IN_BLK]; +} int_list_block; + +/* Given a pointer to the list, return pointer to first element. */ +#define INT_LIST_FIRST(il) (il) + +/* Given a pointer to a list element, return pointer to next element. */ +#define INT_LIST_NEXT(p) ((p)->next) + +/* Return non-zero if P points to the end of the list. */ +#define INT_LIST_END(p) ((p) == NULL) + +/* Return element pointed to by P. */ +#define INT_LIST_VAL(p) ((p)->val) + +#define INT_LIST_SET_VAL(p, new_val) ((p)->val = (new_val)) + +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)] + +/* Special block numbers [markers] for entry and exit. */ +#define ENTRY_BLOCK (-1) +#define EXIT_BLOCK (-2) + +/* 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)); + + +/* 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) + +/* 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)) + +/* 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_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, + int_list_ptr *)); +extern void compute_dominators PROTO ((sbitmap *, sbitmap *, + int_list_ptr *, int_list_ptr *)); diff --git a/contrib/gcc/bitmap.c b/contrib/gcc/bitmap.c new file mode 100644 index 0000000..a5aa2e7 --- /dev/null +++ b/contrib/gcc/bitmap.c @@ -0,0 +1,642 @@ +/* Functions to support general ended bitmaps. + Copyright (C) 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 +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 "obstack.h" +#include "regs.h" +#include "basic-block.h" + +/* Obstack to allocate bitmap elements from. */ +static struct obstack bitmap_obstack; +static int bitmap_obstack_init = FALSE; + + +#ifndef INLINE +#ifndef __GNUC__ +#define INLINE +#else +#define INLINE __inline__ +#endif +#endif + +/* Global data */ +bitmap_element bitmap_zero; /* An element of all zero bits. */ +bitmap_element *bitmap_free; /* Freelist of bitmap elements. */ + +static void bitmap_element_free PROTO((bitmap, bitmap_element *)); +static bitmap_element *bitmap_element_allocate PROTO((void)); +static int bitmap_element_zerop PROTO((bitmap_element *)); +static void bitmap_element_link PROTO((bitmap, bitmap_element *)); +static bitmap_element *bitmap_find_bit PROTO((bitmap, unsigned int)); + +/* Free a bitmap element */ + +static INLINE void +bitmap_element_free (head, elt) + bitmap head; + bitmap_element *elt; +{ + bitmap_element *next = elt->next; + bitmap_element *prev = elt->prev; + + if (prev) + prev->next = next; + + if (next) + next->prev = prev; + + if (head->first == elt) + head->first = next; + + /* Since the first thing we try is to insert before current, + make current the next entry in preference to the previous. */ + if (head->current == elt) + head->current = next != 0 ? next : prev; + + elt->next = bitmap_free; + bitmap_free = elt; +} + +/* Allocate a bitmap element. The bits are cleared, but nothing else is. */ + +static INLINE bitmap_element * +bitmap_element_allocate () +{ + bitmap_element *element; +#if BITMAP_ELEMENT_WORDS != 2 + int i; +#endif + + if (bitmap_free != 0) + { + element = bitmap_free; + bitmap_free = element->next; + } + else + { + /* We can't use gcc_obstack_init to initialize the obstack since + print-rtl.c now calls bitmap functions, and bitmap is linked + into the gen* functions. */ + if (!bitmap_obstack_init) + { + bitmap_obstack_init = TRUE; + + /* Let particular systems override the size of a chunk. */ +#ifndef OBSTACK_CHUNK_SIZE +#define OBSTACK_CHUNK_SIZE 0 +#endif + /* Let them override the alloc and free routines too. */ +#ifndef OBSTACK_CHUNK_ALLOC +#define OBSTACK_CHUNK_ALLOC xmalloc +#endif +#ifndef OBSTACK_CHUNK_FREE +#define OBSTACK_CHUNK_FREE free +#endif + +#if !defined(__GNUC__) || (__GNUC__ < 2) +#define __alignof__(type) 0 +#endif + + obstack_specify_allocation (&bitmap_obstack, OBSTACK_CHUNK_SIZE, + __alignof__ (bitmap_element), + (void *(*) ()) OBSTACK_CHUNK_ALLOC, + (void (*) ()) OBSTACK_CHUNK_FREE); + } + + element = (bitmap_element *) obstack_alloc (&bitmap_obstack, + sizeof (bitmap_element)); + } + +#if BITMAP_ELEMENT_WORDS == 2 + element->bits[0] = element->bits[1] = 0; +#else + for (i = 0; i < BITMAP_ELEMENT_WORDS; i++) + element->bits[i] = 0; +#endif + + return element; +} + +/* Return nonzero if all bits in an element are zero. */ + +static INLINE int +bitmap_element_zerop (element) + bitmap_element *element; +{ +#if BITMAP_ELEMENT_WORDS == 2 + return (element->bits[0] | element->bits[1]) == 0; +#else + int i; + + for (i = 0; i < BITMAP_ELEMENT_WORDS; i++) + if (element->bits[i] != 0) + return 0; + + return 1; +#endif +} + +/* Link the bitmap element into the current bitmap linked list. */ + +static INLINE void +bitmap_element_link (head, element) + bitmap head; + bitmap_element *element; +{ + unsigned int indx = element->indx; + bitmap_element *ptr; + + /* If this is the first and only element, set it in. */ + if (head->first == 0) + { + element->next = element->prev = 0; + head->first = element; + } + + /* If this index is less than that of the current element, it goes someplace + before the current element. */ + else if (indx < head->indx) + { + for (ptr = head->current; + ptr->prev != 0 && ptr->prev->indx > indx; + ptr = ptr->prev) + ; + + if (ptr->prev) + ptr->prev->next = element; + else + head->first = element; + + element->prev = ptr->prev; + element->next = ptr; + ptr->prev = element; + } + + /* Otherwise, it must go someplace after the current element. */ + else + { + for (ptr = head->current; + ptr->next != 0 && ptr->next->indx < indx; + ptr = ptr->next) + ; + + if (ptr->next) + ptr->next->prev = element; + + element->next = ptr->next; + element->prev = ptr; + ptr->next = element; + } + + /* Set up so this is the first element searched. */ + head->current = element; + head->indx = indx; +} + +/* Clear a bitmap by freeing the linked list. */ + +INLINE void +bitmap_clear (head) + bitmap head; +{ + bitmap_element *element, *next; + + for (element = head->first; element != 0; element = next) + { + next = element->next; + element->next = bitmap_free; + bitmap_free = element; + } + + head->first = head->current = 0; +} + +/* Copy a bitmap to another bitmap */ + +void +bitmap_copy (to, from) + bitmap to; + bitmap from; +{ + bitmap_element *from_ptr, *to_ptr = 0; +#if BITMAP_ELEMENT_WORDS != 2 + int i; +#endif + + bitmap_clear (to); + + /* Copy elements in forward direction one at a time */ + for (from_ptr = from->first; from_ptr; from_ptr = from_ptr->next) + { + bitmap_element *to_elt = bitmap_element_allocate (); + + to_elt->indx = from_ptr->indx; + +#if BITMAP_ELEMENT_WORDS == 2 + to_elt->bits[0] = from_ptr->bits[0]; + to_elt->bits[1] = from_ptr->bits[1]; +#else + for (i = 0; i < BITMAP_ELEMENT_WORDS; i++) + to_elt->bits[i] = from_ptr->bits[i]; +#endif + + /* Here we have a special case of bitmap_element_link, for the case + where we know the links are being entered in sequence. */ + if (to_ptr == 0) + { + to->first = to->current = to_elt; + to->indx = from_ptr->indx; + to_elt->next = to_elt->prev = 0; + } + else + { + to_elt->prev = to_ptr; + to_elt->next = 0; + to_ptr->next = to_elt; + } + + to_ptr = to_elt; + } +} + +/* Find a bitmap element that would hold a bitmap's bit. + Update the `current' field even if we can't find an element that + would hold the bitmap's bit to make eventual allocation + faster. */ + +static INLINE bitmap_element * +bitmap_find_bit (head, bit) + bitmap head; + unsigned int bit; +{ + bitmap_element *element; + unsigned HOST_WIDE_INT indx = bit / BITMAP_ELEMENT_ALL_BITS; + + if (head->current == 0) + return 0; + + if (head->indx > indx) + for (element = head->current; + element->prev != 0 && element->indx > indx; + element = element->prev) + ; + + else + for (element = head->current; + element->next != 0 && element->indx < indx; + element = element->next) + ; + + /* `element' is the nearest to the one we want. If it's not the one we + want, the one we want doesn't exist. */ + head->current = element; + head->indx = element->indx; + if (element != 0 && element->indx != indx) + element = 0; + + return element; +} + +/* Clear a single bit in a bitmap. */ + +void +bitmap_clear_bit (head, bit) + bitmap head; + int bit; +{ + bitmap_element *ptr = bitmap_find_bit (head, bit); + + if (ptr != 0) + { + unsigned bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT; + unsigned word_num = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) + % BITMAP_ELEMENT_WORDS); + ptr->bits[word_num] &= ~ (((unsigned HOST_WIDE_INT) 1) << bit_num); + + /* If we cleared the entire word, free up the element */ + if (bitmap_element_zerop (ptr)) + bitmap_element_free (head, ptr); + } +} + + +/* Set a single bit in a bitmap. */ + +void +bitmap_set_bit (head, bit) + bitmap head; + int bit; +{ + bitmap_element *ptr = bitmap_find_bit (head, bit); + unsigned word_num + = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) % BITMAP_ELEMENT_WORDS); + unsigned bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT; + unsigned HOST_WIDE_INT bit_val = ((unsigned HOST_WIDE_INT) 1) << bit_num; + + if (ptr == 0) + { + ptr = bitmap_element_allocate (); + ptr->indx = bit / BITMAP_ELEMENT_ALL_BITS; + ptr->bits[word_num] = bit_val; + bitmap_element_link (head, ptr); + } + else + ptr->bits[word_num] |= bit_val; +} + +/* Return whether a bit is set within a bitmap. */ + +int +bitmap_bit_p (head, bit) + bitmap head; + int bit; +{ + bitmap_element *ptr; + unsigned bit_num; + unsigned word_num; + + ptr = bitmap_find_bit (head, bit); + if (ptr == 0) + return 0; + + bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT; + word_num + = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) % BITMAP_ELEMENT_WORDS); + + return + (ptr->bits[word_num] & (((unsigned HOST_WIDE_INT) 1) << bit_num)) != 0; +} + +/* Store in bitmap TO the result of combining bitmap FROM1 and + FROM2 using a specific bit manipulation. */ + +void +bitmap_operation (to, from1, from2, operation) + bitmap to; + bitmap from1; + bitmap from2; + enum bitmap_bits operation; +{ + bitmap_element *delete_list = 0; + bitmap_element *from1_ptr = from1->first; + bitmap_element *from2_ptr = from2->first; + unsigned int indx1 + = (from1_ptr) ? from1_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0; + unsigned int indx2 + = (from2_ptr) ? from2_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0; + bitmap_element *to_ptr = 0; + bitmap_element *from1_tmp; + bitmap_element *from2_tmp; + unsigned int indx; +#if BITMAP_ELEMENT_WORDS != 2 + int i; +#endif + + /* To simplify things, always create a new list. If the old list was one + of the inputs, free it later. Otherwise, free it now. */ + if (to == from1 || to == from2) + { + delete_list = to->first; + to->first = to->current = 0; + } + else + bitmap_clear (to); + + while (from1_ptr != 0 || from2_ptr != 0) + { + /* Figure out whether we need to substitute zero elements for + missing links. */ + if (indx1 == indx2) + { + indx = indx1; + from1_tmp = from1_ptr; + from2_tmp = from2_ptr; + from1_ptr = from1_ptr->next; + indx1 = (from1_ptr) ? from1_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0; + from2_ptr = from2_ptr->next; + indx2 = (from2_ptr) ? from2_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0; + } + else if (indx1 < indx2) + { + indx = indx1; + from1_tmp = from1_ptr; + from2_tmp = &bitmap_zero; + from1_ptr = from1_ptr->next; + indx1 = (from1_ptr) ? from1_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0; + } + else + { + indx = indx2; + from1_tmp = &bitmap_zero; + from2_tmp = from2_ptr; + from2_ptr = from2_ptr->next; + indx2 = (from2_ptr) ? from2_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0; + } + + if (to_ptr == 0) + to_ptr = bitmap_element_allocate (); + + /* Do the operation, and if any bits are set, link it into the + linked list. */ + switch (operation) + { + default: + abort (); + + case BITMAP_AND: +#if BITMAP_ELEMENT_WORDS == 2 + to_ptr->bits[0] = from1_tmp->bits[0] & from2_tmp->bits[0]; + to_ptr->bits[1] = from1_tmp->bits[1] & from2_tmp->bits[1]; +#else + for (i = BITMAP_ELEMENT_WORDS - 1; i >= 0; i--) + to_ptr->bits[i] = from1_tmp->bits[i] & from2_tmp->bits[i]; +#endif + break; + + case BITMAP_AND_COMPL: +#if BITMAP_ELEMENT_WORDS == 2 + to_ptr->bits[0] = from1_tmp->bits[0] & ~ from2_tmp->bits[0]; + to_ptr->bits[1] = from1_tmp->bits[1] & ~ from2_tmp->bits[1]; +#else + for (i = BITMAP_ELEMENT_WORDS - 1; i >= 0; i--) + to_ptr->bits[i] = from1_tmp->bits[i] & ~ from2_tmp->bits[i]; +#endif + break; + + case BITMAP_IOR: +#if BITMAP_ELEMENT_WORDS == 2 + to_ptr->bits[0] = from1_tmp->bits[0] | from2_tmp->bits[0]; + to_ptr->bits[1] = from1_tmp->bits[1] | from2_tmp->bits[1]; +#else + for (i = BITMAP_ELEMENT_WORDS - 1; i >= 0; i--) + to_ptr->bits[i] = from1_tmp->bits[i] | from2_tmp->bits[i]; +#endif + break; + } + + if (! bitmap_element_zerop (to_ptr)) + { + to_ptr->indx = indx; + bitmap_element_link (to, to_ptr); + to_ptr = 0; + } + } + + /* If we have an unallocated element due to the last element being 0, + release it back to the free pool. Don't bother calling + bitmap_element_free since it was never linked into a bitmap. */ + if (to_ptr != 0) + { + to_ptr->next = bitmap_free; + bitmap_free = to_ptr; + } + + /* If the output bitmap was one of the inputs, free up its + elements now that we're done. */ + for (; delete_list != 0; delete_list = to_ptr) + { + to_ptr = delete_list->next; + delete_list->next = bitmap_free; + bitmap_free = delete_list; + } +} + +/* Or into bitmap TO bitmap FROM1 and'ed with the complement of + bitmap FROM2. */ + +void +bitmap_ior_and_compl (to, from1, from2) + bitmap to; + bitmap from1; + bitmap from2; +{ + bitmap_head tmp; + + tmp.first = tmp.current = 0; + + bitmap_operation (&tmp, from1, from2, BITMAP_AND_COMPL); + bitmap_operation (to, to, &tmp, BITMAP_IOR); + bitmap_clear (&tmp); +} + +/* Initialize a bitmap header. */ + +bitmap +bitmap_initialize (head) + bitmap head; +{ + head->first = head->current = 0; + + return head; +} + +/* Debugging function to print out the contents of a bitmap. */ + +void +bitmap_debug_file (file, head) + FILE *file; + bitmap head; +{ + bitmap_element *ptr; + + fprintf (file, "\nfirst = "); + fprintf (file, HOST_PTR_PRINTF, head->first); + fprintf (file, " current = "); + fprintf (file, HOST_PTR_PRINTF, head->current); + fprintf (file, " indx = %u\n", head->indx); + + for (ptr = head->first; ptr; ptr = ptr->next) + { + int i, j, col = 26; + + fprintf (file, "\t"); + fprintf (file, HOST_PTR_PRINTF, ptr); + fprintf (file, " next = "); + fprintf (file, HOST_PTR_PRINTF, ptr->next); + fprintf (file, " prev = "); + fprintf (file, HOST_PTR_PRINTF, ptr->prev); + fprintf (file, " indx = %u\n\t\tbits = {", ptr->indx); + + for (i = 0; i < BITMAP_ELEMENT_WORDS; i++) + for (j = 0; j < HOST_BITS_PER_WIDE_INT; j++) + if ((ptr->bits[i] & (((unsigned HOST_WIDE_INT) 1) << j)) != 0) + { + if (col > 70) + { + fprintf (file, "\n\t\t\t"); + col = 24; + } + + fprintf (file, " %u", (ptr->indx * BITMAP_ELEMENT_ALL_BITS + + i * HOST_BITS_PER_WIDE_INT + j)); + col += 4; + } + + fprintf (file, " }\n"); + } +} + +/* Function to be called from the debugger to print the contents + of a bitmap. */ + +void +debug_bitmap (head) + bitmap head; +{ + bitmap_debug_file (stdout, head); +} + +/* Function to print out the contents of a bitmap. Unlike bitmap_debug_file, + it does not print anything but the bits. */ + +void +bitmap_print (file, head, prefix, suffix) + FILE *file; + bitmap head; + char *prefix; + char *suffix; +{ + char *comma = ""; + int i; + + fputs (prefix, file); + EXECUTE_IF_SET_IN_BITMAP (head, 0, i, + { + fprintf (file, "%s%d", comma, i); + comma = ", "; + }); + fputs (suffix, file); +} + +/* Release any memory allocated by bitmaps. */ + +void +bitmap_release_memory () +{ + bitmap_free = 0; + if (bitmap_obstack_init) + { + bitmap_obstack_init = FALSE; + obstack_free (&bitmap_obstack, NULL_PTR); + } +} diff --git a/contrib/gcc/bitmap.h b/contrib/gcc/bitmap.h new file mode 100644 index 0000000..2941574 --- /dev/null +++ b/contrib/gcc/bitmap.h @@ -0,0 +1,317 @@ +/* Functions to support general ended bitmaps. + Copyright (C) 1997 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. */ + +/* Number of words to use for each element in the linked list. */ + +#ifndef BITMAP_ELEMENT_WORDS +#define BITMAP_ELEMENT_WORDS 2 +#endif + +/* Number of bits in each actual element of a bitmap. We get slightly better + code for bit % BITMAP_ELEMENT_ALL_BITS and bit / BITMAP_ELEMENT_ALL_BITS if + bits is unsigned, assuming it is a power of 2. */ + +#define BITMAP_ELEMENT_ALL_BITS \ + ((unsigned) (BITMAP_ELEMENT_WORDS * HOST_BITS_PER_WIDE_INT)) + +/* Bitmap set element. We use a linked list to hold only the bits that + are set. This allows for use to grow the bitset dynamically without + having to realloc and copy a giant bit array. The `prev' field is + undefined for an element on the free list. */ + +typedef struct bitmap_element_def +{ + struct bitmap_element_def *next; /* Next element. */ + struct bitmap_element_def *prev; /* Previous element. */ + unsigned int indx; /* regno/BITMAP_ELEMENT_ALL_BITS. */ + unsigned HOST_WIDE_INT bits[BITMAP_ELEMENT_WORDS]; /* Bits that are set. */ +} bitmap_element; + +/* Head of bitmap linked list. */ +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. */ +} bitmap_head, *bitmap; + +/* Enumeration giving the various operations we support. */ +enum bitmap_bits { + BITMAP_AND, /* TO = FROM1 & FROM2 */ + BITMAP_AND_COMPL, /* TO = FROM1 & ~ FROM2 */ + BITMAP_IOR /* TO = FROM1 | FROM2 */ +}; + +/* Global data */ +extern bitmap_element *bitmap_free; /* Freelist of bitmap elements */ +extern bitmap_element bitmap_zero; /* Zero bitmap element */ + +/* Clear a bitmap by freeing up the linked list. */ +extern void bitmap_clear PROTO((bitmap)); + +/* Copy a bitmap to another bitmap. */ +extern void bitmap_copy PROTO((bitmap, bitmap)); + +/* Perform an operation on two bitmaps, yielding a third. */ +extern void bitmap_operation PROTO((bitmap, bitmap, bitmap, enum bitmap_bits)); + +/* `or' into one bitmap the `and' of a second bitmap witih the complement + of a third. */ +extern void bitmap_ior_and_compl PROTO((bitmap, bitmap, bitmap)); + +/* Clear a single register in a register set. */ +extern void bitmap_clear_bit PROTO((bitmap, int)); + +/* Set a single register in a register set. */ +extern void bitmap_set_bit PROTO((bitmap, int)); + +/* Return true if a register is set in a register set. */ +extern int bitmap_bit_p PROTO((bitmap, int)); + +/* Debug functions to print a bitmap linked list. */ +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 *)); + +/* Initialize a bitmap header. */ +extern bitmap bitmap_initialize PROTO((bitmap)); + +/* Release all memory held by bitmaps. */ +extern void bitmap_release_memory PROTO((void)); + +extern void debug_bitmap PROTO((bitmap)); + +/* Allocate a bitmap with oballoc. */ +#define BITMAP_OBSTACK_ALLOC(OBSTACK) \ + bitmap_initialize ((bitmap) obstack_alloc (OBSTACK, sizeof (bitmap_head))) + +/* Allocate a bitmap with alloca. */ +#define BITMAP_ALLOCA() \ + bitmap_initialize ((bitmap) alloca (sizeof (bitmap_head))) + +/* Do any cleanup needed on a bitmap when it is no longer used. */ +#define BITMAP_FREE(BITMAP) \ +do { \ + if (BITMAP) \ + { \ + bitmap_clear (BITMAP); \ + (BITMAP) = 0; \ + } \ +} while (0) + +/* Do any one-time initializations needed for bitmaps. */ +#define BITMAP_INIT_ONCE() + +/* Loop over all bits in BITMAP, starting with MIN, setting BITNUM to the + bit number and executing CODE for all bits that are set. */ + +#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, CODE) \ +do { \ + bitmap_element *ptr_ = (BITMAP)->first; \ + unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \ + unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \ + unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \ + % BITMAP_ELEMENT_WORDS); \ + \ + \ + /* Find the block the minimum bit is in. */ \ + while (ptr_ != 0 && ptr_->indx < indx_) \ + ptr_ = ptr_->next; \ + \ + if (ptr_ != 0 && ptr_->indx != indx_) \ + { \ + bit_num_ = 0; \ + word_num_ = 0; \ + } \ + \ + for (; ptr_ != 0; ptr_ = ptr_->next) \ + { \ + for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \ + { \ + unsigned HOST_WIDE_INT word_ = ptr_->bits[word_num_]; \ + \ + if (word_ != 0) \ + { \ + for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \ + { \ + unsigned HOST_WIDE_INT mask_ \ + = ((unsigned HOST_WIDE_INT) 1) << bit_num_; \ + \ + if ((word_ & mask_) != 0) \ + { \ + word_ &= ~ mask_; \ + (BITNUM) = (ptr_->indx * BITMAP_ELEMENT_ALL_BITS \ + + word_num_ * HOST_BITS_PER_WIDE_INT \ + + bit_num_); \ + CODE; \ + \ + if (word_ == 0) \ + break; \ + } \ + } \ + } \ + \ + bit_num_ = 0; \ + } \ + \ + word_num_ = 0; \ + } \ +} while (0) + +/* Loop over all bits in BITMAP1 and BITMAP2, starting with MIN, setting + BITNUM to the bit number and executing CODE for all bits that are set in + the first bitmap and not set in the second. */ + +#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, CODE) \ +do { \ + bitmap_element *ptr1_ = (BITMAP1)->first; \ + bitmap_element *ptr2_ = (BITMAP2)->first; \ + unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \ + unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \ + unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \ + % BITMAP_ELEMENT_WORDS); \ + \ + /* Find the block the minimum bit is in in the first bitmap. */ \ + while (ptr1_ != 0 && ptr1_->indx < indx_) \ + ptr1_ = ptr1_->next; \ + \ + if (ptr1_ != 0 && ptr1_->indx != indx_) \ + { \ + bit_num_ = 0; \ + word_num_ = 0; \ + } \ + \ + for (; ptr1_ != 0 ; ptr1_ = ptr1_->next) \ + { \ + /* Advance BITMAP2 to the equivalent link, using an all \ + zero element if an equivalent link doesn't exist. */ \ + bitmap_element *tmp2_; \ + \ + while (ptr2_ != 0 && ptr2_->indx < ptr1_->indx) \ + ptr2_ = ptr2_->next; \ + \ + tmp2_ = ((ptr2_ != 0 && ptr2_->indx == ptr1_->indx) \ + ? ptr2_ : &bitmap_zero); \ + \ + for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \ + { \ + unsigned HOST_WIDE_INT word_ = (ptr1_->bits[word_num_] \ + & ~ tmp2_->bits[word_num_]); \ + if (word_ != 0) \ + { \ + for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \ + { \ + unsigned HOST_WIDE_INT mask_ \ + = ((unsigned HOST_WIDE_INT)1) << bit_num_; \ + \ + if ((word_ & mask_) != 0) \ + { \ + word_ &= ~ mask_; \ + (BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \ + + word_num_ * HOST_BITS_PER_WIDE_INT \ + + bit_num_); \ + \ + CODE; \ + if (word_ == 0) \ + break; \ + } \ + } \ + } \ + \ + bit_num_ = 0; \ + } \ + \ + word_num_ = 0; \ + } \ +} while (0) + +/* Loop over all bits in BITMAP1 and BITMAP2, starting with MIN, setting + BITNUM to the bit number and executing CODE for all bits that are set in + the both bitmaps. */ + +#define EXECUTE_IF_AND_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, CODE) \ +do { \ + bitmap_element *ptr1_ = (BITMAP1)->first; \ + bitmap_element *ptr2_ = (BITMAP2)->first; \ + unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \ + unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \ + unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \ + % BITMAP_ELEMENT_WORDS); \ + \ + /* Find the block the minimum bit is in in the first bitmap. */ \ + while (ptr1_ != 0 && ptr1_->indx < indx_) \ + ptr1_ = ptr1_->next; \ + \ + if (ptr1_ != 0 && ptr1_->indx != indx_) \ + { \ + bit_num_ = 0; \ + word_num_ = 0; \ + } \ + \ + for (; ptr1_ != 0 ; ptr1_ = ptr1_->next) \ + { \ + /* Advance BITMAP2 to the equivalent link */ \ + while (ptr2_ != 0 && ptr2_->indx < ptr1_->indx) \ + ptr2_ = ptr2_->next; \ + \ + if (ptr2_ == 0) \ + { \ + /* If there are no more elements in BITMAP2, exit loop now.*/ \ + ptr1_ = (bitmap_element *)0; \ + break; \ + } \ + else if (ptr2_->indx > ptr1_->indx) \ + { \ + bit_num_ = word_num_ = 0; \ + continue; \ + } \ + \ + for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \ + { \ + unsigned HOST_WIDE_INT word_ = (ptr1_->bits[word_num_] \ + & ptr2_->bits[word_num_]); \ + if (word_ != 0) \ + { \ + for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \ + { \ + unsigned HOST_WIDE_INT mask_ \ + = ((unsigned HOST_WIDE_INT)1) << bit_num_; \ + \ + if ((word_ & mask_) != 0) \ + { \ + word_ &= ~ mask_; \ + (BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \ + + word_num_ * HOST_BITS_PER_WIDE_INT \ + + bit_num_); \ + \ + CODE; \ + if (word_ == 0) \ + break; \ + } \ + } \ + } \ + \ + bit_num_ = 0; \ + } \ + \ + word_num_ = 0; \ + } \ +} while (0) diff --git a/contrib/gcc/build-make b/contrib/gcc/build-make index 1d6e18b..f9049ae 100644 --- a/contrib/gcc/build-make +++ b/contrib/gcc/build-make @@ -1,5 +1,5 @@ # We have to use the cross-compiler we just built to compile it. -CC = gcc -b $(target) +CC = gcc -b $(host) # Need those to compile binaries running on host machine. # It is configured by @@ -24,9 +24,12 @@ HOST_OBSTACK=$(OBSTACK) # target. FIXINCLUDES=Makefile.in +# Don't run fixproto either +STMP_FIXPROTO = + # Cause installation using install-build. We do nothing here. -INSTALL_TARGET = install-build +#INSTALL_TARGET = install-build # Don't try to compile the things we can't compile or we have made # while making gcc with the cross-compiler. -ALL = all.build +#ALL = all.build diff --git a/contrib/gcc/c-aux-info.c b/contrib/gcc/c-aux-info.c index d8caa6a..3e2edde 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, 1991, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1989, 91, 94, 95, 97, 1998 Free Software Foundation, Inc. Contributed by Ron Guilmette (rfg@segfault.us.com). This file is part of GNU CC. @@ -21,14 +21,12 @@ 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 #include "config.h" +#include "system.h" #include "flags.h" #include "tree.h" #include "c-tree.h" -extern char* xmalloc (); - enum formals_style_enum { ansi, k_and_r_names, @@ -37,26 +35,26 @@ enum formals_style_enum { typedef enum formals_style_enum formals_style; -static char* data_type; +static char *data_type; -static char * concat (); -static char * concat3 (); -static char * gen_formal_list_for_type (); -static int deserves_ellipsis (); -static char * gen_formal_list_for_func_def (); -static char * gen_type (); -static char * gen_decl (); -void gen_aux_info_record (); +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 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)); /* Take two strings and mash them together into a newly allocated area. */ -static char* +static char * concat (s1, s2) - char* s1; - char* s2; + char *s1; + char *s2; { int size1, size2; - char* ret_val; + char *ret_val; if (!s1) s1 = ""; @@ -73,14 +71,14 @@ concat (s1, s2) /* Take three strings and mash them together into a newly allocated area. */ -static char* +static char * concat3 (s1, s2, s3) - char* s1; - char* s2; - char* s3; + char *s1; + char *s2; + char *s3; { int size1, size2, size3; - char* ret_val; + char *ret_val; if (!s1) s1 = ""; @@ -113,7 +111,7 @@ concat3 (s1, s2, s3) `const char *foo;' and *not* `char const *foo;' so we try to create types that look as expected. */ -static char* +static char * affix_data_type (type_or_decl) char *type_or_decl; { @@ -156,14 +154,14 @@ affix_data_type (type_or_decl) this function type. Return the whole formal parameter list (including a pair of surrounding parens) as a string. Note that if the style we are currently aiming for is non-ansi, then we just return a pair - of empty parens here. */ + of empty parens here. */ -static char* +static char * gen_formal_list_for_type (fntype, style) tree fntype; formals_style style; { - char* formal_list = ""; + char *formal_list = ""; tree formal_type; if (style != ansi) @@ -172,16 +170,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; + char *this_type; if (*formal_list) formal_list = concat (formal_list, ", "); 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); + formal_list + = ((strlen (this_type)) + ? concat (formal_list, affix_data_type (this_type)) + : concat (formal_list, data_type)); formal_type = TREE_CHAIN (formal_type); } @@ -278,12 +276,12 @@ deserves_ellipsis (fntype) This routine returns a string which is the source form for the entire function formal parameter list. */ -static char* +static char * gen_formal_list_for_func_def (fndecl, style) tree fndecl; formals_style style; { - char* formal_list = ""; + char *formal_list = ""; tree formal_decl; formal_decl = DECL_ARGUMENTS (fndecl); @@ -353,15 +351,16 @@ 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 char * gen_type (ret_val, t, style) - char* ret_val; + char *ret_val; tree t; formals_style style; { tree chain_p; - if (TYPE_NAME (t) && DECL_NAME (TYPE_NAME (t))) + /* If there is a typedef name for this type, use it. */ + if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); else { @@ -517,13 +516,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 char * gen_decl (decl, is_func_definition, style) tree decl; int is_func_definition; formals_style style; { - char* ret_val; + char *ret_val; if (DECL_NAME (decl)) ret_val = IDENTIFIER_POINTER (DECL_NAME (decl)); @@ -581,7 +580,7 @@ gen_decl (decl, is_func_definition, style) ret_val = affix_data_type (ret_val); - if (DECL_REGISTER (decl)) + if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) ret_val = concat ("register ", ret_val); if (TREE_PUBLIC (decl)) ret_val = concat ("extern ", ret_val); @@ -591,7 +590,7 @@ gen_decl (decl, is_func_definition, style) return ret_val; } -extern FILE* aux_info_file; +extern FILE *aux_info_file; /* Generate and write a new line of info to the aux-info (.X) file. This routine is called once for each function declaration, and once for each diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c index 78b4d85..61600fb 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, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,24 +19,139 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "tree.h" #include "c-lex.h" #include "c-tree.h" #include "flags.h" #include "obstack.h" -#include -#include +#include "toplev.h" +#include "output.h" + +#if USE_CPPLIB +#include "cpplib.h" +cpp_reader parse_in; +cpp_options parse_options; +static enum cpp_token cpp_token; +#endif + +#ifndef WCHAR_TYPE_SIZE +#ifdef INT_TYPE_SIZE +#define WCHAR_TYPE_SIZE INT_TYPE_SIZE +#else +#define WCHAR_TYPE_SIZE BITS_PER_WORD +#endif +#endif extern struct obstack permanent_obstack; -enum attrs {A_PACKED, A_NOCOMMON, A_NORETURN, A_CONST, A_T_UNION, +/* Nonzero means the expression being parsed will never be evaluated. + This is a count, since unevaluated expressions can nest. */ +int skip_evaluation; + +enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION, A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED, - A_UNUSED, A_FORMAT, A_WEAK, A_ALIAS}; + 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 *, 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)); + +/* 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 + and file of the if. If a potentially ambiguous else is seen, that + fact is recorded; the warning is issued when we can be sure that + the enclosing if statement does not have an else branch. */ +typedef struct +{ + int compstmt_count; + int line; + char *file; + int needs_warning; +} if_elt; + +static if_elt *if_stack; + +/* Amount of space in the if statement stack. */ +static int if_stack_space = 0; + +/* Stack pointer. */ +static int if_stack_pointer = 0; + +/* Generate RTL for the start of an if-then, and record the start of it + for ambiguous else detection. */ + +void +c_expand_start_cond (cond, exitflag, compstmt_count) + tree cond; + int exitflag; + int compstmt_count; +{ + /* Make sure there is enough space on the stack. */ + if (if_stack_space == 0) + { + if_stack_space = 10; + if_stack = (if_elt *)xmalloc (10 * sizeof (if_elt)); + } + else if (if_stack_space == if_stack_pointer) + { + if_stack_space += 10; + if_stack = (if_elt *)xrealloc (if_stack, if_stack_space * sizeof (if_elt)); + } + + /* Record this if statement. */ + if_stack[if_stack_pointer].compstmt_count = compstmt_count; + if_stack[if_stack_pointer].file = input_filename; + if_stack[if_stack_pointer].line = lineno; + if_stack[if_stack_pointer].needs_warning = 0; + if_stack_pointer++; + + expand_start_cond (cond, exitflag); +} + +/* Generate RTL for the end of an if-then. Optionally warn if a nested + if statement had an ambiguous else clause. */ + +void +c_expand_end_cond () +{ + if_stack_pointer--; + if (if_stack[if_stack_pointer].needs_warning) + warning_with_file_and_line (if_stack[if_stack_pointer].file, + if_stack[if_stack_pointer].line, + "suggest explicit braces to avoid ambiguous `else'"); + expand_end_cond (); +} + +/* Generate RTL between the then-clause and the else-clause + of an if-then-else. */ + +void +c_expand_start_else () +{ + /* An ambiguous else warning must be generated for the enclosing if + statement, unless we see an else branch for that one, too. */ + if (warn_parentheses + && if_stack_pointer > 1 + && (if_stack[if_stack_pointer - 1].compstmt_count + == if_stack[if_stack_pointer - 2].compstmt_count)) + if_stack[if_stack_pointer - 2].needs_warning = 1; + + /* Even if a nested if statement had an else branch, it can't be + ambiguous if this one also has an else. So don't warn in that + case. Also don't warn for any if statements nested in this else. */ + if_stack[if_stack_pointer - 1].needs_warning = 0; + if_stack[if_stack_pointer - 1].compstmt_count--; + + expand_start_else (); +} /* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ @@ -52,15 +167,12 @@ declare_function_name () } else { - char *kind = "function"; - if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) - kind = "method"; /* Allow functions to be nameless (such as artificial ones). */ if (DECL_NAME (current_function_decl)) name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); else name = ""; - printable_name = (*decl_printable_name) (current_function_decl, &kind); + printable_name = (*decl_printable_name) (current_function_decl, 2); } declare_hidden_char_array ("__FUNCTION__", name); @@ -78,7 +190,7 @@ declare_hidden_char_array (name, value) or if we want to give warnings for large objects, make a bigger one. */ vlen = strlen (value) + 1; type = char_array_type_node; - if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (type))) < vlen + if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < vlen || warn_larger_than) type = build_array_type (char_type_node, build_index_type (build_int_2 (vlen, 0))); @@ -157,7 +269,12 @@ combine_strings (strings) { int i; for (i = 0; i < len; i++) - ((int *) q)[i] = TREE_STRING_POINTER (t)[i]; + { + if (WCHAR_TYPE_SIZE == HOST_BITS_PER_SHORT) + ((short *) q)[i] = TREE_STRING_POINTER (t)[i]; + else + ((int *) q)[i] = TREE_STRING_POINTER (t)[i]; + } q += len * wchar_bytes; } } @@ -183,7 +300,7 @@ combine_strings (strings) wide_flag = 1; } - /* Compute the number of elements, for the array type. */ + /* Compute the number of elements, for the array type. */ nchars = wide_flag ? length / wchar_bytes : length; /* Create the array type for the string constant. @@ -250,9 +367,10 @@ init_attributes () { add_attribute (A_PACKED, "packed", 0, 0, 0); add_attribute (A_NOCOMMON, "nocommon", 0, 0, 1); + add_attribute (A_COMMON, "common", 0, 0, 1); add_attribute (A_NORETURN, "noreturn", 0, 0, 1); add_attribute (A_NORETURN, "volatile", 0, 0, 1); - add_attribute (A_UNUSED, "unused", 0, 0, 1); + add_attribute (A_UNUSED, "unused", 0, 0, 0); add_attribute (A_CONST, "const", 0, 0, 1); add_attribute (A_T_UNION, "transparent_union", 0, 0, 0); add_attribute (A_CONSTRUCTOR, "constructor", 0, 0, 1); @@ -261,6 +379,7 @@ init_attributes () add_attribute (A_SECTION, "section", 1, 1, 1); add_attribute (A_ALIGNED, "aligned", 0, 1, 0); add_attribute (A_FORMAT, "format", 3, 3, 1); + 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); } @@ -268,14 +387,14 @@ init_attributes () /* 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 - and declaration modifiers but before the declaration proper. */ + and declaration modifiers but before the declaration proper. */ void decl_attributes (node, attributes, prefix_attributes) tree node, attributes, prefix_attributes; { - tree decl = 0, type; - int is_type; + tree decl = 0, type = 0; + int is_type = 0; tree a; if (attrtab_idx == 0) @@ -298,7 +417,7 @@ decl_attributes (node, attributes, prefix_attributes) tree args = TREE_VALUE (a); int i; enum attrs id; - + for (i = 0; i < attrtab_idx; i++) if (attrtab[i].name == name) break; @@ -308,6 +427,8 @@ decl_attributes (node, attributes, prefix_attributes) if (! valid_machine_attribute (name, args, decl, type)) warning ("`%s' attribute directive ignored", IDENTIFIER_POINTER (name)); + else if (decl != 0) + type = TREE_TYPE (decl); continue; } else if (attrtab[i].decl_req && decl == 0) @@ -345,12 +466,19 @@ decl_attributes (node, attributes, prefix_attributes) warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); break; + case A_COMMON: + if (TREE_CODE (decl) == VAR_DECL) + DECL_COMMON (decl) = 1; + else + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + break; + case A_NORETURN: if (TREE_CODE (decl) == FUNCTION_DECL) TREE_THIS_VOLATILE (decl) = 1; else if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) - TREE_TYPE (decl) = type + TREE_TYPE (decl) = type = build_pointer_type (build_type_variant (TREE_TYPE (type), TREE_READONLY (TREE_TYPE (type)), 1)); @@ -359,8 +487,11 @@ decl_attributes (node, attributes, prefix_attributes) break; case A_UNUSED: - if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL) + if (is_type) + TREE_USED (type) = 1; + else if (TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL) TREE_USED (decl) = 1; else warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); @@ -383,7 +514,8 @@ decl_attributes (node, attributes, prefix_attributes) if (is_type && TREE_CODE (type) == UNION_TYPE && (decl == 0 - || TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))) + || (TYPE_FIELDS (type) != 0 + && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type))))) TYPE_TRANSPARENT_UNION (type) = 1; else if (decl != 0 && TREE_CODE (decl) == PARM_DECL && TREE_CODE (type) == UNION_TYPE @@ -471,8 +603,9 @@ decl_attributes (node, attributes, prefix_attributes) || TREE_CODE (decl) == VAR_DECL) && TREE_CODE (TREE_VALUE (args)) == STRING_CST) { - if (TREE_CODE (decl) == VAR_DECL - && current_function_decl != NULL_TREE) + if (TREE_CODE (decl) == VAR_DECL + && current_function_decl != NULL_TREE + && ! TREE_STATIC (decl)) error_with_decl (decl, "section attribute cannot be specified for local variables"); /* The decl may have already been given a section attribute from @@ -497,7 +630,8 @@ decl_attributes (node, attributes, prefix_attributes) case A_ALIGNED: { tree align_expr - = args ? TREE_VALUE (args) : size_int (BIGGEST_ALIGNMENT); + = (args ? TREE_VALUE (args) + : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); int align; /* Strip any NOPs of any kind. */ @@ -505,7 +639,7 @@ decl_attributes (node, attributes, prefix_attributes) || TREE_CODE (align_expr) == CONVERT_EXPR || TREE_CODE (align_expr) == NON_LVALUE_EXPR) align_expr = TREE_OPERAND (align_expr, 0); - + if (TREE_CODE (align_expr) != INTEGER_CST) { error ("requested alignment is not a constant"); @@ -529,16 +663,16 @@ decl_attributes (node, attributes, prefix_attributes) case A_FORMAT: { - tree format_type = TREE_VALUE (args); + tree format_type_id = TREE_VALUE (args); tree format_num_expr = TREE_VALUE (TREE_CHAIN (args)); tree first_arg_num_expr = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))); int format_num; int first_arg_num; - int is_scan; + enum format_type format_type; tree argument; int arg_num; - + if (TREE_CODE (decl) != FUNCTION_DECL) { error_with_decl (decl, @@ -546,21 +680,28 @@ decl_attributes (node, attributes, prefix_attributes) continue; } - if (TREE_CODE (format_type) == IDENTIFIER_NODE - && (!strcmp (IDENTIFIER_POINTER (format_type), "printf") - || !strcmp (IDENTIFIER_POINTER (format_type), - "__printf__"))) - is_scan = 0; - else if (TREE_CODE (format_type) == IDENTIFIER_NODE - && (!strcmp (IDENTIFIER_POINTER (format_type), "scanf") - || !strcmp (IDENTIFIER_POINTER (format_type), - "__scanf__"))) - is_scan = 1; - else + if (TREE_CODE (format_type_id) != IDENTIFIER_NODE) { - error ("unrecognized format specifier for `%s'"); + error ("unrecognized format specifier"); continue; } + else + { + char *p = IDENTIFIER_POINTER (format_type_id); + + if (!strcmp (p, "printf") || !strcmp (p, "__printf__")) + format_type = printf_format_type; + else if (!strcmp (p, "scanf") || !strcmp (p, "__scanf__")) + format_type = scanf_format_type; + else if (!strcmp (p, "strftime") + || !strcmp (p, "__strftime__")) + format_type = strftime_format_type; + else + { + error ("`%s' is an unrecognized format function type", p); + continue; + } + } /* Strip any conversions from the string index and first arg number and verify they are constants. */ @@ -612,7 +753,7 @@ decl_attributes (node, attributes, prefix_attributes) if (first_arg_num != 0) { /* Verify that first_arg_num points to the last arg, - the ... */ + the ... */ while (argument) arg_num++, argument = TREE_CHAIN (argument); if (arg_num != first_arg_num) @@ -625,7 +766,71 @@ decl_attributes (node, attributes, prefix_attributes) record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl), - is_scan, format_num, first_arg_num); + format_type, format_num, first_arg_num); + break; + } + + case A_FORMAT_ARG: + { + tree format_num_expr = TREE_VALUE (args); + int format_num, arg_num; + tree argument; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error_with_decl (decl, + "argument format specified for non-function `%s'"); + continue; + } + + /* Strip any conversions from the first arg number and verify it + is a constant. */ + while (TREE_CODE (format_num_expr) == NOP_EXPR + || TREE_CODE (format_num_expr) == CONVERT_EXPR + || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR) + format_num_expr = TREE_OPERAND (format_num_expr, 0); + + if (TREE_CODE (format_num_expr) != INTEGER_CST) + { + error ("format string has non-constant operand number"); + continue; + } + + format_num = TREE_INT_CST_LOW (format_num_expr); + + /* If a parameter list is specified, verify that the format_num + argument is actually a string, in case the format attribute + is in error. */ + argument = TYPE_ARG_TYPES (type); + if (argument) + { + for (arg_num = 1; ; ++arg_num) + { + if (argument == 0 || arg_num == format_num) + break; + argument = TREE_CHAIN (argument); + } + if (! argument + || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) + != char_type_node)) + { + error ("format string arg not a string type"); + continue; + } + } + + if (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_TYPE (decl)))) + != char_type_node)) + { + error ("function does not return string type"); + continue; + } + + record_international_format (DECL_NAME (decl), + DECL_ASSEMBLER_NAME (decl), + format_num); break; } @@ -635,13 +840,21 @@ decl_attributes (node, attributes, prefix_attributes) case A_ALIAS: if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) - || TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)) + || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))) error_with_decl (decl, "`%s' defined both normally and as an alias"); else if (decl_function_context (decl) == 0) { - tree id = get_identifier (TREE_STRING_POINTER - (TREE_VALUE (args))); + tree id; + + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("alias arg not a string"); + break; + } + id = get_identifier (TREE_STRING_POINTER (id)); + if (TREE_CODE (decl) == FUNCTION_DECL) DECL_INITIAL (decl) = error_mark_node; else @@ -654,6 +867,100 @@ decl_attributes (node, attributes, prefix_attributes) } } } + +/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two + lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE). + + The head of the declspec list is stored in DECLSPECS. + The head of the attribute list is stored in PREFIX_ATTRIBUTES. + + Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of + the list elements. We drop the containing TREE_LIST nodes and link the + resulting attributes together the way decl_attributes expects them. */ + +void +split_specs_attrs (specs_attrs, declspecs, prefix_attributes) + tree specs_attrs; + tree *declspecs, *prefix_attributes; +{ + tree t, s, a, next, specs, attrs; + + /* This can happen in c++ (eg: decl: typespec initdecls ';'). */ + if (specs_attrs != NULL_TREE + && TREE_CODE (specs_attrs) != TREE_LIST) + { + *declspecs = specs_attrs; + *prefix_attributes = NULL_TREE; + return; + } + + /* Remember to keep the lists in the same order, element-wise. */ + + specs = s = NULL_TREE; + attrs = a = NULL_TREE; + for (t = specs_attrs; t; t = next) + { + next = TREE_CHAIN (t); + /* Declspecs have a non-NULL TREE_VALUE. */ + if (TREE_VALUE (t) != NULL_TREE) + { + if (specs == NULL_TREE) + specs = s = t; + else + { + TREE_CHAIN (s) = t; + s = t; + } + } + else + { + if (attrs == NULL_TREE) + attrs = a = TREE_PURPOSE (t); + else + { + TREE_CHAIN (a) = TREE_PURPOSE (t); + a = TREE_PURPOSE (t); + } + /* More attrs can be linked here, move A to the end. */ + while (TREE_CHAIN (a) != NULL_TREE) + a = TREE_CHAIN (a); + } + } + + /* Terminate the lists. */ + if (s != NULL_TREE) + TREE_CHAIN (s) = NULL_TREE; + if (a != NULL_TREE) + TREE_CHAIN (a) = NULL_TREE; + + /* All done. */ + *declspecs = specs; + *prefix_attributes = attrs; +} + +/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes. + This function is used by the parser when a rule will accept attributes + in a particular position, but we don't want to support that just yet. + + A warning is issued for every ignored attribute. */ + +tree +strip_attrs (specs_attrs) + tree specs_attrs; +{ + tree specs, attrs; + + split_specs_attrs (specs_attrs, &specs, &attrs); + + while (attrs) + { + warning ("`%s' attribute ignored", + IDENTIFIER_POINTER (TREE_PURPOSE (attrs))); + attrs = TREE_CHAIN (attrs); + } + + return specs; +} /* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against a parameter list. */ @@ -670,6 +977,7 @@ decl_attributes (node, attributes, prefix_attributes) #define T_D &double_type_node #define T_LD &long_double_type_node #define T_C &char_type_node +#define T_UC &unsigned_char_type_node #define T_V &void_type_node #define T_W &wchar_type_node #define T_ST &sizetype @@ -679,6 +987,9 @@ typedef struct { int pointer_count; /* Type of argument if no length modifier is used. */ tree *nolen; + /* Type of argument if length modifier for shortening to byte is used. + If NULL, then this modifier is not allowed. */ + tree *hhlen; /* Type of argument if length modifier for shortening is used. If NULL, then this modifier is not allowed. */ tree *hlen; @@ -691,89 +1002,146 @@ typedef struct { /* Type of argument if length modifier `L' is used. If NULL, then this modifier is not allowed. */ tree *bigllen; + /* Type of argument if length modifier `Z' is used. + If NULL, then this modifier is not allowed. */ + tree *zlen; /* List of other modifier characters allowed with these options. */ char *flag_chars; } format_char_info; static format_char_info print_char_table[] = { - { "di", 0, T_I, T_I, T_L, T_LL, T_LL, "-wp0 +" }, - { "oxX", 0, T_UI, T_UI, T_UL, T_ULL, T_ULL, "-wp0#" }, - { "u", 0, T_UI, T_UI, T_UL, T_ULL, T_ULL, "-wp0" }, -/* Two GNU extensions. */ - { "Z", 0, T_ST, NULL, NULL, NULL, NULL, "-wp0" }, - { "m", 0, T_V, NULL, NULL, NULL, NULL, "-wp" }, - { "feEgG", 0, T_D, NULL, NULL, NULL, T_LD, "-wp0 +#" }, - { "c", 0, T_I, NULL, T_W, NULL, NULL, "-w" }, - { "C", 0, T_W, NULL, NULL, NULL, NULL, "-w" }, - { "s", 1, T_C, NULL, T_W, NULL, NULL, "-wp" }, - { "S", 1, T_W, NULL, NULL, NULL, NULL, "-wp" }, - { "p", 1, T_V, NULL, NULL, NULL, NULL, "-w" }, - { "n", 1, T_I, T_S, T_L, T_LL, NULL, "" }, + { "di", 0, T_I, T_I, T_I, T_L, T_LL, T_LL, T_ST, "-wp0 +" }, + { "oxX", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, "-wp0#" }, + { "u", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, "-wp0" }, +/* A GNU extension. */ + { "m", 0, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "-wp" }, + { "feEgGaA", 0, T_D, NULL, NULL, NULL, NULL, T_LD, NULL, "-wp0 +#" }, + { "c", 0, T_I, NULL, NULL, T_W, NULL, NULL, NULL, "-w" }, + { "C", 0, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "-w" }, + { "s", 1, T_C, NULL, NULL, T_W, NULL, NULL, NULL, "-wp" }, + { "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 } }; static format_char_info scan_char_table[] = { - { "di", 1, T_I, T_S, T_L, T_LL, T_LL, "*" }, - { "ouxX", 1, T_UI, T_US, T_UL, T_ULL, T_ULL, "*" }, - { "efgEG", 1, T_F, NULL, T_D, NULL, T_LD, "*" }, - { "sc", 1, T_C, NULL, T_W, NULL, NULL, "*a" }, - { "[", 1, T_C, NULL, NULL, NULL, NULL, "*a" }, - { "C", 1, T_W, NULL, NULL, NULL, NULL, "*" }, - { "S", 1, T_W, NULL, NULL, NULL, NULL, "*" }, - { "p", 2, T_V, NULL, NULL, NULL, NULL, "*" }, - { "n", 1, T_I, T_S, T_L, T_LL, NULL, "" }, + { "di", 1, T_I, T_C, T_S, T_L, T_LL, T_LL, NULL, "*" }, + { "ouxX", 1, T_UI, T_UC, T_US, T_UL, T_ULL, T_ULL, NULL, "*" }, + { "efgEGaA", 1, T_F, NULL, NULL, T_D, NULL, T_LD, NULL, "*" }, + { "c", 1, T_C, NULL, NULL, T_W, NULL, NULL, NULL, "*" }, + { "s", 1, T_C, NULL, NULL, T_W, NULL, NULL, NULL, "*a" }, + { "[", 1, T_C, NULL, NULL, NULL, NULL, NULL, NULL, "*a" }, + { "C", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "*" }, + { "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 } }; -typedef struct function_format_info { +/* Handle format characters recognized by glibc's strftime.c. + '2' - MUST do years as only two digits + '3' - MAY do years as only two digits (depending on locale) + 'E' - E modifier is acceptable + 'O' - O modifier is acceptable to Standard C + 'o' - O modifier is acceptable as a GNU extension + 'G' - other GNU extensions */ + +static format_char_info time_char_table[] = { + { "y", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "2EO-_0w" }, + { "D", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "2" }, + { "g", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "2O-_0w" }, + { "cx", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "3E" }, + { "%RTXnrt", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "" }, + { "P", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "G" }, + { "HIMSUWdemw", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0Ow" }, + { "Vju", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0Oow" }, + { "Gklsz", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0OGw" }, + { "ABZa", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "^#" }, + { "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 } +}; + +typedef struct function_format_info +{ struct function_format_info *next; /* next structure on the list */ tree name; /* identifier such as "printf" */ tree assembler_name; /* optional mangled identifier (for C++) */ - int is_scan; /* TRUE if *scanf */ + enum format_type format_type; /* type of format (printf, scanf, etc.) */ int format_num; /* number of format argument */ int first_arg_num; /* number of first arg (zero for varargs) */ } function_format_info; static function_format_info *function_format_list = NULL; -static void check_format_info PROTO((function_format_info *, tree)); +typedef struct international_format_info +{ + struct international_format_info *next; /* next structure on the list */ + tree name; /* identifier such as "gettext" */ + tree assembler_name; /* optional mangled identifier (for C++) */ + int format_num; /* number of format argument */ +} international_format_info; + +static international_format_info *international_format_list = NULL; + +static void check_format_info PROTO((function_format_info *, tree)); /* Initialize the table of functions to perform format checking on. The ANSI functions are always checked (whether is included or not), since it is common to call printf without including . There shouldn't be a problem with this, since ANSI reserves these function names whether you include the - header file or not. In any case, the checking is harmless. */ + header file or not. In any case, the checking is harmless. + + Also initialize the name of function that modify the format string for + internationalization purposes. */ void init_function_format_info () { - record_function_format (get_identifier ("printf"), NULL_TREE, 0, 1, 2); - record_function_format (get_identifier ("fprintf"), NULL_TREE, 0, 2, 3); - record_function_format (get_identifier ("sprintf"), NULL_TREE, 0, 2, 3); - record_function_format (get_identifier ("scanf"), NULL_TREE, 1, 1, 2); - record_function_format (get_identifier ("fscanf"), NULL_TREE, 1, 2, 3); - record_function_format (get_identifier ("sscanf"), NULL_TREE, 1, 2, 3); - record_function_format (get_identifier ("vprintf"), NULL_TREE, 0, 1, 0); - record_function_format (get_identifier ("vfprintf"), NULL_TREE, 0, 2, 0); - record_function_format (get_identifier ("vsprintf"), NULL_TREE, 0, 2, 0); + record_function_format (get_identifier ("printf"), NULL_TREE, + printf_format_type, 1, 2); + record_function_format (get_identifier ("fprintf"), NULL_TREE, + printf_format_type, 2, 3); + record_function_format (get_identifier ("sprintf"), NULL_TREE, + printf_format_type, 2, 3); + record_function_format (get_identifier ("scanf"), NULL_TREE, + scanf_format_type, 1, 2); + record_function_format (get_identifier ("fscanf"), NULL_TREE, + scanf_format_type, 2, 3); + record_function_format (get_identifier ("sscanf"), NULL_TREE, + scanf_format_type, 2, 3); + record_function_format (get_identifier ("vprintf"), NULL_TREE, + printf_format_type, 1, 0); + record_function_format (get_identifier ("vfprintf"), NULL_TREE, + printf_format_type, 2, 0); + record_function_format (get_identifier ("vsprintf"), NULL_TREE, + printf_format_type, 2, 0); + record_function_format (get_identifier ("strftime"), NULL_TREE, + strftime_format_type, 3, 0); + + record_international_format (get_identifier ("gettext"), NULL_TREE, 1); + record_international_format (get_identifier ("dgettext"), NULL_TREE, 2); + record_international_format (get_identifier ("dcgettext"), NULL_TREE, 2); } /* Record information for argument format checking. FUNCTION_IDENT is the identifier node for the name of the function to check (its decl - need not exist yet). IS_SCAN is true for scanf-type format checking; - false indicates printf-style format checking. FORMAT_NUM is the number + need not exist yet). + FORMAT_TYPE specifies the type of format checking. FORMAT_NUM is the number of the argument which is the format control string (starting from 1). FIRST_ARG_NUM is the number of the first actual argument to check - against teh format string, or zero if no checking is not be done + against the format string, or zero if no checking is not be done (e.g. for varargs such as vfprintf). */ -void -record_function_format (name, assembler_name, is_scan, +static void +record_function_format (name, assembler_name, format_type, format_num, first_arg_num) tree name; tree assembler_name; - int is_scan; + enum format_type format_type; int format_num; int first_arg_num; { @@ -796,11 +1164,48 @@ record_function_format (name, assembler_name, is_scan, info->assembler_name = assembler_name; } - info->is_scan = is_scan; + info->format_type = format_type; info->format_num = format_num; info->first_arg_num = first_arg_num; } +/* Record information for the names of function that modify the format + argument to format functions. FUNCTION_IDENT is the identifier node for + the name of the function (its decl need not exist yet) and FORMAT_NUM is + the number of the argument which is the format control string (starting + from 1). */ + +static void +record_international_format (name, assembler_name, format_num) + tree name; + tree assembler_name; + int format_num; +{ + international_format_info *info; + + /* Re-use existing structure if it's there. */ + + for (info = international_format_list; info; info = info->next) + { + if (info->name == name && info->assembler_name == assembler_name) + break; + } + + if (! info) + { + info + = (international_format_info *) + xmalloc (sizeof (international_format_info)); + info->next = international_format_list; + international_format_list = info; + + info->name = name; + info->assembler_name = assembler_name; + } + + info->format_num = format_num; +} + static char tfaff[] = "too few arguments for format"; /* Check the argument list of a call to printf, scanf, etc. @@ -843,7 +1248,7 @@ check_format_info (info, params) int i; int arg_num; int suppressed, wide, precise; - int length_char; + int length_char = 0; int format_char; int format_length; tree format_tree; @@ -852,8 +1257,7 @@ check_format_info (info, params) tree wanted_type; tree first_fillin_param; char *format_chars; - format_char_info *fci; - static char message[132]; + format_char_info *fci = NULL; char flag_chars[8]; int has_operand_number = 0; @@ -871,9 +1275,43 @@ check_format_info (info, params) params = TREE_CHAIN (params); if (format_tree == 0) return; + /* We can only check the format if it's a string constant. */ while (TREE_CODE (format_tree) == NOP_EXPR) format_tree = TREE_OPERAND (format_tree, 0); /* strip coercion */ + + if (TREE_CODE (format_tree) == CALL_EXPR + && TREE_CODE (TREE_OPERAND (format_tree, 0)) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (format_tree, 0), 0)) + == FUNCTION_DECL)) + { + tree function = TREE_OPERAND (TREE_OPERAND (format_tree, 0), 0); + + /* See if this is a call to a known internationalization function + that modifies the format arg. */ + international_format_info *info; + + for (info = international_format_list; info; info = info->next) + if (info->assembler_name + ? (info->assembler_name == DECL_ASSEMBLER_NAME (function)) + : (info->name == DECL_NAME (function))) + { + tree inner_args; + int i; + + for (inner_args = TREE_OPERAND (format_tree, 1), i = 1; + inner_args != 0; + inner_args = TREE_CHAIN (inner_args), i++) + if (i == info->format_num) + { + format_tree = TREE_VALUE (inner_args); + + while (TREE_CODE (format_tree) == NOP_EXPR) + format_tree = TREE_OPERAND (format_tree, 0); + } + } + } + if (integer_zerop (format_tree)) { warning ("null format string"); @@ -928,15 +1366,55 @@ check_format_info (info, params) } flag_chars[0] = 0; suppressed = wide = precise = FALSE; - if (info->is_scan) + if (info->format_type == scanf_format_type) { suppressed = *format_chars == '*'; if (suppressed) ++format_chars; - while (isdigit (*format_chars)) + while (ISDIGIT (*format_chars)) ++format_chars; } - else + else if (info->format_type == strftime_format_type) + { + while (*format_chars != 0 && index ("_-0^#", *format_chars) != 0) + { + if (pedantic) + warning ("ANSI C does not support the strftime `%c' flag", + *format_chars); + if (index (flag_chars, *format_chars) != 0) + { + warning ("repeated `%c' flag in format", + *format_chars); + ++format_chars; + } + else + { + i = strlen (flag_chars); + flag_chars[i++] = *format_chars++; + flag_chars[i] = 0; + } + } + while (ISDIGIT ((unsigned char) *format_chars)) + { + wide = TRUE; + ++format_chars; + } + if (wide && pedantic) + warning ("ANSI C does not support strftime format width"); + if (*format_chars == 'E' || *format_chars == 'O') + { + i = strlen (flag_chars); + flag_chars[i++] = *format_chars++; + flag_chars[i] = 0; + if (*format_chars == 'E' || *format_chars == 'O') + { + warning ("multiple E/O modifiers in format"); + while (*format_chars == 'E' || *format_chars == 'O') + ++format_chars; + } + } + } + else if (info->format_type == printf_format_type) { /* See if we have a number followed by a dollar sign. If we do, it is an operand number, so set PARAMS to that operand. */ @@ -969,16 +1447,15 @@ check_format_info (info, params) while (*format_chars != 0 && index (" +#0-", *format_chars) != 0) { if (index (flag_chars, *format_chars) != 0) + warning ("repeated `%c' flag in format", *format_chars++); + else { - sprintf (message, "repeated `%c' flag in format", - *format_chars); - warning (message); + i = strlen (flag_chars); + flag_chars[i++] = *format_chars++; + flag_chars[i] = 0; } - i = strlen (flag_chars); - flag_chars[i++] = *format_chars++; - flag_chars[i] = 0; } - /* "If the space and + flags both appear, + /* "If the space and + flags both appear, the space flag will be ignored." */ if (index (flag_chars, ' ') != 0 && index (flag_chars, '+') != 0) @@ -1013,17 +1490,12 @@ check_format_info (info, params) && (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) != unsigned_type_node)) - { - sprintf (message, - "field width is not type int (arg %d)", - arg_num); - warning (message); - } + warning ("field width is not type int (arg %d)", arg_num); } } else { - while (isdigit (*format_chars)) + while (ISDIGIT (*format_chars)) { wide = TRUE; ++format_chars; @@ -1033,7 +1505,7 @@ check_format_info (info, params) { precise = TRUE; ++format_chars; - if (*format_chars != '*' && !isdigit (*format_chars)) + if (*format_chars != '*' && !ISDIGIT (*format_chars)) warning ("`.' not followed by `*' or digit in format"); /* "...a...precision...may be indicated by an asterisk. In this case, an int argument supplies the...precision." */ @@ -1052,84 +1524,137 @@ check_format_info (info, params) ++arg_num; if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) != integer_type_node) - { - sprintf (message, - "field width is not type int (arg %d)", - arg_num); - warning (message); - } + warning ("field width is not type int (arg %d)", + arg_num); } } else { - while (isdigit (*format_chars)) + while (ISDIGIT (*format_chars)) ++format_chars; } } } - if (*format_chars == 'h' || *format_chars == 'l' || *format_chars == 'q' || - *format_chars == 'L') - length_char = *format_chars++; - else - length_char = 0; - if (length_char == 'l' && *format_chars == 'l') - length_char = 'q', format_chars++; + aflag = 0; - if (*format_chars == 'a') - { - aflag = 1; - format_chars++; - } - if (suppressed && length_char != 0) + + if (info->format_type != strftime_format_type) { - sprintf (message, - "use of `*' and `%c' together in format", - length_char); - warning (message); + if (*format_chars == 'h' || *format_chars == 'l') + length_char = *format_chars++; + else if (*format_chars == 'q' || *format_chars == 'L') + { + length_char = *format_chars++; + if (pedantic) + warning ("ANSI C does not support the `%c' length modifier", + length_char); + } + else if (*format_chars == 'Z') + { + length_char = *format_chars++; + if (pedantic) + warning ("ANSI C does not support the `Z' length modifier"); + } + else + length_char = 0; + if (length_char == 'l' && *format_chars == 'l') + { + length_char = 'q', format_chars++; + /* FIXME: Is allowed in ISO C 9x. */ + if (pedantic) + warning ("ANSI C does not support the `ll' length modifier"); + } + else if (length_char == 'h' && *format_chars == 'h') + { + length_char = 'H', format_chars++; + /* FIXME: Is allowed in ISO C 9x. */ + if (pedantic) + warning ("ANSI C does not support the `hh' length modifier"); + } + if (*format_chars == 'a' && info->format_type == scanf_format_type) + { + if (format_chars[1] == 's' || format_chars[1] == 'S' + || format_chars[1] == '[') + { + /* `a' is used as a flag. */ + aflag = 1; + format_chars++; + } + } + if (suppressed && length_char != 0) + warning ("use of `*' and `%c' together in format", length_char); } format_char = *format_chars; - if (format_char == 0) + if (format_char == 0 + || (info->format_type != strftime_format_type && format_char == '%')) { warning ("conversion lacks type at end of format"); continue; } + /* The m, C, and S formats are GNU extensions. */ + if (pedantic && info->format_type != strftime_format_type + && (format_char == 'm' || format_char == 'C' || format_char == 'S')) + warning ("ANSI C does not support the `%c' format", format_char); + /* ??? The a and A formats are C9X extensions, and should be allowed + when a C9X option is added. */ + if (pedantic && info->format_type != strftime_format_type + && (format_char == 'a' || format_char == 'A')) + warning ("ANSI C does not support the `%c' format", format_char); format_chars++; - fci = info->is_scan ? scan_char_table : print_char_table; + switch (info->format_type) + { + case printf_format_type: + fci = print_char_table; + break; + case scanf_format_type: + fci = scan_char_table; + break; + case strftime_format_type: + fci = time_char_table; + break; + default: + abort (); + } while (fci->format_chars != 0 && index (fci->format_chars, format_char) == 0) ++fci; if (fci->format_chars == 0) { if (format_char >= 040 && format_char < 0177) - sprintf (message, - "unknown conversion type character `%c' in format", + warning ("unknown conversion type character `%c' in format", format_char); else - sprintf (message, - "unknown conversion type character 0x%x in format", + warning ("unknown conversion type character 0x%x in format", format_char); - warning (message); continue; } - if (wide && index (fci->flag_chars, 'w') == 0) + if (pedantic) { - sprintf (message, "width used with `%c' format", - format_char); - warning (message); + if (index (fci->flag_chars, 'G') != 0) + warning ("ANSI C does not support `%%%c'", format_char); + if (index (fci->flag_chars, 'o') != 0 + && index (flag_chars, 'O') != 0) + warning ("ANSI C does not support `%%O%c'", format_char); } + if (wide && index (fci->flag_chars, 'w') == 0) + warning ("width used with `%c' format", format_char); + if (index (fci->flag_chars, '2') != 0) + warning ("`%%%c' yields only last 2 digits of year", format_char); + else if (index (fci->flag_chars, '3') != 0) + warning ("`%%%c' yields only last 2 digits of year in some locales", + format_char); if (precise && index (fci->flag_chars, 'p') == 0) - { - sprintf (message, "precision used with `%c' format", - format_char); - warning (message); - } + warning ("precision used with `%c' format", format_char); if (aflag && index (fci->flag_chars, 'a') == 0) { - sprintf (message, "`a' flag used with `%c' format", - format_char); - warning (message); + warning ("`a' flag used with `%c' format", format_char); + /* To simplify the following code. */ + aflag = 0; } - if (info->is_scan && format_char == '[') + /* The a flag is a GNU extension. */ + else if (pedantic && aflag) + warning ("ANSI C does not support the `a' flag"); + if (info->format_type == scanf_format_type && format_char == '[') { /* Skip over scan set, in case it happens to have '%' in it. */ if (*format_chars == '^') @@ -1141,63 +1666,42 @@ check_format_info (info, params) while (*format_chars && *format_chars != ']') ++format_chars; if (*format_chars != ']') - /* The end of the format string was reached. */ - warning ("no closing `]' for `%%[' format"); + /* The end of the format string was reached. */ + warning ("no closing `]' for `%%[' format"); } if (suppressed) { if (index (fci->flag_chars, '*') == 0) - { - sprintf (message, - "suppression of `%c' conversion in format", - format_char); - warning (message); - } + warning ("suppression of `%c' conversion in format", format_char); continue; } for (i = 0; flag_chars[i] != 0; ++i) { if (index (fci->flag_chars, flag_chars[i]) == 0) - { - sprintf (message, "flag `%c' used with type `%c'", - flag_chars[i], format_char); - warning (message); - } + warning ("flag `%c' used with type `%c'", + flag_chars[i], format_char); } + if (info->format_type == strftime_format_type) + continue; 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')) - { - sprintf (message, - "precision and `0' flag not both allowed with `%c' format", - format_char); - warning (message); - } + warning ("`0' flag ignored with precision specifier and `%c' format", + format_char); switch (length_char) { default: wanted_type = fci->nolen ? *(fci->nolen) : 0; break; + case 'H': wanted_type = fci->hhlen ? *(fci->hhlen) : 0; break; case 'h': wanted_type = fci->hlen ? *(fci->hlen) : 0; break; case 'l': wanted_type = fci->llen ? *(fci->llen) : 0; break; case 'q': wanted_type = fci->qlen ? *(fci->qlen) : 0; break; case 'L': wanted_type = fci->bigllen ? *(fci->bigllen) : 0; break; + case 'Z': wanted_type = fci->zlen ? *fci->zlen : 0; break; } if (wanted_type == 0) - { - sprintf (message, - "use of `%c' length character with `%c' type character", - length_char, format_char); - warning (message); - } - - /* - ** XXX -- should kvetch about stuff such as - ** { - ** const int i; - ** - ** scanf ("%d", &i); - ** } - */ + warning ("use of `%c' length character with `%c' type character", + length_char, format_char); /* Finally. . .check type of argument against desired type! */ if (info->first_arg_num == 0) @@ -1215,28 +1719,48 @@ check_format_info (info, params) ++arg_num; cur_type = TREE_TYPE (cur_param); + STRIP_NOPS (cur_param); + /* Check the types of any additional pointer arguments that precede the "real" argument. */ - for (i = 0; i < fci->pointer_count; ++i) + for (i = 0; i < fci->pointer_count + aflag; ++i) { if (TREE_CODE (cur_type) == POINTER_TYPE) { cur_type = TREE_TYPE (cur_type); + + if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) + cur_param = TREE_OPERAND (cur_param, 0); + else + cur_param = 0; + continue; } if (TREE_CODE (cur_type) != ERROR_MARK) - { - sprintf (message, - "format argument is not a %s (arg %d)", - ((fci->pointer_count == 1) ? "pointer" : "pointer to a pointer"), - arg_num); - warning (message); - } + warning ("format argument is not a %s (arg %d)", + ((fci->pointer_count + aflag == 1) + ? "pointer" : "pointer to a pointer"), + arg_num); break; } + /* See if this is an attempt to write into a const type with + scanf or with printf "%n". */ + if ((info->format_type == scanf_format_type + || (info->format_type == printf_format_type + && format_char == 'n')) + && i == fci->pointer_count + aflag + && wanted_type != 0 + && TREE_CODE (cur_type) != ERROR_MARK + && (TYPE_READONLY (cur_type) + || (cur_param != 0 + && (TREE_CODE_CLASS (TREE_CODE (cur_param)) == 'c' + || (TREE_CODE_CLASS (TREE_CODE (cur_param)) == 'd' + && TREE_READONLY (cur_param)))))) + warning ("writing into constant object (arg %d)", arg_num); + /* Check the type of the "real" argument, if there's a type we want. */ - if (i == fci->pointer_count && wanted_type != 0 + if (i == fci->pointer_count + aflag && wanted_type != 0 && TREE_CODE (cur_type) != ERROR_MARK && wanted_type != TYPE_MAIN_VARIANT (cur_type) /* If we want `void *', allow any pointer type. @@ -1257,7 +1781,7 @@ check_format_info (info, params) { register char *this; register char *that; - + this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type))); that = 0; if (TREE_CODE (cur_type) != ERROR_MARK @@ -1293,11 +1817,7 @@ check_format_info (info, params) that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type))); if (strcmp (this, that) != 0) - { - sprintf (message, "%s format, %s arg (arg %d)", - this, that, arg_num); - warning (message); - } + warning ("%s format, %s arg (arg %d)", this, that, arg_num); } } } @@ -1335,7 +1855,8 @@ overflow_warning (value) && TREE_OVERFLOW (value)) { TREE_OVERFLOW (value) = 0; - warning ("integer overflow in expression"); + if (skip_evaluation == 0) + warning ("integer overflow in expression"); } else if ((TREE_CODE (value) == REAL_CST || (TREE_CODE (value) == COMPLEX_CST @@ -1343,7 +1864,8 @@ overflow_warning (value) && TREE_OVERFLOW (value)) { TREE_OVERFLOW (value) = 0; - warning ("floating-pointer overflow in expression"); + if (skip_evaluation == 0) + warning ("floating point overflow in expression"); } } @@ -1359,6 +1881,7 @@ unsigned_conversion_warning (result, operand) if (TREE_CODE (operand) == INTEGER_CST && TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE && TREE_UNSIGNED (TREE_TYPE (result)) + && skip_evaluation == 0 && !int_fits_type_p (operand, TREE_TYPE (result))) { if (!int_fits_type_p (operand, signed_type (TREE_TYPE (result)))) @@ -1394,9 +1917,10 @@ convert_and_check (type, expr) && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr)))) /* If EXPR fits in the unsigned version of TYPE, don't warn unless pedantic. */ - if (pedantic - || TREE_UNSIGNED (type) - || ! int_fits_type_p (expr, unsigned_type (type))) + if ((pedantic + || TREE_UNSIGNED (type) + || ! int_fits_type_p (expr, unsigned_type (type))) + && skip_evaluation == 0) warning ("overflow in implicit constant conversion"); } else @@ -1525,6 +2049,9 @@ type_for_mode (mode, unsignedp) if (mode == TYPE_MODE (intDI_type_node)) return unsignedp ? unsigned_intDI_type_node : intDI_type_node; + if (mode == TYPE_MODE (intTI_type_node)) + return unsignedp ? unsigned_intTI_type_node : intTI_type_node; + if (mode == TYPE_MODE (float_type_node)) return float_type_node; @@ -1581,7 +2108,7 @@ void binary_op_error (code) enum tree_code code; { - register char *opname = "unknown"; + register char *opname; switch (code) { @@ -1634,6 +2161,8 @@ binary_op_error (code) case LROTATE_EXPR: case RROTATE_EXPR: opname = "rotate"; break; + default: + opname = "unknown"; break; } error ("invalid operands to binary %s", opname); } @@ -1720,6 +2249,8 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) case GE_EXPR: code = LE_EXPR; break; + default: + break; } *rescode_ptr = code; } @@ -1753,6 +2284,12 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) type = signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0)); + /* If TYPE is an enumeration, then we need to get its min/max + values from it's underlying integral type, not the enumerated + type itself. */ + if (TREE_CODE (type) == ENUMERAL_TYPE) + type = type_for_size (TYPE_PRECISION (type), unsignedp0); + maxval = TYPE_MAX_VALUE (type); minval = TYPE_MIN_VALUE (type); @@ -1850,6 +2387,9 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) primop1 = TYPE_MAX_VALUE (type); val = 0; break; + + default: + break; } type = unsigned_type (type); } @@ -1947,6 +2487,10 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) primop0)))) warning ("unsigned value < 0 is always 0"); value = boolean_false_node; + break; + + default: + break; } if (value != 0) @@ -2048,6 +2592,12 @@ truthvalue_conversion (expr) return real_zerop (expr) ? boolean_false_node : boolean_true_node; case ADDR_EXPR: + /* If we are taking the address of a external decl, it might be zero + if it is weak, so we cannot optimize. */ + if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (expr, 0))) == 'd' + && DECL_EXTERNAL (TREE_OPERAND (expr, 0))) + break; + if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))) return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0), boolean_true_node); @@ -2077,7 +2627,7 @@ truthvalue_conversion (expr) truthvalue_conversion (TREE_OPERAND (expr, 0))); else return truthvalue_conversion (TREE_OPERAND (expr, 0)); - + case COND_EXPR: /* Distribute the conversion into the arms of a COND_EXPR. */ return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0), @@ -2090,7 +2640,7 @@ truthvalue_conversion (expr) if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) break; - /* fall through... */ + /* fall through... */ case NOP_EXPR: /* If this is widening the argument, we can ignore it. */ if (TYPE_PRECISION (TREE_TYPE (expr)) @@ -2104,7 +2654,7 @@ truthvalue_conversion (expr) if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) break; - /* fall through... */ + /* fall through... */ case BIT_XOR_EXPR: /* This and MINUS_EXPR can be changed into a comparison of the two objects. */ @@ -2128,19 +2678,26 @@ truthvalue_conversion (expr) if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR) warning ("suggest parentheses around assignment used as truth value"); break; + + default: + break; } if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE) - return (build_binary_op - ((TREE_SIDE_EFFECTS (expr) - ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), - truthvalue_conversion (build_unary_op (REALPART_EXPR, expr, 0)), - truthvalue_conversion (build_unary_op (IMAGPART_EXPR, expr, 0)), - 0)); + { + tree tem = save_expr (expr); + return (build_binary_op + ((TREE_SIDE_EFFECTS (expr) + ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), + truthvalue_conversion (build_unary_op (REALPART_EXPR, tem, 0)), + truthvalue_conversion (build_unary_op (IMAGPART_EXPR, tem, 0)), + 0)); + } return build_binary_op (NE_EXPR, expr, integer_zero_node, 1); } +#if USE_CPPLIB /* Read the rest of a #-directive from input stream FINPUT. In normal use, the directive name and the white space after it have already been read, so they won't be included in the result. @@ -2150,6 +2707,107 @@ truthvalue_conversion (expr) The value is a string in a reusable buffer. It remains valid only until the next time this function is called. */ +unsigned char *yy_cur, *yy_lim; + +#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ()) +#define UNGETC(c) ((c), yy_cur--) + +int +yy_get_token () +{ + for (;;) + { + parse_in.limit = parse_in.token_buffer; + cpp_token = cpp_get_token (&parse_in); + if (cpp_token == CPP_EOF) + return -1; + yy_lim = CPP_PWRITTEN (&parse_in); + yy_cur = parse_in.token_buffer; + if (yy_cur < yy_lim) + return *yy_cur++; + } +} + +char * +get_directive_line () +{ + static char *directive_buffer = NULL; + static unsigned buffer_length = 0; + register char *p; + register char *buffer_limit; + register int looking_for = 0; + register int char_escaped = 0; + + if (buffer_length == 0) + { + directive_buffer = (char *)xmalloc (128); + buffer_length = 128; + } + + buffer_limit = &directive_buffer[buffer_length]; + + for (p = directive_buffer; ; ) + { + int c; + + /* Make buffer bigger if it is full. */ + if (p >= buffer_limit) + { + register unsigned bytes_used = (p - directive_buffer); + + buffer_length *= 2; + directive_buffer + = (char *)xrealloc (directive_buffer, buffer_length); + p = &directive_buffer[bytes_used]; + buffer_limit = &directive_buffer[buffer_length]; + } + + c = GETC (); + + /* Discard initial whitespace. */ + if ((c == ' ' || c == '\t') && p == directive_buffer) + continue; + + /* Detect the end of the directive. */ + if (c == '\n' && looking_for == 0) + { + UNGETC (c); + c = '\0'; + } + + *p++ = c; + + if (c == 0) + return directive_buffer; + + /* Handle string and character constant syntax. */ + if (looking_for) + { + if (looking_for == c && !char_escaped) + looking_for = 0; /* Found terminator... stop looking. */ + } + else + if (c == '\'' || c == '"') + looking_for = c; /* Don't stop buffering until we see another + another one of these (or an EOF). */ + + /* Handle backslash. */ + char_escaped = (c == '\\' && ! char_escaped); + } +} +#else +/* Read the rest of a #-directive from input stream FINPUT. + In normal use, the directive name and the white space after it + have already been read, so they won't be included in the result. + We allow for the fact that the directive line may contain + a newline embedded within a character or string literal which forms + a part of the directive. + + The value is a string in a reusable buffer. It remains valid + only until the next time this function is called. + + The terminating character ('\n' or EOF) is left in FINPUT for the + caller to re-read. */ char * get_directive_line (finput) @@ -2193,7 +2851,8 @@ get_directive_line (finput) continue; /* Detect the end of the directive. */ - if (c == '\n' && looking_for == 0) + if (looking_for == 0 + && (c == '\n' || c == EOF)) { ungetc (c, finput); c = '\0'; @@ -2213,12 +2872,13 @@ get_directive_line (finput) else if (c == '\'' || c == '"') looking_for = c; /* Don't stop buffering until we see another - another one of these (or an EOF). */ + one of these (or an EOF). */ /* Handle backslash. */ char_escaped = (c == '\\' && ! char_escaped); } } +#endif /* !USE_CPPLIB */ /* Make a variant type in the proper way for C/C++, propagating qualifiers down to the element type of an array. */ @@ -2229,27 +2889,95 @@ c_build_type_variant (type, constp, volatilep) int constp, volatilep; { if (TREE_CODE (type) == ARRAY_TYPE) - { - tree real_main_variant = TYPE_MAIN_VARIANT (type); + return build_array_type (c_build_type_variant (TREE_TYPE (type), + constp, volatilep), + TYPE_DOMAIN (type)); + return build_type_variant (type, constp, volatilep); +} + +/* Return the typed-based alias set for T, which may be an expression + or a type. */ - push_obstacks (TYPE_OBSTACK (real_main_variant), - TYPE_OBSTACK (real_main_variant)); - type = build_array_type (c_build_type_variant (TREE_TYPE (type), - constp, volatilep), - TYPE_DOMAIN (type)); +int +c_get_alias_set (t) + tree t; +{ + static int next_set = 0; + tree type; + + if (t == error_mark_node) + return 0; + + type = (TREE_CODE_CLASS (TREE_CODE (t)) == '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); + + if (TREE_CODE (t) == BIT_FIELD_REF) + /* Perhaps reads and writes to this piece of data alias fields + neighboring the bitfield. Perhaps that's impossible. For now, + 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) + { + /* 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); + } + else if (TREE_CODE (type) == INTEGER_TYPE) + { + tree signed_variant; - /* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not, - make a copy. (TYPE might have come from the hash table and - REAL_MAIN_VARIANT might be in some function's obstack.) */ + /* The C standard specifically allows aliasing between signed and + unsigned variants of the same type. We treat the signed + variant as canonical. */ + signed_variant = signed_type (type); - if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant)) + if (signed_variant != type) { - type = copy_node (type); - TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0; + TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant); + return TYPE_ALIAS_SET (type); + } + 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_MAIN_VARIANT (type) = real_main_variant; - pop_obstacks (); } - return build_type_variant (type, constp, volatilep); + 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); + } + + /* 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 8ba93a9..6f58e76 100644 --- a/contrib/gcc/c-convert.c +++ b/contrib/gcc/c-convert.c @@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */ #include "tree.h" #include "flags.h" #include "convert.h" +#include "toplev.h" /* Change of width--truncation and extension of integers or reals-- is represented with NOP_EXPR. Proper functioning of many things diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c index ca33a4c..ccaa7d2 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, 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. @@ -27,12 +27,20 @@ Boston, MA 02111-1307, USA. */ line numbers. For example, the CONST_DECLs for enum values. */ #include "config.h" +#include "system.h" #include "tree.h" #include "flags.h" #include "output.h" #include "c-tree.h" #include "c-lex.h" -#include +#include "toplev.h" + +#if USE_CPPLIB +#include "cpplib.h" +extern cpp_reader parse_in; +extern cpp_options parse_options; +static int cpp_initialized; +#endif /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -143,11 +151,13 @@ tree intQI_type_node; tree intHI_type_node; tree intSI_type_node; tree intDI_type_node; +tree intTI_type_node; tree unsigned_intQI_type_node; tree unsigned_intHI_type_node; tree unsigned_intSI_type_node; tree unsigned_intDI_type_node; +tree unsigned_intTI_type_node; /* a VOID_TYPE node. */ @@ -411,16 +421,20 @@ tree static_ctors, static_dtors; /* Forward declarations. */ -static tree grokparms (), grokdeclarator (); -tree pushdecl (); -tree builtin_function (); -void shadow_tag_warned (); - -static tree lookup_tag (); -static tree lookup_tag_reverse (); -tree lookup_name_current_level (); -static char *redeclaration_error_message (); -static void layout_array_type (); +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 void storedecls PROTO((tree)); +static void storetags PROTO((tree)); +static tree lookup_tag PROTO((enum tree_code, tree, + struct binding_level *, int)); +static tree lookup_tag_reverse PROTO((tree)); +static tree grokdeclarator PROTO((tree, tree, enum decl_context, + int)); +static tree grokparms PROTO((tree, int)); +static int field_decl_cmp PROTO((const GENERIC_PTR, const GENERIC_PTR)); +static void layout_array_type PROTO((tree)); /* C-specific option variables. */ @@ -450,8 +464,12 @@ int flag_no_nonansi_builtin; int flag_traditional; +/* Nonzero means that we have builtin functions, and main is an int */ + +int flag_hosted = 1; + /* Nonzero means to allow single precision math even if we're generally - being traditional. */ + being traditional. */ int flag_allow_single_precision = 0; /* Nonzero means to treat bitfields as signed unless they say `unsigned'. */ @@ -463,9 +481,18 @@ int explicit_flag_signed_bitfields = 0; int flag_no_ident = 0; -/* Nonzero means warn about implicit declarations. */ +/* Nonzero means warn about use of implicit int. */ + +int warn_implicit_int; + +/* Nonzero means warn about usage of long long when `-pedantic'. */ + +int warn_long_long = 1; -int warn_implicit; +/* Nonzero means message about use of implicit function declarations; + 1 means warning; 2 means error. */ + +int mesg_implicit_function_declaration; /* Nonzero means give string constants the type `const char *' to get extra warnings from them. These warnings will be too numerous @@ -521,7 +548,7 @@ int warn_redundant_decls = 0; int warn_nested_externs = 0; -/* Warn about *printf or *scanf format/argument anomalies. */ +/* Warn about *printf or *scanf format/argument anomalies. */ int warn_format; @@ -541,44 +568,80 @@ int warn_parentheses; int warn_missing_braces; -/* Nonzero means `$' can be in an identifier. - See cccp.c for reasons why this breaks some obscure ANSI C programs. */ +/* Warn if main is suspicious. */ + +int warn_main; + +/* Warn about #pragma directives that are not recognised. */ + +int warn_unknown_pragmas = 0; /* Tri state variable. */ + +/* Warn about comparison of signed and unsigned values. + If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */ + +int warn_sign_compare = -1; + +/* Nonzero means warn about use of multicharacter literals. */ + +int warn_multichar = 1; + +/* Nonzero means `$' can be in an identifier. */ #ifndef DOLLARS_IN_IDENTIFIERS #define DOLLARS_IN_IDENTIFIERS 1 #endif -int dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1; +int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; /* Decode the string P as a language-specific option for C. - Return 1 if it is recognized (and handle it); - return 0 if not recognized. */ + Return the number of strings consumed. */ int -c_decode_option (p) - char *p; +c_decode_option (argc, argv) + int argc; + 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_traditional = 1; flag_writable_strings = 1; -#if DOLLARS_IN_IDENTIFIERS > 0 - dollars_in_ident = 1; -#endif } else if (!strcmp (p, "-fallow-single-precision")) flag_allow_single_precision = 1; + else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding")) + { + flag_hosted = 1; + flag_no_builtin = 0; + } + else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted")) + { + flag_hosted = 0; + flag_no_builtin = 1; + /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */ + if (warn_main == 2) + warn_main = 0; + } else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional")) { flag_traditional = 0; flag_writable_strings = 0; - dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1; } else if (!strcmp (p, "-fdollars-in-identifiers")) - { -#if DOLLARS_IN_IDENTIFIERS > 0 - dollars_in_ident = 1; -#endif - } + dollars_in_ident = 1; else if (!strcmp (p, "-fno-dollars-in-identifiers")) dollars_in_ident = 0; else if (!strcmp (p, "-fsigned-char")) @@ -626,11 +689,29 @@ c_decode_option (p) else if (!strcmp (p, "-fident")) flag_no_ident = 0; else if (!strcmp (p, "-ansi")) - flag_no_asm = 1, flag_no_nonansi_builtin = 1, dollars_in_ident = 0; + flag_no_asm = 1, flag_no_nonansi_builtin = 1; + else if (!strcmp (p, "-Werror-implicit-function-declaration")) + mesg_implicit_function_declaration = 2; + else if (!strcmp (p, "-Wimplicit-function-declaration")) + mesg_implicit_function_declaration = 1; + else if (!strcmp (p, "-Wno-implicit-function-declaration")) + mesg_implicit_function_declaration = 0; + else if (!strcmp (p, "-Wimplicit-int")) + warn_implicit_int = 1; + else if (!strcmp (p, "-Wno-implicit-int")) + warn_implicit_int = 0; else if (!strcmp (p, "-Wimplicit")) - warn_implicit = 1; + { + warn_implicit_int = 1; + if (mesg_implicit_function_declaration != 2) + mesg_implicit_function_declaration = 1; + } else if (!strcmp (p, "-Wno-implicit")) - warn_implicit = 0; + warn_implicit_int = 0, mesg_implicit_function_declaration = 0; + else if (!strcmp (p, "-Wlong-long")) + warn_long_long = 1; + else if (!strcmp (p, "-Wno-long-long")) + warn_long_long = 0; else if (!strcmp (p, "-Wwrite-strings")) warn_write_strings = 1; else if (!strcmp (p, "-Wno-write-strings")) @@ -703,6 +784,10 @@ c_decode_option (p) ; /* cpp handles this one. */ else if (!strcmp (p, "-Wno-trigraphs")) ; /* cpp handles this one. */ + else if (!strcmp (p, "-Wundef")) + ; /* cpp handles this one. */ + else if (!strcmp (p, "-Wno-undef")) + ; /* cpp handles this one. */ else if (!strcmp (p, "-Wimport")) ; /* cpp handles this one. */ else if (!strcmp (p, "-Wno-import")) @@ -711,6 +796,24 @@ c_decode_option (p) warn_missing_braces = 1; else if (!strcmp (p, "-Wno-missing-braces")) warn_missing_braces = 0; + else if (!strcmp (p, "-Wmain")) + warn_main = 1; + else if (!strcmp (p, "-Wno-main")) + warn_main = 0; + else if (!strcmp (p, "-Wsign-compare")) + warn_sign_compare = 1; + else if (!strcmp (p, "-Wno-sign-compare")) + warn_sign_compare = 0; + else if (!strcmp (p, "-Wmultichar")) + warn_multichar = 1; + else if (!strcmp (p, "-Wno-multichar")) + warn_multichar = 0; + else if (!strcmp (p, "-Wunknown-pragmas")) + /* Set to greater than 1, so that even unknown pragmas in system + headers will be warned about. */ + warn_unknown_pragmas = 2; + else if (!strcmp (p, "-Wno-unknown-pragmas")) + warn_unknown_pragmas = 0; else if (!strcmp (p, "-Wall")) { /* We save the value of warn_uninitialized, since if they put @@ -718,7 +821,8 @@ c_decode_option (p) warning about not using it without also specifying -O. */ if (warn_uninitialized != 1) warn_uninitialized = 2; - warn_implicit = 1; + warn_implicit_int = 1; + mesg_implicit_function_declaration = 1; warn_return_type = 1; warn_unused = 1; warn_switch = 1; @@ -726,9 +830,14 @@ c_decode_option (p) warn_char_subscripts = 1; warn_parentheses = 1; warn_missing_braces = 1; + /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn + it off only if it's not explicit. */ + warn_main = 2; + /* Only warn about unknown pragmas that are not in system headers. */ + warn_unknown_pragmas = 1; } else - return 0; + return strings_processed; return 1; } @@ -737,17 +846,17 @@ c_decode_option (p) void print_lang_decl (file, node, indent) - FILE *file; - tree node; - int indent; + FILE *file ATTRIBUTE_UNUSED; + tree node ATTRIBUTE_UNUSED; + int indent ATTRIBUTE_UNUSED; { } void print_lang_type (file, node, indent) - FILE *file; - tree node; - int indent; + FILE *file ATTRIBUTE_UNUSED; + tree node ATTRIBUTE_UNUSED; + int indent ATTRIBUTE_UNUSED; { } @@ -772,13 +881,16 @@ void finish_incomplete_decl (decl) tree decl; { - if (TREE_CODE (decl) == VAR_DECL && TREE_TYPE (decl) != error_mark_node) + if (TREE_CODE (decl) == VAR_DECL) { tree type = TREE_TYPE (decl); - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == 0 - && TREE_CODE (decl) != TYPE_DECL) + if (type != error_mark_node + && TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type) == 0) { + if (! DECL_EXTERNAL (decl)) + warning_with_decl (decl, "array `%s' assumed to have one element"); + complete_array_type (type, NULL_TREE, 1); layout_decl (decl, 0); @@ -890,6 +1002,22 @@ pushlevel (tag_transparent) keep_next_if_subblocks = 0; } +/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */ + +static void +clear_limbo_values (block) + tree block; +{ + tree tem; + + for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem)) + if (DECL_NAME (tem) != 0) + IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0; + + for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem)) + clear_limbo_values (tem); +} + /* 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. @@ -980,7 +1108,7 @@ poplevel (keep, reverse, functionbody) 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); @@ -1043,6 +1171,8 @@ poplevel (keep, reverse, functionbody) if (functionbody) { + clear_limbo_values (block); + /* 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 @@ -1299,6 +1429,10 @@ pushtag (name, type) tagged type. */ TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type)); + + /* An approximation for now, so we can tell this is a function-scope tag. + This will be updated in poplevel. */ + TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type)); } /* Handle when a new declaration NEWDECL @@ -1307,11 +1441,15 @@ pushtag (name, type) Prints an error message if appropriate. If safely possible, alter OLDDECL to look like NEWDECL, and return 1. - Otherwise, return 0. */ + Otherwise, return 0. + + When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external declaration, + and OLDDECL is in an outer binding level and should thus not be changed. */ static int -duplicate_decls (newdecl, olddecl) +duplicate_decls (newdecl, olddecl, different_binding_level) register tree newdecl, olddecl; + int different_binding_level; { int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL @@ -1321,7 +1459,8 @@ duplicate_decls (newdecl, olddecl) char *errmsg = 0; if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd') - DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl); + DECL_MACHINE_ATTRIBUTES (newdecl) + = merge_machine_decl_attributes (olddecl, newdecl); if (TREE_CODE (newtype) == ERROR_MARK || TREE_CODE (oldtype) == ERROR_MARK) @@ -1404,8 +1543,8 @@ duplicate_decls (newdecl, olddecl) else if (!types_match) { /* Accept the return type of the new declaration if same modes. */ - tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl)); - tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl)); + tree oldreturntype = TREE_TYPE (oldtype); + tree newreturntype = TREE_TYPE (newtype); /* Make sure we put the new type in the same obstack as the old ones. If the old types are not both in the same obstack, use the @@ -1422,36 +1561,37 @@ duplicate_decls (newdecl, olddecl) { /* Function types may be shared, so we can't just modify the return type of olddecl's function type. */ - tree newtype + tree trytype = build_function_type (newreturntype, - TYPE_ARG_TYPES (TREE_TYPE (olddecl))); + TYPE_ARG_TYPES (oldtype)); - types_match = comptypes (TREE_TYPE (newdecl), newtype); + types_match = comptypes (newtype, trytype); if (types_match) - TREE_TYPE (olddecl) = newtype; + oldtype = trytype; } /* Accept harmless mismatch in first argument type also. This is for ffs. */ if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0 - && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0 - && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl))) != 0 - && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (olddecl))) != 0 - && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl)))) - == - TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (olddecl)))))) + && TYPE_ARG_TYPES (oldtype) != 0 + && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0 + && TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0 + && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype))) + == TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype))))) { /* Function types may be shared, so we can't just modify the return type of olddecl's function type. */ - tree newtype - = build_function_type (TREE_TYPE (TREE_TYPE (olddecl)), + tree trytype + = build_function_type (TREE_TYPE (oldtype), tree_cons (NULL_TREE, - TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl))), - TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (olddecl))))); + TREE_VALUE (TYPE_ARG_TYPES (newtype)), + TREE_CHAIN (TYPE_ARG_TYPES (oldtype)))); - types_match = comptypes (TREE_TYPE (newdecl), newtype); + types_match = comptypes (newtype, trytype); if (types_match) - TREE_TYPE (olddecl) = newtype; + oldtype = trytype; } + if (! different_binding_level) + TREE_TYPE (olddecl) = oldtype; pop_obstacks (); } @@ -1672,7 +1812,7 @@ duplicate_decls (newdecl, olddecl) /* Optionally warn about more than one declaration for the same name. */ if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 - /* Dont warn about a function declaration + /* Don't warn about a function declaration followed by a definition. */ && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0 && DECL_INITIAL (olddecl) == 0) @@ -1691,6 +1831,11 @@ duplicate_decls (newdecl, olddecl) if (types_match) { + /* When copying info to olddecl, we store into write_olddecl + instead. This allows us to avoid modifying olddecl when + different_binding_level is true. */ + tree write_olddecl = different_binding_level ? newdecl : olddecl; + /* Make sure we put the new type in the same obstack as the old ones. If the old types are not both in the same obstack, use the permanent one. */ @@ -1704,9 +1849,18 @@ duplicate_decls (newdecl, olddecl) /* Merge the data types specified in the two decls. */ if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) - TREE_TYPE (newdecl) - = TREE_TYPE (olddecl) - = common_type (newtype, oldtype); + { + if (different_binding_level) + TREE_TYPE (newdecl) + = build_type_attribute_variant + (newtype, + merge_attributes (TYPE_ATTRIBUTES (newtype), + TYPE_ATTRIBUTES (oldtype))); + else + TREE_TYPE (newdecl) + = TREE_TYPE (olddecl) + = common_type (newtype, oldtype); + } /* Lay the type out, unless already done. */ if (oldtype != TREE_TYPE (newdecl)) @@ -1733,37 +1887,37 @@ duplicate_decls (newdecl, olddecl) /* Merge the type qualifiers. */ if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) && !TREE_THIS_VOLATILE (newdecl)) - TREE_THIS_VOLATILE (olddecl) = 0; + TREE_THIS_VOLATILE (write_olddecl) = 0; if (TREE_READONLY (newdecl)) - TREE_READONLY (olddecl) = 1; + TREE_READONLY (write_olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) { - TREE_THIS_VOLATILE (olddecl) = 1; + TREE_THIS_VOLATILE (write_olddecl) = 1; if (TREE_CODE (newdecl) == VAR_DECL) make_var_volatile (newdecl); } - /* Keep source location of definition rather than declaration. - Likewise, keep decl at outer scope. */ - if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) - || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0)) + /* Keep source location of definition rather than declaration. */ + /* When called with different_binding_level set, keep the old + information so that meaningful diagnostics can be given. */ + if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0 + && ! different_binding_level) { DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); - - if (DECL_CONTEXT (olddecl) == 0 - && TREE_CODE (newdecl) != FUNCTION_DECL) - DECL_CONTEXT (newdecl) = 0; } /* Merge the unused-warning information. */ if (DECL_IN_SYSTEM_HEADER (olddecl)) DECL_IN_SYSTEM_HEADER (newdecl) = 1; else if (DECL_IN_SYSTEM_HEADER (newdecl)) - DECL_IN_SYSTEM_HEADER (olddecl) = 1; + DECL_IN_SYSTEM_HEADER (write_olddecl) = 1; /* Merge the initialization information. */ - if (DECL_INITIAL (newdecl) == 0) + /* When called with different_binding_level set, don't copy over + DECL_INITIAL, so that we don't accidentally change function + declarations into function definitions. */ + if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); /* Merge the section attribute. @@ -1783,7 +1937,7 @@ duplicate_decls (newdecl, olddecl) } /* If cannot merge, then use the new type and qualifiers, and don't preserve the old rtl. */ - else + else if (! different_binding_level) { TREE_TYPE (olddecl) = TREE_TYPE (newdecl); TREE_READONLY (olddecl) = TREE_READONLY (newdecl); @@ -1799,6 +1953,8 @@ duplicate_decls (newdecl, olddecl) TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); /* This is since we don't automatically copy the attributes of NEWDECL into OLDDECL. */ + /* No need to worry about different_binding_level here because + then TREE_PUBLIC (newdecl) was true. */ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); /* If this clears `static', clear it in the identifier too. */ if (! TREE_PUBLIC (olddecl)) @@ -1810,6 +1966,8 @@ duplicate_decls (newdecl, olddecl) DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); /* An extern decl does not override previous storage class. */ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); + if (! DECL_EXTERNAL (newdecl)) + DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); } else { @@ -1823,37 +1981,62 @@ duplicate_decls (newdecl, olddecl) DECL_INLINE (olddecl) = 1; DECL_INLINE (newdecl) = DECL_INLINE (olddecl); - /* Get rid of any built-in function if new arg types don't match it - or if we have a function definition. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL - && DECL_BUILT_IN (olddecl) - && (!types_match || new_is_definition)) - { - TREE_TYPE (olddecl) = TREE_TYPE (newdecl); - DECL_BUILT_IN (olddecl) = 0; - } - - /* If redeclaring a builtin function, and not a definition, - it stays built in. - Also preserve various other info from the definition. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition) + if (TREE_CODE (newdecl) == FUNCTION_DECL) { if (DECL_BUILT_IN (olddecl)) { - DECL_BUILT_IN (newdecl) = 1; - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + /* Get rid of any built-in function if new arg types don't match it + or if we have a function definition. */ + if (! types_match || new_is_definition) + { + if (! different_binding_level) + { + TREE_TYPE (olddecl) = TREE_TYPE (newdecl); + DECL_BUILT_IN (olddecl) = 0; + } + } + else + { + /* If redeclaring a builtin function, and not a definition, + it stays built in. */ + DECL_BUILT_IN (newdecl) = 1; + DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + } } - else + /* Also preserve various other info from the definition. */ + else if (! new_is_definition) DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); + if (! new_is_definition) + { + DECL_RESULT (newdecl) = DECL_RESULT (olddecl); + /* When called with different_binding_level set, don't copy over + DECL_INITIAL, so that we don't accidentally change function + declarations into function definitions. */ + if (! different_binding_level) + DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); + DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); + DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); + if (DECL_INLINE (newdecl)) + DECL_ABSTRACT_ORIGIN (newdecl) = olddecl; + } + } + if (different_binding_level) + { + /* Don't output a duplicate symbol or debugging information for this + declaration. - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); - DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); - DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); + Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually + just have two declarations without a definition. VAR_DECLs may need + the same treatment, I'm not sure. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL) + DECL_IGNORED_P (newdecl) = 1; + else + TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1; + return 0; } /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. - But preserve OLDdECL's DECL_UID. */ + But preserve OLDDECL's DECL_UID. */ { register unsigned olddecl_uid = DECL_UID (olddecl); @@ -1863,6 +2046,10 @@ duplicate_decls (newdecl, olddecl) DECL_UID (olddecl) = olddecl_uid; } + /* NEWDECL contains the merged attribute lists. + Update OLDDECL to be the same. */ + DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl); + return 1; } @@ -1900,15 +2087,21 @@ pushdecl (x) { char *file; int line; - int declared_global; + int different_binding_level = 0; + t = lookup_name_current_level (name); /* Don't type check externs here when -traditional. This is so that code with conflicting declarations inside blocks will get warnings not errors. X11 for instance depends on this. */ - if (DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) - t = lookup_name_current_level_global (name); - else - t = lookup_name_current_level (name); + if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) + { + t = IDENTIFIER_GLOBAL_VALUE (name); + /* Type decls at global scope don't conflict with externs declared + inside lexical blocks. */ + if (t && TREE_CODE (t) == TYPE_DECL) + t = 0; + different_binding_level = 1; + } if (t != 0 && t == error_mark_node) /* error_mark_node is 0 for a while during initialization! */ { @@ -1922,10 +2115,29 @@ pushdecl (x) line = DECL_SOURCE_LINE (t); } - /* duplicate_decls might write to TREE_PUBLIC (x) and DECL_EXTERNAL (x) - to make it identical to the initial declaration. */ - declared_global = TREE_PUBLIC (x) || DECL_EXTERNAL (x); - if (t != 0 && duplicate_decls (x, t)) + /* If this decl is `static' and an implicit decl was seen previously, + warn. But don't complain if -traditional, + since traditional compilers don't complain. */ + if (! flag_traditional && TREE_PUBLIC (name) + /* Don't test for DECL_EXTERNAL, because grokdeclarator + sets this for all functions. */ + && ! TREE_PUBLIC (x) + && (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level) + /* We used to warn also for explicit extern followed by static, + but sometimes you need to do it that way. */ + && IDENTIFIER_IMPLICIT_DECL (name) != 0) + { + pedwarn ("`%s' was declared implicitly `extern' and later `static'", + IDENTIFIER_POINTER (name)); + pedwarn_with_file_and_line + (DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)), + DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)), + "previous declaration of `%s'", + IDENTIFIER_POINTER (name)); + TREE_THIS_VOLATILE (name) = 1; + } + + if (t != 0 && duplicate_decls (x, t, different_binding_level)) { if (TREE_CODE (t) == PARM_DECL) { @@ -1934,32 +2146,7 @@ pushdecl (x) TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x); return t; } - /* If this decl is `static' and an implicit decl was seen previously, - warn. But don't complain if -traditional, - since traditional compilers don't complain. */ - if (!flag_traditional && TREE_PUBLIC (name) - - /* should this be '&& ! declared_global' ? */ - && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) - - /* We used to warn also for explicit extern followed by static, - but sometimes you need to do it that way. */ - && IDENTIFIER_IMPLICIT_DECL (name) != 0) - { - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); - pedwarn_with_file_and_line (file, line, - "previous declaration of `%s'", - IDENTIFIER_POINTER (name)); - } - - /* If this is a global decl, and there exists a conflicting local - decl in a parent block, then we can't return as yet, because we - need to register this decl in the current binding block. */ - /* A test for TREE_PUBLIC (x) will fail for variables that have - been declared static first, and extern now. */ - if (! declared_global || lookup_name (name) == t) - return t; + return t; } /* If we are processing a typedef statement, generate a whole new @@ -1981,7 +2168,7 @@ pushdecl (x) MY_TYPE object; Later parts of the compiler might only know that `object' was of - type `struct S' if if were not for code just below. With this + type `struct S' if it were not for code just below. With this code however, later parts of the compiler see something like: struct S' == struct S @@ -2012,10 +2199,11 @@ pushdecl (x) if (TYPE_NAME (TREE_TYPE (x)) == 0) TYPE_NAME (TREE_TYPE (x)) = x; } - else if (TREE_TYPE (x) != error_mark_node) + else if (TREE_TYPE (x) != error_mark_node + && DECL_ORIGINAL_TYPE (x) == NULL_TREE) { tree tt = TREE_TYPE (x); - + DECL_ORIGINAL_TYPE (x) = tt; tt = build_type_copy (tt); TYPE_NAME (tt) = x; TREE_TYPE (x) = tt; @@ -2145,9 +2333,16 @@ pushdecl (x) /* Okay to declare a non-ANSI built-in as anything. */ else if (t != 0 && DECL_BUILT_IN_NONANSI (t)) ; + /* Okay to have global type decl after an earlier extern + declaration inside a lexical block. */ + else if (TREE_CODE (x) == TYPE_DECL) + ; else if (IDENTIFIER_IMPLICIT_DECL (name)) - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); + { + if (! TREE_THIS_VOLATILE (name)) + pedwarn ("`%s' was declared implicitly `extern' and later `static'", + IDENTIFIER_POINTER (name)); + } else pedwarn ("`%s' was declared `extern' and later `static'", IDENTIFIER_POINTER (name)); @@ -2217,11 +2412,11 @@ pushdecl (x) 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 == 0 - && oldglobal == 0 && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { - TREE_PUBLIC (name) = 1; + if (oldglobal == 0) + TREE_PUBLIC (name) = 1; /* Save this decl, so that we can do type checking against other decls after it falls out of scope. @@ -2363,9 +2558,15 @@ implicitly_declare (functionid) rest_of_decl_compilation (decl, NULL_PTR, 0, 0); - if (warn_implicit && implicit_warning) - warning ("implicit declaration of function `%s'", - IDENTIFIER_POINTER (functionid)); + if (mesg_implicit_function_declaration && implicit_warning) + { + if (mesg_implicit_function_declaration == 2) + error ("implicit declaration of function `%s'", + IDENTIFIER_POINTER (functionid)); + else + warning ("implicit declaration of function `%s'", + IDENTIFIER_POINTER (functionid)); + } else if (warn_traditional && traditional_warning) warning ("function `%s' was previously declared within a block", IDENTIFIER_POINTER (functionid)); @@ -2731,32 +2932,9 @@ lookup_name_current_level (name) return t; } - -/* Similar to `lookup_name_current_level' but also look at the global binding - level. */ - -tree -lookup_name_current_level_global (name) - tree name; -{ - register tree t = 0; - - if (current_binding_level == global_binding_level) - return IDENTIFIER_GLOBAL_VALUE (name); - - if (IDENTIFIER_LOCAL_VALUE (name) != 0) - for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name) - break; - - if (t == 0) - t = IDENTIFIER_GLOBAL_VALUE (name); - - return t; -} /* Create the predefined scalar types of C, - and some nodes representing standard constants (0, 1, (void *)0). + and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global binding level. Make definitions for built-in primitive functions. */ @@ -2767,8 +2945,8 @@ init_decl_processing () /* Either char* or void*. */ tree traditional_ptr_type_node; /* Data types of memcpy and strlen. */ - tree memcpy_ftype, strlen_ftype; - tree void_ftype_any; + tree memcpy_ftype, memset_ftype, strlen_ftype; + tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr; int wchar_type_size; tree temp; tree array_domain_type; @@ -2816,37 +2994,29 @@ init_decl_processing () pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"), long_long_unsigned_type_node)); + short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"), + short_integer_type_node)); + + short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"), + short_unsigned_type_node)); + /* `unsigned long' is the standard type for sizeof. Traditionally, use a signed type. Note that stddef.h uses `unsigned long', - and this must agree, even of long and int are the same size. */ - sizetype - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))); + and this must agree, even if long and int are the same size. */ + set_sizetype + (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)))); if (flag_traditional && TREE_UNSIGNED (sizetype)) - sizetype = signed_type (sizetype); + set_sizetype (signed_type (sizetype)); ptrdiff_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE))); - TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype; - 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)); - - short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"), - short_unsigned_type_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"), @@ -2868,6 +3038,9 @@ init_decl_processing () intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode)); pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); + intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node)); + unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode)); pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); @@ -2880,6 +3053,9 @@ 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)); + unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node)); + float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT], @@ -3074,6 +3250,19 @@ init_decl_processing () sizetype, endlink)))); + memset_ftype /* memset prototype */ + = build_function_type (traditional_ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, + sizetype, + endlink)))); + + ptr_ftype_void = build_function_type (ptr_type_node, endlink); + ptr_ftype_ptr + = build_function_type (ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink)); + builtin_function ("__builtin_constant_p", default_function_type, BUILT_IN_CONSTANT_P, NULL_PTR); @@ -3091,6 +3280,44 @@ init_decl_processing () endlink)), BUILT_IN_FRAME_ADDRESS, NULL_PTR); + builtin_function ("__builtin_aggregate_incoming_address", + build_function_type (ptr_type_node, NULL_TREE), + BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR); + + /* Hooks for the DWARF 2 __throw routine. */ + 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_fp_regnum", + build_function_type (unsigned_type_node, endlink), + BUILT_IN_DWARF_FP_REGNUM, NULL_PTR); + builtin_function ("__builtin_dwarf_reg_size", int_ftype_int, + BUILT_IN_DWARF_REG_SIZE, NULL_PTR); + builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr, + 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", + 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); + builtin_function ("__builtin_alloca", build_function_type (ptr_type_node, tree_cons (NULL_TREE, @@ -3182,6 +3409,8 @@ init_decl_processing () BUILT_IN_MEMCPY, "memcpy"); builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, "memcmp"); + builtin_function ("__builtin_memset", memset_ftype, + BUILT_IN_MEMSET, "memset"); builtin_function ("__builtin_strcmp", int_ftype_string_string, BUILT_IN_STRCMP, "strcmp"); builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, @@ -3206,6 +3435,22 @@ init_decl_processing () BUILT_IN_COS, "cos"); builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, BUILT_IN_COS, "cosl"); + builtin_function ("__builtin_setjmp", + build_function_type (integer_type_node, + tree_cons (NULL_TREE, + ptr_type_node, endlink)), + BUILT_IN_SETJMP, NULL_PTR); + builtin_function ("__builtin_longjmp", + build_function_type + (void_type_node, + tree_cons (NULL, ptr_type_node, + tree_cons (NULL_TREE, + integer_type_node, + endlink))), + BUILT_IN_LONGJMP, NULL_PTR); + builtin_function ("__builtin_trap", + build_function_type (void_type_node, endlink), + BUILT_IN_TRAP, NULL_PTR); /* In an ANSI C program, it is okay to supply built-in meanings for these functions, since applications cannot validly use them @@ -3222,6 +3467,7 @@ init_decl_processing () builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR); builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, NULL_PTR); + builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET, NULL_PTR); builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR); builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, @@ -3264,8 +3510,6 @@ init_decl_processing () BUILT_IN_FMOD, NULL_PTR); builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, NULL_PTR); - builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, - BUILT_IN_MEMSET, NULL_PTR); builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, NULL_PTR); builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, @@ -3285,6 +3529,8 @@ init_decl_processing () init_iterators (); incomplete_decl_finalize_hook = finish_incomplete_decl; + + lang_get_alias_set = &c_get_alias_set; } /* Return a definition for a builtin function named NAME and whose data type @@ -3351,10 +3597,15 @@ shadow_tag_warned (declspecs, warned) { int found_tag = 0; register tree link; + tree specs, attrs; pending_invalid_xref = 0; - for (link = declspecs; link; link = TREE_CHAIN (link)) + /* Remove the attributes from declspecs, since they will confuse the + following code. */ + split_specs_attrs (declspecs, &specs, &attrs); + + for (link = specs; link; link = TREE_CHAIN (link)) { register tree value = TREE_VALUE (link); register enum tree_code code = TREE_CODE (value); @@ -3467,6 +3718,10 @@ 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 + && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main")) + warning_with_decl (decl, "`%s' is usually a function"); + if (initialized) /* Is it valid for this decl to have an initializer at all? If not, set INITIALIZED to zero, which will indirectly @@ -3551,9 +3806,17 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) if (TREE_CODE (decl) == FUNCTION_DECL) gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0); - /* For C and Objective-C, we by default put things in .common when - possible. */ - DECL_COMMON (decl) = 1; + /* ANSI specifies that a tentative definition which is not merged with + a non-tentative definition behaves exactly like a definition with an + initializer equal to zero. (Section 3.7.2) + -fno-common gives strict ANSI behavior. Usually you don't want it. + This matters only for variables with external linkage. */ + if (! flag_no_common || ! TREE_PUBLIC (decl)) + DECL_COMMON (decl) = 1; + +#ifdef SET_DEFAULT_DECL_ATTRIBUTES + SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes); +#endif /* Set attributes here so if duplicate decl, will have proper attributes. */ decl_attributes (decl, attributes, prefix_attributes); @@ -3703,10 +3966,11 @@ finish_decl (decl, init, asmspec_tree) Also if it is not file scope. Otherwise, let it through, but if it is not `extern' then it may cause an error message later. */ - /* We must use DECL_CONTEXT instead of current_binding_level, - because a duplicate_decls call could have changed the binding - level of this decl. */ - (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0) + /* A duplicate_decls call could have changed an extern + declaration into a file scope one. This can be detected + by TREE_ASM_WRITTEN being set. */ + (DECL_INITIAL (decl) != 0 + || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl))) : /* An automatic variable with an incomplete type is an error. */ @@ -3724,6 +3988,9 @@ finish_decl (decl, init, asmspec_tree) else error_with_decl (decl, "storage size of `%s' isn't constant"); } + + if (TREE_USED (type)) + TREE_USED (decl) = 1; } /* If this is a function and an assembler name is specified, it isn't @@ -3748,7 +4015,9 @@ finish_decl (decl, init, asmspec_tree) end_temporary_allocation (); /* This is a no-op in c-lang.c or something real in objc-actions.c. */ maybe_objc_check_decl (decl); - rest_of_decl_compilation (decl, asmspec, DECL_CONTEXT (decl) == 0, + rest_of_decl_compilation (decl, asmspec, + (DECL_CONTEXT (decl) == 0 + || TREE_ASM_WRITTEN (decl)), 0); pop_obstacks (); } @@ -3871,7 +4140,7 @@ finish_decl (decl, init, asmspec_tree) tree maybe_build_cleanup (decl) - tree decl; + tree decl ATTRIBUTE_UNUSED; { /* There are no cleanups in C. */ return NULL_TREE; @@ -3990,12 +4259,6 @@ complete_array_type (type, initial_value, do_default) TYPE_DOMAIN (type) = build_index_type (maxindex); if (!TREE_TYPE (maxindex)) TREE_TYPE (maxindex) = TYPE_DOMAIN (type); -#if 0 /* I took out this change - together with the change in build_array_type. --rms */ - change_main_variant (type, - build_array_type (TREE_TYPE (type), - TYPE_DOMAIN (type))); -#endif } /* Lay out the type now that we can get the real answer. */ @@ -4151,7 +4414,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) error ("`long long long' is too long for GCC"); else { - if (pedantic && ! in_system_header) + if (pedantic && ! in_system_header && warn_long_long) pedwarn ("ANSI C does not support `long long'"); longlong = 1; } @@ -4201,10 +4464,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (type == 0) { - if (funcdef_flag && warn_return_type - && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_SIGNED) | (1 << (int) RID_UNSIGNED)))) - warn_about_return_type = 1; + if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) + | (1 << (int) RID_SIGNED) + | (1 << (int) RID_UNSIGNED)))) + /* Don't warn about typedef foo = bar. */ + && ! (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. */ + if ((warn_implicit_int || warn_return_type) && funcdef_flag) + warn_about_return_type = 1; + else if (warn_implicit_int) + warning ("type defaults to `int' in declaration of `%s'", name); + } + defaulted_int = 1; type = integer_type_node; } @@ -4214,7 +4490,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Long double is a special combination. */ - if ((specbits & 1 << (int) RID_LONG) + if ((specbits & 1 << (int) RID_LONG) && ! longlong && TYPE_MAIN_VARIANT (type) == double_type_node) { specbits &= ~ (1 << (int) RID_LONG); @@ -4228,11 +4504,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { int ok = 0; - if (TREE_CODE (type) != INTEGER_TYPE) - error ("long, short, signed or unsigned invalid for `%s'", name); - else if ((specbits & 1 << (int) RID_LONG) - && (specbits & 1 << (int) RID_SHORT)) - error ("long and short specified together for `%s'", name); + if ((specbits & 1 << (int) RID_LONG) + && (specbits & 1 << (int) RID_SHORT)) + error ("both long and short specified for `%s'", name); else if (((specbits & 1 << (int) RID_LONG) || (specbits & 1 << (int) RID_SHORT)) && explicit_char) @@ -4240,10 +4514,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else if (((specbits & 1 << (int) RID_LONG) || (specbits & 1 << (int) RID_SHORT)) && TREE_CODE (type) == REAL_TYPE) - error ("long or short specified with floating type for `%s'", name); + { + static int already = 0; + + error ("long or short specified with floating type for `%s'", name); + if (! already && ! pedantic) + { + error ("the only valid combination is `long double'"); + already = 1; + } + } else if ((specbits & 1 << (int) RID_SIGNED) && (specbits & 1 << (int) RID_UNSIGNED)) - error ("signed and unsigned given together for `%s'", name); + error ("both signed and unsigned specified for `%s'", name); + else if (TREE_CODE (type) != INTEGER_TYPE) + error ("long, short, signed or unsigned invalid for `%s'", name); else { ok = 1; @@ -4538,6 +4823,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) convert (index_type, size), convert (index_type, size_one_node))); + /* If that overflowed, the array is too big. + ??? While a size of INT_MAX+1 technically shouldn't cause + an overflow (because we subtract 1), the overflow is recorded + during the conversion to index_type, before the subtraction. + Handling this case seems like an unnecessary complication. */ + if (TREE_OVERFLOW (itype)) + { + error ("size of array `%s' is too large", name); + type = error_mark_node; + continue; + } + if (size_varies) itype = variable_size (itype); itype = build_index_type (itype); @@ -4656,7 +4953,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { register tree link; - for (link = current_function_parm_tags; + for (link = last_function_parm_tags; link; link = TREE_CHAIN (link)) TYPE_CONTEXT (TREE_VALUE (link)) = type; @@ -4713,6 +5010,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Now TYPE has the actual type. */ + /* Did array size calculations overflow? */ + + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) + && TREE_OVERFLOW (TYPE_SIZE (type))) + error ("size of array `%s' is too large", name); + /* If this is declaring a typedef name, return a TYPE_DECL. */ if (specbits & (1 << (int) RID_TYPEDEF)) @@ -4725,11 +5029,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) pedwarn ("ANSI C forbids const or volatile function types"); if (constp || volatilep) type = c_build_type_variant (type, constp, volatilep); - pop_obstacks (); decl = build_decl (TYPE_DECL, declarator, type); if ((specbits & (1 << (int) RID_SIGNED)) || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; + pop_obstacks (); return decl; } @@ -4909,6 +5213,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) && ! DECL_IN_SYSTEM_HEADER (decl)) pedwarn ("ANSI C forbids const or volatile functions"); + 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)))) + && ! DECL_IN_SYSTEM_HEADER (decl)) + pedwarn ("ANSI C forbids const or volatile void function return type"); + if (volatilep && TREE_TYPE (TREE_TYPE (decl)) != void_type_node) warning ("`noreturn' function returns non-void value"); @@ -4922,13 +5233,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Record presence of `inline', if it is reasonable. */ if (inlinep) { - tree last = tree_last (TYPE_ARG_TYPES (type)); - if (! strcmp (IDENTIFIER_POINTER (declarator), "main")) warning ("cannot inline function `main'"); - else if (last && (TYPE_MAIN_VARIANT (TREE_VALUE (last)) - != void_type_node)) - warning ("inline declaration ignored for function with `...'"); else /* Assume that otherwise the function can be inlined. */ DECL_INLINE (decl) = 1; @@ -5248,7 +5554,7 @@ parmlist_tags_warning () enum tree_code code = TREE_CODE (TREE_VALUE (elt)); /* An anonymous union parm type is meaningful as a GNU extension. So don't warn for that. */ - if (code == UNION_TYPE && !pedantic) + if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic) continue; if (TREE_PURPOSE (elt) != 0) warning ("`%s %s' declared inside parameter list", @@ -5351,6 +5657,7 @@ start_struct (code, name) if (ref && TREE_CODE (ref) == code) { C_TYPE_BEING_DEFINED (ref) = 1; + TYPE_PACKED (ref) = flag_pack_struct; if (TYPE_FIELDS (ref)) error ((code == UNION_TYPE ? "redefinition of `union %s'" : "redefinition of `struct %s'"), @@ -5364,6 +5671,7 @@ start_struct (code, name) ref = make_node (code); pushtag (name, ref); C_TYPE_BEING_DEFINED (ref) = 1; + TYPE_PACKED (ref) = flag_pack_struct; return ref; } @@ -5398,9 +5706,12 @@ grokfield (filename, line, declarator, declspecs, width) /* Function to help qsort sort FIELD_DECLs by name order. */ static int -field_decl_cmp (x, y) - tree *x, *y; +field_decl_cmp (xp, yp) + const GENERIC_PTR xp; + const GENERIC_PTR yp; { + tree *x = (tree *)xp, *y = (tree *)yp; + if (DECL_NAME (*x) == DECL_NAME (*y)) return 0; if (DECL_NAME (*x) == NULL) @@ -5450,9 +5761,17 @@ finish_struct (t, fieldlist, attributes) old_momentary = suspend_momentary (); - if (fieldlist == 0 && pedantic) - pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union has no members" - : "structure has no members")); + if (pedantic) + { + for (x = fieldlist; x; x = TREE_CHAIN (x)) + if (DECL_NAME (x) != 0) + break; + + if (x == 0) + pedwarn ("%s has no %smembers", + (TREE_CODE (t) == UNION_TYPE ? "union" : "structure"), + (fieldlist ? "named " : "")); + } /* Install struct as DECL_CONTEXT of each field decl. Also process specified field sizes. @@ -5554,8 +5873,15 @@ finish_struct (t, fieldlist, attributes) { register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); + if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE + && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) + || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))))) + warning_with_decl (x, "`%s' is narrower than values of its type"); + DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = 1; + DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1; DECL_INITIAL (x) = NULL; if (width == 0) @@ -5565,14 +5891,15 @@ finish_struct (t, fieldlist, attributes) 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 if (TREE_TYPE (x) != error_mark_node) { - int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT + unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT : TYPE_ALIGN (TREE_TYPE (x))); /* Non-bit-fields are aligned for their type, except packed fields which require only BITS_PER_UNIT alignment. */ @@ -5675,27 +6002,6 @@ finish_struct (t, fieldlist, attributes) TYPE_ALIGN (x) = TYPE_ALIGN (t); } - /* Promote each bit-field's type to int if it is narrower than that. */ - for (x = fieldlist; x; x = TREE_CHAIN (x)) - if (DECL_BIT_FIELD (x) - && (C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x)) - || DECL_FIELD_SIZE (x) < TYPE_PRECISION (integer_type_node))) - { - tree type = TREE_TYPE (x); - - /* Preserve unsignedness if traditional - or if not really getting any wider. */ - if (TREE_UNSIGNED (type) - && (flag_traditional - || - (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) - && - DECL_FIELD_SIZE (x) == TYPE_PRECISION (integer_type_node)))) - TREE_TYPE (x) = unsigned_type_node; - else - TREE_TYPE (x) = integer_type_node; - } - /* If this was supposed to be a transparent union, but we can't make it one, warn and turn off the flag. */ if (TREE_CODE (t) == UNION_TYPE @@ -5703,7 +6009,7 @@ finish_struct (t, fieldlist, attributes) && TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))) { TYPE_TRANSPARENT_UNION (t) = 0; - warning ("cannot make `%s' a transparent union"); + warning ("union cannot be made transparent"); } /* If this structure or union completes the type of any previous @@ -5805,6 +6111,9 @@ start_enum (name) enum_next_value = integer_zero_node; enum_overflow = 0; + if (flag_short_enums) + TYPE_PACKED (enumtype) = 1; + return enumtype; } @@ -5861,10 +6170,17 @@ finish_enum (enumtype, values, attributes) highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype)); precision = MAX (lowprec, highprec); - if (flag_short_enums || TYPE_PACKED (enumtype) - || 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)); + if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) + { + tree narrowest = type_for_size (precision, 1); + if (narrowest == 0) + { + warning ("enumeration values exceed range of largest integer"); + narrowest = long_long_integer_type_node; + } + + TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest); + } else TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); @@ -5900,6 +6216,7 @@ finish_enum (enumtype, values, attributes) 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); @@ -6007,7 +6324,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested) tree restype; int old_immediate_size_expand = immediate_size_expand; - current_function_returns_value = 0; /* Assume, until we see it does. */ + current_function_returns_value = 0; /* Assume, until we see it does. */ current_function_returns_null = 0; warn_about_return_type = 0; current_extern_inline = 0; @@ -6023,7 +6340,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested) /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == 0) - return 0; + { + immediate_size_expand = old_immediate_size_expand; + return 0; + } decl_attributes (decl1, prefix_attributes, attributes); @@ -6116,6 +6436,67 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested) if (current_function_decl != 0) TREE_PUBLIC (decl1) = 0; + /* Warn for unlikely, improbable, or stupid declarations of `main'. */ + if (warn_main + && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0) + { + tree args; + int argct = 0; + + if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) + != integer_type_node) + pedwarn_with_decl (decl1, "return type of `%s' is not `int'"); + + for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args; + args = TREE_CHAIN (args)) + { + tree type = args ? TREE_VALUE (args) : 0; + + if (type == void_type_node) + break; + + ++argct; + switch (argct) + { + case 1: + if (TYPE_MAIN_VARIANT (type) != integer_type_node) + pedwarn_with_decl (decl1, + "first argument of `%s' should be `int'"); + break; + + case 2: + if (TREE_CODE (type) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) + != char_type_node)) + pedwarn_with_decl (decl1, + "second argument of `%s' should be `char **'"); + break; + + case 3: + if (TREE_CODE (type) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) + != char_type_node)) + pedwarn_with_decl (decl1, + "third argument of `%s' should probably be `char **'"); + break; + } + } + + /* It is intentional that this message does not mention the third + argument, which is warned for only pedantically, because it's + blessed by mention in an appendix of the standard. */ + if (argct > 0 && (argct < 2 || argct > 3)) + pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments"); + + if (argct == 3 && pedantic) + pedwarn_with_decl (decl1, "third argument of `%s' is deprecated"); + + if (! TREE_PUBLIC (decl1)) + pedwarn_with_decl (decl1, "`%s' is normally a non-static function"); + } + /* 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. */ @@ -6729,7 +7110,9 @@ combine_parm_decls (specparms, parmlist, void_at_end) if (void_at_end) return saveable_tree_cons (parmdecls, nonparms, - nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types))); + nreverse (saveable_tree_cons (NULL_TREE, + void_type_node, + types))); return saveable_tree_cons (parmdecls, nonparms, nreverse (types)); } @@ -6766,19 +7149,28 @@ finish_function (nested) setjmp_protect_args (); } -#ifdef DEFAULT_MAIN_RETURN if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")) { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != integer_type_node) - warning_with_decl (fndecl, "return type of `%s' is not `int'"); + { + /* 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) + pedwarn_with_decl (fndecl, "return type of `%s' is not `int'"); + } else { +#ifdef DEFAULT_MAIN_RETURN /* Make it so that `main' always returns success by default. */ DEFAULT_MAIN_RETURN; +#endif } } -#endif /* Generate rtl for function exit. */ expand_function_end (input_filename, lineno, 0); @@ -6962,6 +7354,6 @@ pop_c_function_context () void copy_lang_decl (node) - tree node; + tree node ATTRIBUTE_UNUSED; { } diff --git a/contrib/gcc/c-iterate.c b/contrib/gcc/c-iterate.c index b35a167..b8f51d0 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, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92, 93, 96, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -24,26 +24,14 @@ Boston, MA 02111-1307, USA. */ both their declarations and the expansion of statements using them. */ #include "config.h" -#include +#include "system.h" #include "tree.h" #include "c-tree.h" #include "flags.h" #include "obstack.h" #include "rtl.h" - -static void expand_stmt_with_iterators_1 (); -static tree collect_iterators (); -static void iterator_loop_prologue (); -static void iterator_loop_epilogue (); -static void add_ixpansion (); -static void delete_ixpansion(); -static int top_level_ixpansion_p (); -static void istack_sublevel_to_current (); - -/* A special obstack, and a pointer to the start of - all the data in it (so we can free everything easily). */ -static struct obstack ixp_obstack; -static char *ixp_firstobj; +#include "toplev.h" +#include "expr.h" /* KEEPING TRACK OF EXPANSIONS @@ -96,11 +84,26 @@ struct iter_stack_node }; struct iter_stack_node *iter_stack; - struct iter_stack_node sublevel_ixpansions; +/* A special obstack, and a pointer to the start of + all the data in it (so we can free everything easily). */ +static struct obstack ixp_obstack; +static char *ixp_firstobj; + /* During collect_iterators, a list of SAVE_EXPRs already scanned. */ static tree save_exprs; + +static void expand_stmt_with_iterators_1 PROTO((tree, tree)); +static tree collect_iterators PROTO((tree, tree)); +static void iterator_loop_prologue PROTO((tree, rtx *, rtx *)); +static void iterator_loop_epilogue PROTO((tree, rtx *, rtx *)); +static int top_level_ixpansion_p PROTO((void)); +static void isn_append PROTO((struct iter_stack_node *, + struct iter_stack_node *)); +static void istack_sublevel_to_current PROTO((void)); +static void add_ixpansion PROTO((tree, rtx, rtx, rtx, rtx)); +static void delete_ixpansion PROTO((tree)); /* Initialize our obstack once per compilation. */ @@ -254,6 +257,8 @@ collect_iterators (exp, list) break; case RTL_EXPR: return list; + default: + break; } for (i = 0; i < num_args; i++) @@ -283,7 +288,8 @@ iterator_loop_prologue (idecl, start_note, end_note) /* Force the save_expr in DECL_INITIAL to be calculated if it hasn't been calculated yet. */ - expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode, 0); + expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode, + EXPAND_NORMAL); if (DECL_RTL (idecl) == 0) expand_decl (idecl); @@ -294,7 +300,7 @@ iterator_loop_prologue (idecl, start_note, end_note) /* Initialize counter. */ expr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, integer_zero_node); TREE_SIDE_EFFECTS (expr) = 1; - expand_expr (expr, const0_rtx, VOIDmode, 0); + expand_expr (expr, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_start_loop_continue_elsewhere (1); @@ -335,7 +341,7 @@ iterator_loop_epilogue (idecl, start_note, end_note) incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0); incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr); TREE_SIDE_EFFECTS (incr) = 1; - expand_expr (incr, const0_rtx, VOIDmode, 0); + expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL); test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0); expand_exit_loop_if_false (0, test); expand_end_loop (); @@ -343,7 +349,9 @@ iterator_loop_epilogue (idecl, start_note, end_note) ITERATOR_BOUND_P (idecl) = 0; /* we can reset rtl since there is not chance that this expansion */ /* would be superseded by a higher level one */ - if (top_level_ixpansion_p ()) + /* but don't do this if the decl is static, since we need to share */ + /* the same decl in that case. */ + if (top_level_ixpansion_p () && ! TREE_STATIC (idecl)) DECL_RTL (idecl) = 0; if (end_note) *end_note = emit_note (0, NOTE_INSN_DELETED); @@ -409,7 +417,7 @@ void push_iterator_stack () { struct iter_stack_node *new_top - = (struct iter_stack_node*) + = (struct iter_stack_node *) obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node)); new_top->first = 0; @@ -442,15 +450,15 @@ add_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end) tree idecl; rtx pro_start, pro_end, epi_start, epi_end; { - struct ixpansion* newix; + struct ixpansion *newix; /* Do nothing if we are not inside "({...})", as in that case this expansion can't need subsequent RTL modification. */ if (iter_stack == 0) return; - newix = (struct ixpansion*) obstack_alloc (&ixp_obstack, - sizeof (struct ixpansion)); + newix = (struct ixpansion *) obstack_alloc (&ixp_obstack, + sizeof (struct ixpansion)); newix->ixdecl = idecl; newix->ixprologue_start = pro_start; newix->ixprologue_end = pro_end; @@ -471,7 +479,7 @@ static void delete_ixpansion (idecl) tree idecl; { - struct ixpansion* previx = 0, *ix; + struct ixpansion *previx = 0, *ix; for (ix = sublevel_ixpansions.first; ix; ix = ix->next) if (ix->ixdecl == idecl) @@ -577,7 +585,7 @@ pixl (head) return head; } -/* Print Iterator Stack*/ +/* Print Iterator Stack. */ void pis () diff --git a/contrib/gcc/c-lang.c b/contrib/gcc/c-lang.c index ef9f184..8a5fd6b 100644 --- a/contrib/gcc/c-lang.c +++ b/contrib/gcc/c-lang.c @@ -1,5 +1,5 @@ /* Language-specific hook definitions for C front end. - Copyright (C) 1991, 1995 Free Software Foundation, Inc. + Copyright (C) 1991, 1995, 1997, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -20,27 +20,39 @@ Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "tree.h" -#include #include "input.h" +#include "c-tree.h" +#include "c-lex.h" +#include "toplev.h" +#include "output.h" /* Each of the functions defined here is an alternative to a function in objc-actions.c. */ int -lang_decode_option (p) - char *p; +lang_decode_option (argc, argv) + int argc; + char **argv; +{ + return c_decode_option (argc, argv); +} + +void +lang_init_options () { - return c_decode_option (p); } 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. */ ungetc (check_newline (), finput); +#endif } void @@ -59,39 +71,50 @@ print_lang_statistics () { } +/* used by print-tree.c */ + +void +lang_print_xnode (file, node, indent) + FILE *file ATTRIBUTE_UNUSED; + tree node ATTRIBUTE_UNUSED; + int indent ATTRIBUTE_UNUSED; +{ +} + /* Used by c-lex.c, but only for objc. */ tree lookup_interface (arg) - tree arg; + tree arg ATTRIBUTE_UNUSED; { return 0; } tree is_class_name (arg) - tree arg; + tree arg ATTRIBUTE_UNUSED; { return 0; } void maybe_objc_check_decl (decl) - tree decl; + tree decl ATTRIBUTE_UNUSED; { } int maybe_objc_comptypes (lhs, rhs, reflexive) - tree lhs, rhs; - int reflexive; + tree lhs ATTRIBUTE_UNUSED; + tree rhs ATTRIBUTE_UNUSED; + int reflexive ATTRIBUTE_UNUSED; { return -1; } tree maybe_objc_method_name (decl) - tree decl; + tree decl ATTRIBUTE_UNUSED; { return 0; } @@ -110,33 +133,28 @@ recognize_objc_keyword () tree build_objc_string (len, str) - int len; - char *str; + int len ATTRIBUTE_UNUSED; + char *str ATTRIBUTE_UNUSED; { abort (); return NULL_TREE; } -void -GNU_xref_begin () -{ - fatal ("GCC does not yet support XREF"); -} - -void -GNU_xref_end () -{ - fatal ("GCC does not yet support XREF"); -} +/* Called at end of parsing, but before end-of-file processing. */ -/* called at end of parsing, but before end-of-file processing. */ void finish_file () { - extern tree static_ctors, static_dtors; - extern tree get_file_function_name (); +#ifndef ASM_OUTPUT_CONSTRUCTOR + extern tree static_ctors; +#endif +#ifndef ASM_OUTPUT_DESTRUCTOR + extern tree static_dtors; +#endif extern tree build_function_call PROTO((tree, tree)); +#if !defined(ASM_OUTPUT_CONSTRUCTOR) || !defined(ASM_OUTPUT_DESTRUCTOR) tree void_list_node = build_tree_list (NULL_TREE, void_type_node); +#endif #ifndef ASM_OUTPUT_CONSTRUCTOR if (static_ctors) { diff --git a/contrib/gcc/c-lex.c b/contrib/gcc/c-lex.c index 007b363..f82ad76 100644 --- a/contrib/gcc/c-lex.c +++ b/contrib/gcc/c-lex.c @@ -1,5 +1,5 @@ /* Lexical analyzer for C and Objective C. - Copyright (C) 1987, 88, 89, 92, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92, 94-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -18,32 +18,43 @@ 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 -#include +#include "config.h" +#include "system.h" #include -#include "config.h" #include "rtl.h" #include "tree.h" #include "input.h" +#include "output.h" #include "c-lex.h" #include "c-tree.h" #include "flags.h" #include "c-parse.h" #include "c-pragma.h" +#include "toplev.h" -#include +/* 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 #include #endif -#ifndef errno -extern int errno; +#if USE_CPPLIB +#include "cpplib.h" +extern cpp_reader parse_in; +extern cpp_options parse_options; +#else +/* Stream for reading from the input file. */ +FILE *finput; #endif +extern void yyprint PROTO((FILE *, int, YYSTYPE)); + /* The elements of `ridpointers' are identifier nodes for the reserved type names and storage classes. It is indexed by a RID_... value. */ @@ -52,6 +63,18 @@ tree ridpointers[(int) RID_MAX]; /* Cause the `yydebug' variable to be defined. */ #define YYDEBUG 1 +#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--) +#else +#define GETC() getc (finput) +#define UNGETC(c) ungetc (c, finput) +#endif + /* the declaration found for the last IDENTIFIER token read in. yylex must look this up to detect typedefs, which get token type TYPENAME, so it is left around in case the identifier is not a typedef but is @@ -62,8 +85,6 @@ tree lastiddecl; int doing_objc_thang; -extern tree is_class_name (); - extern int yydebug; /* File used for outputting assembler code. */ @@ -85,13 +106,24 @@ char *token_buffer; /* Pointer to token buffer. Actual allocated length is maxtoken + 2. This is not static because objc-parse.y uses it. */ +static int indent_level = 0; /* Number of { minus number of }. */ + /* Nonzero if end-of-file has been seen on input. */ static int end_of_file; +#if !USE_CPPLIB /* Buffered-back input character; faster than using ungetc. */ static int nextchar = -1; +#endif -int check_newline (); +#ifdef HANDLE_SYSV_PRAGMA +static int handle_sysv_pragma PROTO((int)); +#endif /* HANDLE_SYSV_PRAGMA */ +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 int readescape PROTO((int *)); /* Do not insert generated code into the source, instead, include it. This allows us to build gcc automatically even for targets that @@ -142,6 +174,51 @@ remember_protocol_qualifiers () wordlist[i].name = "oneway"; } +char * +init_parse (filename) + char *filename; +{ +#if !USE_CPPLIB + /* Open input file. */ + if (filename == 0 || !strcmp (filename, "-")) + { + finput = stdin; + filename = "stdin"; + } + else + finput = fopen (filename, "r"); + if (finput == 0) + pfatal_with_name (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; + + parse_in.show_column = 1; + if (! cpp_start_read (&parse_in, filename)) + abort (); +#endif + + return filename; +} + +void +finish_parse () +{ +#if USE_CPPLIB + cpp_finish (&parse_in); +#else + fclose (finput); +#endif +} + void init_lex () { @@ -245,10 +322,14 @@ yyprint (file, yychar, yylval) if (TREE_CODE (t) == INTEGER_CST) fprintf (file, #if HOST_BITS_PER_WIDE_INT == 64 -#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + " 0x%x%016x", +#else +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG " 0x%lx%016lx", #else - " 0x%x%016x", + " 0x%llx%016llx", +#endif #endif #else #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT @@ -261,8 +342,30 @@ yyprint (file, yychar, yylval) break; } } - +/* Iff C is a carriage return, warn about it - if appropriate - + and return nonzero. */ +static int +whitespace_cr (c) + int c; +{ + static int newline_warning = 0; + + if (c == '\r') + { + /* ANSI C says the effects of a carriage return in a source file + are undefined. */ + if (pedantic && !newline_warning) + { + warning ("carriage return in source file"); + warning ("(we only warn about the first carriage return)"); + newline_warning = 1; + } + return 1; + } + return 0; +} + /* If C is not whitespace, return C. Otherwise skip whitespace and return first nonwhite char read. */ @@ -270,8 +373,6 @@ static int skip_white_space (c) register int c; { - static int newline_warning = 0; - for (;;) { switch (c) @@ -289,28 +390,21 @@ skip_white_space (c) case '\f': case '\v': case '\b': - c = getc (finput); + c = GETC(); break; case '\r': - /* ANSI C says the effects of a carriage return in a source file - are undefined. */ - if (pedantic && !newline_warning) - { - warning ("carriage return in source file"); - warning ("(we only warn about the first carriage return)"); - newline_warning = 1; - } - c = getc (finput); + whitespace_cr (c); + c = GETC(); break; case '\\': - c = getc (finput); + c = GETC(); if (c == '\n') lineno++; else error ("stray '\\' in program"); - c = getc (finput); + c = GETC(); break; default: @@ -327,12 +421,46 @@ position_after_white_space () { register int c; +#if !USE_CPPLIB if (nextchar != -1) c = nextchar, nextchar = -1; else - c = getc (finput); +#endif + c = GETC(); - ungetc (skip_white_space (c), finput); + UNGETC (skip_white_space (c)); +} + +/* Like skip_white_space, but don't advance beyond the end of line. + Moreover, we don't get passed a character to start with. */ +static int +skip_white_space_on_line () +{ + register int c; + + while (1) + { + c = GETC(); + switch (c) + { + case '\n': + default: + break; + + case ' ': + case '\t': + case '\f': + case '\v': + case '\b': + continue; + + case '\r': + whitespace_cr (c); + continue; + } + break; + } + return c; } /* Make the token buffer longer, preserving the data in it. @@ -367,9 +495,9 @@ check_newline () /* Read first nonwhite char on the line. */ - c = getc (finput); + c = GETC(); while (c == ' ' || c == '\t') - c = getc (finput); + c = GETC(); if (c != '#') { @@ -379,9 +507,9 @@ check_newline () /* Read first nonwhite char after the `#'. */ - c = getc (finput); + c = GETC(); while (c == ' ' || c == '\t') - c = getc (finput); + c = GETC(); /* If a letter follows, then if the word here is `line', skip it and ignore it; otherwise, ignore the line, with an error @@ -391,86 +519,105 @@ check_newline () { if (c == 'p') { - if (getc (finput) == 'r' - && getc (finput) == 'a' - && getc (finput) == 'g' - && getc (finput) == 'm' - && getc (finput) == 'a' - && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n')) + if (GETC() == 'r' + && GETC() == 'a' + && GETC() == 'g' + && GETC() == 'm' + && GETC() == 'a' + && ((c = GETC()) == ' ' || c == '\t' || c == '\n' + || whitespace_cr (c) )) { + while (c == ' ' || c == '\t' || whitespace_cr (c)) + c = GETC (); + if (c == '\n') + return c; #ifdef HANDLE_SYSV_PRAGMA - return handle_sysv_pragma (finput, c); + UNGETC (c); + token = yylex (); + if (token != IDENTIFIER) + goto skipline; + return handle_sysv_pragma (token); #else /* !HANDLE_SYSV_PRAGMA */ #ifdef HANDLE_PRAGMA - HANDLE_PRAGMA (finput); +#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; + } +#else + ??? do not know what to do ???; +#endif /* !USE_CPPLIB */ #endif /* HANDLE_PRAGMA */ - goto skipline; #endif /* !HANDLE_SYSV_PRAGMA */ + goto skipline; } } else if (c == 'd') { - if (getc (finput) == 'e' - && getc (finput) == 'f' - && getc (finput) == 'i' - && getc (finput) == 'n' - && getc (finput) == 'e' - && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n')) + if (GETC() == 'e' + && GETC() == 'f' + && GETC() == 'i' + && GETC() == 'n' + && GETC() == 'e' + && ((c = GETC()) == ' ' || c == '\t' || c == '\n')) { -#ifdef DWARF_DEBUGGING_INFO - if ((debug_info_level == DINFO_LEVEL_VERBOSE) - && (write_symbols == DWARF_DEBUG)) - dwarfout_define (lineno, get_directive_line (finput)); -#endif /* DWARF_DEBUGGING_INFO */ + if (c != '\n') + debug_define (lineno, GET_DIRECTIVE_LINE ()); goto skipline; } } else if (c == 'u') { - if (getc (finput) == 'n' - && getc (finput) == 'd' - && getc (finput) == 'e' - && getc (finput) == 'f' - && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n')) + if (GETC() == 'n' + && GETC() == 'd' + && GETC() == 'e' + && GETC() == 'f' + && ((c = GETC()) == ' ' || c == '\t' || c == '\n')) { -#ifdef DWARF_DEBUGGING_INFO - if ((debug_info_level == DINFO_LEVEL_VERBOSE) - && (write_symbols == DWARF_DEBUG)) - dwarfout_undef (lineno, get_directive_line (finput)); -#endif /* DWARF_DEBUGGING_INFO */ + if (c != '\n') + debug_undef (lineno, GET_DIRECTIVE_LINE ()); goto skipline; } } else if (c == 'l') { - if (getc (finput) == 'i' - && getc (finput) == 'n' - && getc (finput) == 'e' - && ((c = getc (finput)) == ' ' || c == '\t')) + if (GETC() == 'i' + && GETC() == 'n' + && GETC() == 'e' + && ((c = GETC()) == ' ' || c == '\t')) goto linenum; } else if (c == 'i') { - if (getc (finput) == 'd' - && getc (finput) == 'e' - && getc (finput) == 'n' - && getc (finput) == 't' - && ((c = getc (finput)) == ' ' || c == '\t')) + if (GETC() == 'd' + && GETC() == 'e' + && GETC() == 'n' + && GETC() == 't' + && ((c = GETC()) == ' ' || c == '\t')) { /* #ident. The pedantic warning is now in cccp.c. */ /* Here we have just seen `#ident '. A string constant should follow. */ - while (c == ' ' || c == '\t') - c = getc (finput); + c = skip_white_space_on_line (); /* If no argument, ignore the line. */ if (c == '\n') return c; - ungetc (c, finput); + UNGETC (c); token = yylex (); if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) @@ -499,8 +646,11 @@ linenum: /* Here we have either `#line' or `# '. In either case, it should be a line number; a digit should follow. */ - while (c == ' ' || c == '\t') - c = getc (finput); + /* Can't use skip_white_space here, but must handle all whitespace + that is not '\n', lest we get a recursion for '\r' '\n' when + calling yylex. */ + UNGETC (c); + c = skip_white_space_on_line (); /* If the # is the only nonwhite char on the line, just ignore it. Check the new newline. */ @@ -509,7 +659,7 @@ linenum: /* Something follows the #; read a token. */ - ungetc (c, finput); + UNGETC (c); token = yylex (); if (token == CONSTANT @@ -523,16 +673,14 @@ linenum: int l = TREE_INT_CST_LOW (yylval.ttype) - 1; /* Is this the last nonwhite stuff on the line? */ - c = getc (finput); - while (c == ' ' || c == '\t') - c = getc (finput); + c = skip_white_space_on_line (); if (c == '\n') { /* No more: store the line number and check following line. */ lineno = l; return c; } - ungetc (c, finput); + UNGETC (c); /* More follows: it must be a string constant (filename). */ @@ -558,9 +706,7 @@ linenum: main_input_filename = input_filename; /* Is this the last nonwhite stuff on the line? */ - c = getc (finput); - while (c == ' ' || c == '\t') - c = getc (finput); + c = skip_white_space_on_line (); if (c == '\n') { /* Update the name in the top element of input_file_stack. */ @@ -569,7 +715,7 @@ linenum: return c; } - ungetc (c, finput); + UNGETC (c); token = yylex (); used_up = 0; @@ -588,14 +734,10 @@ linenum: input_file_stack->line = old_lineno; p->next = input_file_stack; p->name = input_filename; + p->indent_level = indent_level; input_file_stack = p; input_file_stack_tick++; -#ifdef DWARF_DEBUGGING_INFO - if (debug_info_level == DINFO_LEVEL_VERBOSE - && write_symbols == DWARF_DEBUG) - dwarfout_start_new_source_file (input_filename); -#endif /* DWARF_DEBUGGING_INFO */ - + debug_start_source_file (input_filename); used_up = 1; } else if (TREE_INT_CST_LOW (yylval.ttype) == 2) @@ -604,14 +746,18 @@ linenum: if (input_file_stack->next) { struct file_stack *p = input_file_stack; + if (indent_level != p->indent_level) + { + warning_with_file_and_line + (p->name, old_lineno, + "This file contains more `%c's than `%c's.", + indent_level > p->indent_level ? '{' : '}', + indent_level > p->indent_level ? '}' : '{'); + } input_file_stack = p->next; free (p); input_file_stack_tick++; -#ifdef DWARF_DEBUGGING_INFO - if (debug_info_level == DINFO_LEVEL_VERBOSE - && write_symbols == DWARF_DEBUG) - dwarfout_resume_previous_source_file (input_file_stack->line); -#endif /* DWARF_DEBUGGING_INFO */ + debug_end_source_file (input_file_stack->line); } else error ("#-lines for entering and leaving files don't match"); @@ -630,12 +776,10 @@ linenum: if (used_up) { /* Is this the last nonwhite stuff on the line? */ - c = getc (finput); - while (c == ' ' || c == '\t') - c = getc (finput); + c = skip_white_space_on_line (); if (c == '\n') return c; - ungetc (c, finput); + UNGETC (c); token = yylex (); used_up = 0; @@ -651,12 +795,10 @@ linenum: if (used_up) { /* Is this the last nonwhite stuff on the line? */ - c = getc (finput); - while (c == ' ' || c == '\t') - c = getc (finput); + c = skip_white_space_on_line (); if (c == '\n') return c; - ungetc (c, finput); + UNGETC (c); } warning ("unrecognized text at end of #line"); @@ -666,37 +808,33 @@ linenum: /* skip the rest of this line. */ skipline: - if (c == '\n') - return c; - while ((c = getc (finput)) != EOF && c != '\n'); +#if !USE_CPPLIB + if (c != '\n' && c != EOF && nextchar >= 0) + c = nextchar, nextchar = -1; +#endif + while (c != '\n' && c != EOF) + c = GETC(); return c; } #ifdef HANDLE_SYSV_PRAGMA -/* 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 token we read after `#pragma'. Processes the entire input + line and returns a character for the caller to reread: either \n or EOF. */ /* This function has to be in this file, in order to get at the token types. */ -int -handle_sysv_pragma (input, c) - FILE *input; - int c; +static int +handle_sysv_pragma (token) + register int token; { + register int c; + for (;;) { - while (c == ' ' || c == '\t') - c = getc (input); - if (c == '\n' || c == EOF) - { - handle_pragma_token (0, 0); - return c; - } - ungetc (c, input); - switch (yylex ()) + switch (token) { case IDENTIFIER: case TYPENAME: @@ -707,10 +845,22 @@ handle_sysv_pragma (input, c) default: handle_pragma_token (token_buffer, 0); } +#if !USE_CPPLIB if (nextchar >= 0) c = nextchar, nextchar = -1; else - c = getc (input); +#endif + c = GETC (); + + while (c == ' ' || c == '\t') + c = GETC (); + if (c == '\n' || c == EOF) + { + handle_pragma_token (0, 0); + return c; + } + UNGETC (c); + token = yylex (); } } @@ -725,7 +875,7 @@ static int readescape (ignore_ptr) int *ignore_ptr; { - register int c = getc (finput); + register int c = GETC(); register int code; register unsigned count; unsigned firstdig = 0; @@ -745,12 +895,12 @@ readescape (ignore_ptr) nonnull = 0; while (1) { - c = getc (finput); + c = GETC(); if (!(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F') && !(c >= '0' && c <= '9')) { - ungetc (c, finput); + UNGETC (c); break; } code *= 16; @@ -787,9 +937,9 @@ readescape (ignore_ptr) while ((c <= '7') && (c >= '0') && (count++ < 3)) { code = (code * 8) + (c - '0'); - c = getc (finput); + c = GETC(); } - ungetc (c, finput); + UNGETC (c); return code; case '\\': case '\'': case '"': @@ -913,10 +1063,12 @@ yylex () int wide_flag = 0; int objc_flag = 0; +#if !USE_CPPLIB if (nextchar >= 0) c = nextchar, nextchar = -1; else - c = getc (finput); +#endif + c = GETC(); /* Effectively do c = skip_white_space (c) but do it faster in the usual cases. */ @@ -928,7 +1080,7 @@ yylex () case '\f': case '\v': case '\b': - c = getc (finput); + c = GETC(); break; case '\r': @@ -956,15 +1108,10 @@ yylex () value = ENDFILE; break; - case '$': - if (dollars_in_ident) - goto letter; - return '$'; - case 'L': /* Capital L may start a wide-string or wide-character constant. */ { - register int c = getc (finput); + register int c = GETC(); if (c == '\'') { wide_flag = 1; @@ -975,7 +1122,7 @@ yylex () wide_flag = 1; goto string_constant; } - ungetc (c, finput); + UNGETC (c); } goto letter; @@ -988,13 +1135,13 @@ yylex () else { /* '@' may start a constant string object. */ - register int c = getc(finput); + register int c = GETC (); if (c == '"') { objc_flag = 1; goto string_constant; } - ungetc(c, finput); + UNGETC (c); /* Fall through to treat '@' as the start of an identifier. */ } @@ -1011,25 +1158,35 @@ yylex () case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '_': + case '$': letter: p = token_buffer; - while (isalnum (c) || c == '_' || c == '$' || c == '@') + while (ISALNUM (c) || c == '_' || c == '$' || c == '@') { /* Make sure this char really belongs in an identifier. */ if (c == '@' && ! doing_objc_thang) break; - if (c == '$' && ! dollars_in_ident) - break; + if (c == '$') + { + if (! dollars_in_ident) + error ("`$' in identifier"); + else if (pedantic) + pedwarn ("`$' in identifier"); + } if (p >= token_buffer + maxtoken) p = extend_token_buffer (p); *p++ = c; - c = getc (finput); + c = GETC(); } *p = 0; +#if USE_CPPLIB + UNGETC (c); +#else nextchar = c; +#endif value = IDENTIFIER; yylval.itype = 0; @@ -1039,7 +1196,7 @@ yylex () { register struct resword *ptr; - if (ptr = is_reserved_word (token_buffer, p - token_buffer)) + if ((ptr = is_reserved_word (token_buffer, p - token_buffer))) { if (ptr->rid) yylval.ttype = ridpointers[(int) ptr->rid]; @@ -1109,7 +1266,23 @@ yylex () break; - case '0': case '1': case '2': case '3': case '4': + case '0': case '1': + { + int next_c; + /* Check first for common special case: single-digit 0 or 1. */ + + next_c = GETC (); + UNGETC (next_c); /* Always undo this lookahead. */ + if (!ISALNUM (next_c) && next_c != '.') + { + token_buffer[0] = (char)c, token_buffer[1] = '\0'; + yylval.ttype = (c == '0') ? integer_zero_node : integer_one_node; + value = CONSTANT; + break; + } + /*FALLTHRU*/ + } + case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': { @@ -1138,11 +1311,11 @@ yylex () if (c == '0') { - *p++ = (c = getc (finput)); + *p++ = (c = GETC()); if ((c == 'x') || (c == 'X')) { base = 16; - *p++ = (c = getc (finput)); + *p++ = (c = GETC()); } /* Leading 0 forces octal unless the 0 is the only digit. */ else if (c >= '0' && c <= '9') @@ -1157,7 +1330,7 @@ yylex () /* Read all the digits-and-decimal-points. */ while (c == '.' - || (isalnum (c) && c != 'l' && c != 'L' + || (ISALNUM (c) && c != 'l' && c != 'L' && c != 'u' && c != 'U' && c != 'i' && c != 'I' && c != 'j' && c != 'J' && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F'))))) @@ -1181,16 +1354,16 @@ yylex () floatflag = AFTER_POINT; base = 10; - *p++ = c = getc (finput); + *p++ = c = GETC(); /* Accept '.' as the start of a floating-point number only when it is followed by a digit. Otherwise, unread the following non-digit and use the '.' as a structural token. */ - if (p == token_buffer + 2 && !isdigit (c)) + if (p == token_buffer + 2 && !ISDIGIT (c)) { if (c == '.') { - c = getc (finput); + c = GETC(); if (c == '.') { *p++ = c; @@ -1199,7 +1372,7 @@ yylex () } error ("parse error at `..'"); } - ungetc (c, finput); + UNGETC (c); token_buffer[1] = 0; value = '.'; goto done; @@ -1210,7 +1383,7 @@ yylex () /* It is not a decimal point. It should be a digit (perhaps a hex digit). */ - if (isdigit (c)) + if (ISDIGIT (c)) { c = c - '0'; } @@ -1258,7 +1431,7 @@ yylex () if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); - *p++ = (c = getc (finput)); + *p++ = (c = GETC()); } } @@ -1274,8 +1447,8 @@ yylex () if (floatflag != NOT_FLOAT) { tree type = double_type_node; - int garbage_chars = 0, exceeds_double = 0; int imag = 0; + int conversion_errno = 0; REAL_VALUE_TYPE value; jmp_buf handler; @@ -1286,25 +1459,24 @@ yylex () if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; - c = getc (finput); + c = GETC(); if ((c == '+') || (c == '-')) { *p++ = c; - c = getc (finput); + c = GETC(); } - if (! isdigit (c)) + 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); *p++ = c; - c = getc (finput); + c = GETC(); } } *p = 0; - errno = 0; /* Convert string to a double, checking for overflow. */ if (setjmp (handler)) @@ -1361,7 +1533,7 @@ yylex () p = extend_token_buffer (p); *p++ = c; *p = 0; - c = getc (finput); + c = GETC(); } /* The second argument, machine_mode, of REAL_VALUE_ATOF @@ -1374,7 +1546,9 @@ yylex () 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. */ @@ -1384,13 +1558,17 @@ yylex () 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'"); } @@ -1398,31 +1576,13 @@ yylex () set_float_handler (NULL_PTR); } #ifdef ERANGE - if (errno == ERANGE && !flag_traditional && pedantic) - { - /* ERANGE is also reported for underflow, - so test the value to distinguish overflow from that. */ - if (REAL_VALUES_LESS (dconst1, value) - || REAL_VALUES_LESS (value, dconstm1)) - { - warning ("floating point number exceeds range of `double'"); - exceeds_double = 1; - } - } + /* ERANGE is also reported for underflow, + so test the value to distinguish overflow from that. */ + if (conversion_errno == ERANGE && !flag_traditional && pedantic + && (REAL_VALUES_LESS (dconst1, value) + || REAL_VALUES_LESS (value, dconstm1))) + warning ("floating point number exceeds range of `double'"); #endif - garbage_chars = 0; - while (isalnum (c) || c == '.' || c == '_' - || (!flag_traditional && (c == '+' || c == '-') - && (p[-1] == 'e' || p[-1] == 'E'))) - { - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getc (finput); - garbage_chars++; - } - if (garbage_chars > 0) - error ("garbage at end of number"); /* If the result is not a number, assume it must have been due to some error message above, so silently convert @@ -1432,13 +1592,11 @@ yylex () /* Create a node with determined type and value. */ if (imag) - yylval.ttype = build_complex (convert (type, integer_zero_node), + yylval.ttype = build_complex (NULL_TREE, + convert (type, integer_zero_node), build_real (type, value)); else yylval.ttype = build_real (type, value); - - ungetc (c, finput); - *p = 0; } else { @@ -1450,6 +1608,7 @@ yylex () int spec_imag = 0; int bytes, warn, i; + traditional_type = ansi_type = type = NULL_TREE; while (1) { if (c == 'u' || c == 'U') @@ -1479,46 +1638,22 @@ yylex () spec_imag = 1; } else - { - if (isalnum (c) || c == '.' || c == '_' - || (!flag_traditional && (c == '+' || c == '-') - && (p[-1] == 'e' || p[-1] == 'E'))) - { - error ("garbage at end of number"); - while (isalnum (c) || c == '.' || c == '_' - || (!flag_traditional && (c == '+' || c == '-') - && (p[-1] == 'e' || p[-1] == 'E'))) - { - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getc (finput); - } - } - break; - } + break; if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; - c = getc (finput); + c = GETC(); } - ungetc (c, finput); - - /* If the constant is not long long and it won't fit in an - unsigned long, or if the constant is long long and won't fit - in an unsigned long long, then warn that the constant is out - of range. */ + /* 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. */ - if (spec_long_long) - bytes = TYPE_PRECISION (long_long_integer_type_node) / 8; - else - bytes = TYPE_PRECISION (long_integer_type_node) / 8; + bytes = TYPE_PRECISION (long_long_integer_type_node) / 8; warn = overflow; for (i = bytes; i < TOTAL_PARTS; i++) @@ -1585,11 +1720,11 @@ yylex () else if (! spec_unsigned && !spec_long_long && int_fits_type_p (yylval.ttype, long_integer_type_node)) ansi_type = long_integer_type_node; - else if (! spec_long_long) + else if (! spec_long_long + && int_fits_type_p (yylval.ttype, + long_unsigned_type_node)) ansi_type = long_unsigned_type_node; else if (! spec_unsigned - /* Verify value does not overflow into sign bit. */ - && TREE_INT_CST_HIGH (yylval.ttype) >= 0 && int_fits_type_p (yylval.ttype, long_long_integer_type_node)) ansi_type = long_long_integer_type_node; @@ -1611,8 +1746,9 @@ yylex () warning ("width of integer constant may change on other systems with -traditional"); } - if (!flag_traditional && !int_fits_type_p (yylval.ttype, type) - && !warn) + if (pedantic && !flag_traditional && !spec_long_long && !warn + && (TYPE_PRECISION (long_integer_type_node) + < TYPE_PRECISION (type))) pedwarn ("integer constant out of range"); if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) @@ -1623,8 +1759,9 @@ yylex () if (TYPE_PRECISION (type) <= TYPE_PRECISION (integer_type_node)) yylval.ttype - = build_complex (integer_zero_node, - convert (integer_type_node, yylval.ttype)); + = build_complex (NULL_TREE, integer_zero_node, + convert (integer_type_node, + yylval.ttype)); else error ("complex integer constant is too wide for `complex int'"); } @@ -1640,10 +1777,16 @@ yylex () } else TREE_TYPE (yylval.ttype) = type; - - *p = 0; } + UNGETC (c); + *p = 0; + + if (ISALNUM (c) || c == '.' || c == '_' || c == '$' + || (!flag_traditional && (c == '-' || c == '+') + && (p[-1] == 'e' || p[-1] == 'E'))) + error ("missing white space after number `%s'", token_buffer); + value = CONSTANT; break; } @@ -1671,7 +1814,7 @@ yylex () { tryagain: - c = getc (finput); + c = GETC(); if (c == '\'' || c == EOF) break; @@ -1686,7 +1829,7 @@ yylex () && (unsigned) c >= (1 << width)) pedwarn ("escape sequence out of range for character"); #ifdef MAP_CHARACTER - if (isprint (c)) + if (ISPRINT (c)) c = MAP_CHARACTER (c); #endif } @@ -1729,7 +1872,7 @@ yylex () num_chars = max_chars; error ("character constant too long"); } - else if (num_chars != 1 && ! flag_traditional) + else if (num_chars != 1 && ! flag_traditional && warn_multichar) warning ("multi-character character constant"); /* If char type is signed, sign-extend the constant. */ @@ -1742,12 +1885,12 @@ 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); TREE_TYPE (yylval.ttype) = integer_type_node; @@ -1781,7 +1924,7 @@ yylex () case '"': string_constant: { - c = getc (finput); + c = GETC(); p = token_buffer + 1; while (c != '"' && c >= 0) @@ -1809,7 +1952,7 @@ yylex () *p++ = c; skipnewline: - c = getc (finput); + c = GETC(); } *p = 0; @@ -1836,15 +1979,9 @@ yylex () bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES); #else { - union { long l; char c[sizeof (long)]; } u; - int big_endian; char *wp, *cp; - /* Determine whether host is little or big endian. */ - u.l = 1; - big_endian = u.c[sizeof (long) - 1]; - wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0); - + 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; @@ -1857,7 +1994,6 @@ yylex () } else if (objc_flag) { - extern tree build_objc_string(); /* Return an Objective-C @"..." constant string object. */ yylval.ttype = build_objc_string (p - token_buffer, token_buffer + 1); @@ -1923,7 +2059,7 @@ yylex () yylval.code = GT_EXPR; break; } - token_buffer[1] = c1 = getc (finput); + token_buffer[1] = c1 = GETC(); token_buffer[2] = 0; if (c1 == '=') @@ -1972,16 +2108,16 @@ yylex () break; case '<': if (c1 == '%') - { value = '{'; goto done; } + { value = '{'; indent_level++; goto done; } if (c1 == ':') { value = '['; goto done; } break; case '%': if (c1 == '>') - { value = '}'; goto done; } + { value = '}'; indent_level--; goto done; } break; } - ungetc (c1, finput); + UNGETC (c1); token_buffer[1] = 0; if ((c == '<') || (c == '>')) @@ -1995,6 +2131,16 @@ yylex () value = 1; break; + case '{': + indent_level++; + value = c; + break; + + case '}': + indent_level--; + value = c; + break; + default: value = c; } diff --git a/contrib/gcc/c-lex.h b/contrib/gcc/c-lex.h index c1aed08..bd0b9d4 100644 --- a/contrib/gcc/c-lex.h +++ b/contrib/gcc/c-lex.h @@ -73,8 +73,14 @@ extern tree lastiddecl; extern char *token_buffer; /* Pointer to token buffer. */ -extern tree make_pointer_declarator (); -extern void reinit_parse_for_function (); -extern int yylex (); +extern tree make_pointer_declarator PROTO((tree, tree)); +extern void reinit_parse_for_function PROTO((void)); +extern void position_after_white_space PROTO((void)); +extern int check_newline PROTO((void)); -extern char *get_directive_line (); +extern int yylex PROTO((void)); +extern void yyerror PROTO((char *)); + +extern void forget_protocol_qualifiers PROTO((void)); +extern void remember_protocol_qualifiers PROTO((void)); +extern tree is_class_name PROTO((tree)); diff --git a/contrib/gcc/c-parse.in b/contrib/gcc/c-parse.in index 044e452..16500c5 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, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -28,10 +28,10 @@ Boston, MA 02111-1307, USA. */ written by AT&T, but I have never seen it. */ ifobjc -%expect 48 +%expect 66 end ifobjc ifc -%expect 34 +%expect 46 /* These are the 23 conflicts you should get in parse.output; the state numbers may vary if minor changes in the grammar are made. @@ -58,19 +58,19 @@ State 434 contains 2 shift/reduce conflicts. (Four ways to parse this.) */ end ifc %{ -#include -#include +#include "config.h" +#include "system.h" #include -#include "config.h" #include "tree.h" #include "input.h" #include "c-lex.h" #include "c-tree.h" #include "flags.h" +#include "output.h" +#include "toplev.h" #ifdef MULTIBYTE_CHARS -#include #include #endif @@ -87,12 +87,6 @@ ifc char *language_string = "GNU C"; end ifc -#ifndef errno -extern int errno; -#endif - -void yyerror (); - /* Like YYERROR but do call yyerror. */ #define YYERROR1 { yyerror ("syntax error"); YYERROR; } @@ -185,6 +179,8 @@ void yyerror (); %type typed_declspecs reserved_declspecs %type typed_typespecs reserved_typespecquals %type declmods typespec typespecqual_reserved +%type typed_declspecs_no_prefix_attr reserved_declspecs_no_prefix_attr +%type declmods_no_prefix_attr %type SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual %type initdecls notype_initdecls initdcl notype_initdcl %type init maybeasm @@ -201,6 +197,7 @@ void yyerror (); %type structsp component_decl_list component_decl_list2 %type component_decl components component_declarator %type enumlist enumerator +%type struct_head union_head enum_head %type typename absdcl absdcl1 type_quals %type xexpr parms parm identifiers @@ -224,21 +221,24 @@ ifobjc %type keywordexpr keywordarglist keywordarg %type myparms myparm optparmlist reservedwords objcselectorexpr %type selectorarg keywordnamelist keywordname objcencodeexpr -%type objc_string protocolrefs identifier_list objcprotocolexpr +%type objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr + %type CLASSNAME OBJC_STRING OBJECTNAME end ifobjc %{ -/* Number of statements (loosely speaking) seen so far. */ +/* Number of statements (loosely speaking) and compound statements + seen so far. */ static int stmt_count; - +static int compstmt_count; + /* Input file and line number of the end of the body of last simple_if; used by the stmt-rule immediately after simple_if returns. */ static char *if_stmt_file; static int if_stmt_line; /* List of types and structure classes of the current declaration. */ -static tree current_declspecs; +static tree current_declspecs = NULL_TREE; static tree prefix_attributes = NULL_TREE; /* Stack of saved values of current_declspecs and prefix_attributes. */ @@ -264,7 +264,7 @@ end ifobjc /* Tell yyparse how to print a token's value, if yydebug is set. */ #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL) -extern void yyprint (); +extern void yyprint PROTO ((FILE *, int, YYSTYPE)); %} %% @@ -306,6 +306,8 @@ end ifobjc assemble_asm ($3); else error ("argument of `asm' is not a constant string"); } + | extension extdef + { pedantic = $1; } ; datadef: @@ -342,11 +344,11 @@ datadef: fndef: typed_declspecs setspecs declarator - { if (! start_function ($1, $3, prefix_attributes, - NULL_TREE, 0)) + { if (! start_function (current_declspecs, $3, + prefix_attributes, NULL_TREE, 0)) YYERROR1; reinit_parse_for_function (); } - xdecls + old_style_parm_decls { store_parm_decls (); } compstmt_or_error { finish_function (0); @@ -360,11 +362,11 @@ fndef: declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_declarator - { if (! start_function ($1, $3, prefix_attributes, - NULL_TREE, 0)) + { if (! start_function (current_declspecs, $3, + prefix_attributes, NULL_TREE, 0)) YYERROR1; reinit_parse_for_function (); } - xdecls + old_style_parm_decls { store_parm_decls (); } compstmt_or_error { finish_function (0); @@ -382,7 +384,7 @@ fndef: prefix_attributes, NULL_TREE, 0)) YYERROR1; reinit_parse_for_function (); } - xdecls + old_style_parm_decls { store_parm_decls (); } compstmt_or_error { finish_function (0); @@ -444,11 +446,8 @@ unary_expr: | '*' cast_expr %prec UNARY { $$ = build_indirect_ref ($2, "unary *"); } /* __extension__ turns off -pedantic for following primary. */ - | EXTENSION - { $1 = pedantic; - pedantic = 0; } - cast_expr %prec UNARY - { $$ = $3; + | extension cast_expr %prec UNARY + { $$ = $2; pedantic = $1; } | unop cast_expr %prec UNARY { $$ = build_unary_op ($1, $2, 0); @@ -482,23 +481,35 @@ unary_expr: $$ = build_unary_op (ADDR_EXPR, $$, 0); } } */ - | SIZEOF unary_expr %prec UNARY - { if (TREE_CODE ($2) == COMPONENT_REF - && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) + | sizeof unary_expr %prec UNARY + { skip_evaluation--; + if (TREE_CODE ($2) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1))) error ("`sizeof' applied to a bit-field"); $$ = c_sizeof (TREE_TYPE ($2)); } - | SIZEOF '(' typename ')' %prec HYPERUNARY - { $$ = c_sizeof (groktypename ($3)); } - | ALIGNOF unary_expr %prec UNARY - { $$ = c_alignof_expr ($2); } - | ALIGNOF '(' typename ')' %prec HYPERUNARY - { $$ = c_alignof (groktypename ($3)); } + | sizeof '(' typename ')' %prec HYPERUNARY + { skip_evaluation--; + $$ = c_sizeof (groktypename ($3)); } + | alignof unary_expr %prec UNARY + { skip_evaluation--; + $$ = c_alignof_expr ($2); } + | alignof '(' typename ')' %prec HYPERUNARY + { skip_evaluation--; + $$ = c_alignof (groktypename ($3)); } | REALPART cast_expr %prec UNARY { $$ = build_unary_op (REALPART_EXPR, $2, 0); } | IMAGPART cast_expr %prec UNARY { $$ = build_unary_op (IMAGPART_EXPR, $2, 0); } ; +sizeof: + SIZEOF { skip_evaluation++; } + ; + +alignof: + ALIGNOF { skip_evaluation++; } + ; + cast_expr: unary_expr | '(' typename ')' cast_expr %prec UNARY @@ -561,12 +572,37 @@ expr_no_commas: { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '^' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } - | expr_no_commas ANDAND expr_no_commas - { $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); } - | expr_no_commas OROR expr_no_commas - { $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $3); } - | expr_no_commas '?' xexpr ':' expr_no_commas - { $$ = build_conditional_expr ($1, $3, $5); } + | expr_no_commas ANDAND + { $1 = truthvalue_conversion (default_conversion ($1)); + skip_evaluation += $1 == boolean_false_node; } + expr_no_commas + { skip_evaluation -= $1 == boolean_false_node; + $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); } + | expr_no_commas OROR + { $1 = truthvalue_conversion (default_conversion ($1)); + skip_evaluation += $1 == boolean_true_node; } + expr_no_commas + { skip_evaluation -= $1 == boolean_true_node; + $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); } + | expr_no_commas '?' + { $1 = truthvalue_conversion (default_conversion ($1)); + skip_evaluation += $1 == boolean_false_node; } + expr ':' + { skip_evaluation += (($1 == boolean_true_node) + - ($1 == boolean_false_node)); } + expr_no_commas + { skip_evaluation -= $1 == boolean_true_node; + $$ = build_conditional_expr ($1, $4, $7); } + | expr_no_commas '?' + { if (pedantic) + pedwarn ("ANSI C forbids omitting the middle term of a ?: expression"); + /* Make sure first operand is calculated only once. */ + $2 = save_expr ($1); + $1 = truthvalue_conversion (default_conversion ($2)); + skip_evaluation += $1 == boolean_true_node; } + ':' expr_no_commas + { skip_evaluation -= $1 == boolean_true_node; + $$ = build_conditional_expr ($1, $2, $5); } | expr_no_commas '=' expr_no_commas { $$ = build_modify_expr ($1, NOP_EXPR, $3); C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } @@ -640,7 +676,7 @@ end ifobjc if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl) { - error ("`%s' undeclared (first use this function)", + error ("`%s' undeclared (first use in this function)", IDENTIFIER_POINTER ($1)); if (! undeclared_variable_notice) @@ -861,7 +897,7 @@ objc_string: ; end ifobjc -xdecls: +old_style_parm_decls: /* empty */ | datadecls | datadecls ELLIPSIS @@ -886,21 +922,25 @@ datadecls: | lineno_datadecl errstmt ; +/* We don't allow prefix attributes here because they cause reduce/reduce + conflicts: we can't know whether we're parsing a function decl with + attribute suffix, or function defn with attribute prefix on first old + style parm. */ datadecl: - typed_declspecs setspecs initdecls ';' + typed_declspecs_no_prefix_attr setspecs initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } - | declmods setspecs notype_initdecls ';' + | declmods_no_prefix_attr setspecs notype_initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } - | typed_declspecs ';' + | typed_declspecs_no_prefix_attr ';' { shadow_tag_warned ($1, 1); pedwarn ("empty declaration"); } - | declmods ';' + | declmods_no_prefix_attr ';' { pedwarn ("empty declaration"); } ; @@ -930,10 +970,11 @@ setspecs: /* empty */ declspec_stack = tree_cons (prefix_attributes, current_declspecs, declspec_stack); - current_declspecs = $0; - prefix_attributes = NULL_TREE; } + split_specs_attrs ($0, + ¤t_declspecs, &prefix_attributes); } ; +/* ??? Yuck. See after_type_declarator. */ setattrs: /* empty */ { prefix_attributes = chainon (prefix_attributes, $0); } ; @@ -963,11 +1004,14 @@ decl: { shadow_tag ($1); } | declmods ';' { pedwarn ("empty declaration"); } + | extension decl + { pedantic = $1; } ; /* Declspecs which contain at least one type specifier or typedef name. (Just `const' or `volatile' is not enough.) - A typedef'd name following these is taken as a name to be declared. */ + A typedef'd name following these is taken as a name to be declared. + Declspecs have a non-NULL TREE_VALUE, attributes do not. */ typed_declspecs: typespec reserved_declspecs @@ -985,22 +1029,55 @@ reserved_declspecs: /* empty */ warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = tree_cons (NULL_TREE, $2, $1); } + | reserved_declspecs attributes + { $$ = tree_cons ($2, NULL_TREE, $1); } + ; + +typed_declspecs_no_prefix_attr: + typespec reserved_declspecs_no_prefix_attr + { $$ = tree_cons (NULL_TREE, $1, $2); } + | declmods_no_prefix_attr typespec reserved_declspecs_no_prefix_attr + { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } + ; + +reserved_declspecs_no_prefix_attr: + /* empty */ + { $$ = NULL_TREE; } + | reserved_declspecs_no_prefix_attr typespecqual_reserved + { $$ = tree_cons (NULL_TREE, $2, $1); } + | reserved_declspecs_no_prefix_attr SCSPEC + { if (extra_warnings) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER ($2)); + $$ = tree_cons (NULL_TREE, $2, $1); } ; -/* List of just storage classes and type modifiers. +/* List of just storage classes, type modifiers, and prefix attributes. A declaration can start with just this, but then it cannot be used - to redeclare a typedef-name. */ + to redeclare a typedef-name. + Declspecs have a non-NULL TREE_VALUE, attributes do not. */ declmods: + declmods_no_prefix_attr + { $$ = $1; } + | attributes + { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); } + | declmods declmods_no_prefix_attr + { $$ = chainon ($2, $1); } + | declmods attributes + { $$ = tree_cons ($2, NULL_TREE, $1); } + ; + +declmods_no_prefix_attr: TYPE_QUAL { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); TREE_STATIC ($$) = 1; } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } - | declmods TYPE_QUAL + | declmods_no_prefix_attr TYPE_QUAL { $$ = tree_cons (NULL_TREE, $2, $1); TREE_STATIC ($$) = 1; } - | declmods SCSPEC + | declmods_no_prefix_attr SCSPEC { if (extra_warnings && TREE_STATIC ($1)) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); @@ -1041,6 +1118,11 @@ ifobjc { $$ = get_static_reference ($1, $2); } | OBJECTNAME protocolrefs { $$ = get_object_reference ($2); } + +/* Make "" equivalent to "id " + - nisse@lysator.liu.se */ + | non_empty_protocolrefs + { $$ = get_object_reference ($1); } end ifobjc | TYPEOF '(' expr ')' { $$ = TREE_TYPE ($3); } @@ -1232,7 +1314,7 @@ nested_function: YYERROR1; } reinit_parse_for_function (); } - xdecls + old_style_parm_decls { store_parm_decls (); } /* This used to use compstmt_or_error. That caused a bug with input `f(g) int g {}', @@ -1255,7 +1337,7 @@ notype_nested_function: YYERROR1; } reinit_parse_for_function (); } - xdecls + old_style_parm_decls { store_parm_decls (); } /* This used to use compstmt_or_error. That caused a bug with input `f(g) int g {}', @@ -1292,6 +1374,11 @@ after_type_declarator: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } | '*' type_quals after_type_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } + /* ??? Yuck. setattrs is a quick hack. We can't use + prefix_attributes because $1 only applies to this + declarator. We assume setspecs has already been done. + setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple + attributes could be recognized here or in `attributes'). */ | attributes setattrs after_type_declarator { $$ = $3; } | TYPENAME @@ -1317,6 +1404,11 @@ parm_declarator: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } | '*' type_quals parm_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } + /* ??? Yuck. setattrs is a quick hack. We can't use + prefix_attributes because $1 only applies to this + declarator. We assume setspecs has already been done. + setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple + attributes could be recognized here or in `attributes'). */ | attributes setattrs parm_declarator { $$ = $3; } | TYPENAME @@ -1339,47 +1431,73 @@ notype_declarator: { $$ = build_nt (ARRAY_REF, $1, $3); } | notype_declarator '[' ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } + /* ??? Yuck. setattrs is a quick hack. We can't use + prefix_attributes because $1 only applies to this + declarator. We assume setspecs has already been done. + setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple + attributes could be recognized here or in `attributes'). */ | attributes setattrs notype_declarator { $$ = $3; } | IDENTIFIER ; +struct_head: + STRUCT + { $$ = NULL_TREE; } + | STRUCT attributes + { $$ = $2; } + ; + +union_head: + UNION + { $$ = NULL_TREE; } + | UNION attributes + { $$ = $2; } + ; + +enum_head: + ENUM + { $$ = NULL_TREE; } + | ENUM attributes + { $$ = $2; } + ; + structsp: - STRUCT identifier '{' + struct_head identifier '{' { $$ = start_struct (RECORD_TYPE, $2); /* Start scope of tag before parsing components. */ } component_decl_list '}' maybe_attribute - { $$ = finish_struct ($4, $5, $7); } - | STRUCT '{' component_decl_list '}' maybe_attribute + { $$ = finish_struct ($4, $5, chainon ($1, $7)); } + | struct_head '{' component_decl_list '}' maybe_attribute { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), - $3, $5); + $3, chainon ($1, $5)); } - | STRUCT identifier + | struct_head identifier { $$ = xref_tag (RECORD_TYPE, $2); } - | UNION identifier '{' + | union_head identifier '{' { $$ = start_struct (UNION_TYPE, $2); } component_decl_list '}' maybe_attribute - { $$ = finish_struct ($4, $5, $7); } - | UNION '{' component_decl_list '}' maybe_attribute + { $$ = finish_struct ($4, $5, chainon ($1, $7)); } + | union_head '{' component_decl_list '}' maybe_attribute { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE), - $3, $5); + $3, chainon ($1, $5)); } - | UNION identifier + | union_head identifier { $$ = xref_tag (UNION_TYPE, $2); } - | ENUM identifier '{' + | enum_head identifier '{' { $3 = suspend_momentary (); $$ = start_enum ($2); } enumlist maybecomma_warn '}' maybe_attribute - { $$ = finish_enum ($4, nreverse ($5), $8); + { $$= finish_enum ($4, nreverse ($5), chainon ($1, $8)); resume_momentary ($3); } - | ENUM '{' + | enum_head '{' { $2 = suspend_momentary (); $$ = start_enum (NULL_TREE); } enumlist maybecomma_warn '}' maybe_attribute - { $$ = finish_enum ($3, nreverse ($4), $7); + { $$= finish_enum ($3, nreverse ($4), chainon ($1, $7)); resume_momentary ($2); } - | ENUM identifier + | enum_head identifier { $$ = xref_tag (ENUMERAL_TYPE, $2); } ; @@ -1461,6 +1579,9 @@ component_decl: $$ = NULL_TREE; } | error { $$ = NULL_TREE; } + | extension component_decl + { $$ = $2; + pedantic = $1; } ; components: @@ -1553,8 +1674,8 @@ absdcl1: /* a nonempty absolute declarator */ { $$ = build_nt (ARRAY_REF, NULL_TREE, $2); } | '[' ']' %prec '.' { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); } - | attributes setattrs absdcl1 - { $$ = $3; } + /* ??? It appears we have to support attributes here, however + using prefix_attributes is wrong. */ ; /* at least one statement, the first of which parses without error. */ @@ -1632,9 +1753,11 @@ compstmt_or_error: | error compstmt ; -compstmt: '{' '}' +compstmt_start: '{' { compstmt_count++; } + +compstmt: compstmt_start '}' { $$ = convert (void_type_node, integer_zero_node); } - | '{' pushlevel maybe_label_decls decls xstmts '}' + | compstmt_start pushlevel maybe_label_decls decls xstmts '}' { emit_line_note (input_filename, lineno); expand_end_bindings (getdecls (), 1, 0); $$ = poplevel (1, 1, 0); @@ -1642,7 +1765,7 @@ compstmt: '{' '}' pop_momentary_nofree (); else pop_momentary (); } - | '{' pushlevel maybe_label_decls error '}' + | compstmt_start pushlevel maybe_label_decls error '}' { emit_line_note (input_filename, lineno); expand_end_bindings (getdecls (), kept_level_p (), 0); $$ = poplevel (kept_level_p (), 0, 0); @@ -1650,7 +1773,7 @@ compstmt: '{' '}' pop_momentary_nofree (); else pop_momentary (); } - | '{' pushlevel maybe_label_decls stmts '}' + | compstmt_start pushlevel maybe_label_decls stmts '}' { emit_line_note (input_filename, lineno); expand_end_bindings (getdecls (), kept_level_p (), 0); $$ = poplevel (kept_level_p (), 0, 0); @@ -1663,8 +1786,8 @@ compstmt: '{' '}' /* Value is number of statements counted as of the closeparen. */ simple_if: if_prefix lineno_labeled_stmt -/* Make sure expand_end_cond is run once - for each call to expand_start_cond. +/* Make sure c_expand_end_cond is run once + for each call to c_expand_start_cond. Otherwise a crash is likely. */ | if_prefix error ; @@ -1672,7 +1795,8 @@ simple_if: if_prefix: IF '(' expr ')' { emit_line_note ($-1, $0); - expand_start_cond (truthvalue_conversion ($3), 0); + c_expand_start_cond (truthvalue_conversion ($3), 0, + compstmt_count); $$ = stmt_count; if_stmt_file = $-1; if_stmt_line = $0; @@ -1685,6 +1809,7 @@ if_prefix: do_stmt_start: DO { stmt_count++; + compstmt_count++; emit_line_note ($-1, $0); /* See comment in `while' alternative, above. */ emit_nop (); @@ -1747,15 +1872,15 @@ stmt: iterator_expand ($1); clear_momentary (); } | simple_if ELSE - { expand_start_else (); + { c_expand_start_else (); $1 = stmt_count; position_after_white_space (); } lineno_labeled_stmt - { expand_end_cond (); + { c_expand_end_cond (); if (extra_warnings && stmt_count == $1) warning ("empty body in an else-statement"); } | simple_if %prec IF - { expand_end_cond (); + { c_expand_end_cond (); /* This warning is here instead of in simple_if, because we do not want a warning if an empty if is followed by an else statement. Increment stmt_count so we don't @@ -1763,11 +1888,11 @@ stmt: if (extra_warnings && stmt_count++ == $1) warning_with_file_and_line (if_stmt_file, if_stmt_line, "empty body in an if-statement"); } -/* Make sure expand_end_cond is run once - for each call to expand_start_cond. +/* Make sure c_expand_end_cond is run once + for each call to c_expand_start_cond. Otherwise a crash is likely. */ | simple_if ELSE error - { expand_end_cond (); } + { c_expand_end_cond (); } | WHILE { stmt_count++; emit_line_note ($-1, $0); @@ -1919,7 +2044,9 @@ stmt: } } | GOTO '*' expr ';' - { stmt_count++; + { if (pedantic) + pedwarn ("ANSI C forbids `goto *expr;'"); + stmt_count++; emit_line_note ($-1, $0); expand_computed_goto (convert (ptr_type_node, $3)); } | ';' @@ -1997,8 +2124,14 @@ label: CASE expr_no_commas ':' if (value != error_mark_node) { tree duplicate; - int success = pushcase (value, convert_and_check, - label, &duplicate); + int success; + + if (pedantic && ! INTEGRAL_TYPE_P (TREE_TYPE (value))) + pedwarn ("label must have integral type in ANSI C"); + + success = pushcase (value, convert_and_check, + label, &duplicate); + if (success == 1) error ("case label not within a switch statement"); else if (success == 2) @@ -2018,6 +2151,8 @@ label: CASE expr_no_commas ':' register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + if (pedantic) + pedwarn ("ANSI C forbids case ranges"); stmt_count++; if (value1 != error_mark_node && value2 != error_mark_node) @@ -2250,6 +2385,12 @@ identifiers_or_typenames: | identifiers_or_typenames ',' identifier { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } ; + +extension: + EXTENSION + { $$ = pedantic; + pedantic = 0; } + ; ifobjc /* Objective-C productions. */ @@ -2436,7 +2577,11 @@ protocolrefs: { $$ = NULL_TREE; } - | ARITHCOMPARE identifier_list ARITHCOMPARE + | non_empty_protocolrefs + ; + +non_empty_protocolrefs: + ARITHCOMPARE identifier_list ARITHCOMPARE { if ($1 == LT_EXPR && $3 == GT_EXPR) $$ = $2; @@ -2602,20 +2747,28 @@ semi_or_error: methodproto: '+' { + /* Remember protocol qualifiers in prototypes. */ + remember_protocol_qualifiers (); objc_inherit_code = CLASS_METHOD_DECL; } methoddecl { + /* Forget protocol qualifiers here. */ + forget_protocol_qualifiers (); add_class_method (objc_interface_context, $3); } semi_or_error | '-' { + /* Remember protocol qualifiers in prototypes. */ + remember_protocol_qualifiers (); objc_inherit_code = INSTANCE_METHOD_DECL; } methoddecl { + /* Forget protocol qualifiers here. */ + forget_protocol_qualifiers (); add_instance_method (objc_interface_context, $3); } semi_or_error diff --git a/contrib/gcc/c-pragma.c b/contrib/gcc/c-pragma.c index 480cfca..3d01925 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 Free Software Foundation, Inc. + Copyright (C) 1992, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -18,18 +18,22 @@ 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 #include "config.h" +#include "system.h" +#include "rtl.h" #include "tree.h" +#include "except.h" #include "function.h" #include "defaults.h" #include "c-pragma.h" +#include "flags.h" +#include "toplev.h" #ifdef HANDLE_SYSV_PRAGMA /* 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. */ + in effect, this is zero. */ extern int maximum_field_alignment; @@ -64,7 +68,7 @@ handle_pragma_token (string, token) if (HANDLE_PRAGMA_WEAK) handle_pragma_weak (state, name, value); -#endif /* HANDLE_PRAMA_WEAK */ +#endif /* HANDLE_PRAGMA_WEAK */ } type = state = ps_start; @@ -81,7 +85,16 @@ handle_pragma_token (string, token) else if (strcmp (IDENTIFIER_POINTER (token), "weak") == 0) type = state = ps_weak; else - type = state = ps_done; + { + 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); + } } else type = state = ps_done; diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h index 02f57c3..7605cfe 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 Free Software Foundation, Inc. + Copyright (C) 1987, 1993, 1994, 1995, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -40,27 +40,27 @@ struct lang_identifier /* This represents the value which the identifier has in the file-scope namespace. */ #define IDENTIFIER_GLOBAL_VALUE(NODE) \ - (((struct lang_identifier *)(NODE))->global_value) + (((struct lang_identifier *) (NODE))->global_value) /* This represents the value which the identifier has in the current scope. */ #define IDENTIFIER_LOCAL_VALUE(NODE) \ - (((struct lang_identifier *)(NODE))->local_value) + (((struct lang_identifier *) (NODE))->local_value) /* This represents the value which the identifier has as a label in the current label scope. */ #define IDENTIFIER_LABEL_VALUE(NODE) \ - (((struct lang_identifier *)(NODE))->label_value) + (((struct lang_identifier *) (NODE))->label_value) /* This records the extern decl of this identifier, if it has had one at any point in this compilation. */ #define IDENTIFIER_LIMBO_VALUE(NODE) \ - (((struct lang_identifier *)(NODE))->limbo_value) + (((struct lang_identifier *) (NODE))->limbo_value) /* This records the implicit function decl of this identifier, if it has had one at any point in this compilation. */ #define IDENTIFIER_IMPLICIT_DECL(NODE) \ - (((struct lang_identifier *)(NODE))->implicit_decl) + (((struct lang_identifier *) (NODE))->implicit_decl) /* This is the last function in which we printed an "undefined variable" message for this identifier. Value is a FUNCTION_DECL or null. */ #define IDENTIFIER_ERROR_LOCUS(NODE) \ - (((struct lang_identifier *)(NODE))->error_locus) + (((struct lang_identifier *) (NODE))->error_locus) /* In identifiers, C uses the following fields in a special way: TREE_PUBLIC to record that there was a previous local extern decl. @@ -109,7 +109,7 @@ struct lang_type /* Store a value in that field. */ #define C_SET_EXP_ORIGINAL_CODE(exp, code) \ - (TREE_COMPLEXITY (exp) = (int)(code)) + (TREE_COMPLEXITY (exp) = (int) (code)) /* Record whether a typedef for type `int' was actually `signed int'. */ #define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp)) @@ -124,6 +124,9 @@ struct lang_type without prototypes. */ #define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_NONCOPIED_PARTS (NODE) +/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */ +#define DECL_C_BIT_FIELD(NODE) DECL_LANG_FLAG_4 (NODE) + /* 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. */ @@ -146,6 +149,7 @@ struct lang_type extern tree lookup_interface PROTO((tree)); extern tree is_class_name PROTO((tree)); extern void maybe_objc_check_decl PROTO((tree)); +extern void finish_file PROTO((void)); 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)); @@ -159,12 +163,15 @@ extern void gen_aux_info_record PROTO((tree, int, int, int)); extern void declare_function_name PROTO((void)); extern void decl_attributes PROTO((tree, tree, tree)); extern void init_function_format_info PROTO((void)); -extern void record_function_format PROTO((tree, tree, int, int, int)); extern void check_function_format PROTO((tree, tree, tree)); +extern int c_get_alias_set PROTO((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 void c_expand_expr_stmt PROTO((tree)); +extern void c_expand_start_cond PROTO((tree, int, int)); +extern void c_expand_start_else PROTO((void)); +extern void c_expand_end_cond PROTO((void)); /* Validate the expression after `case' and apply default promotions. */ extern tree check_case_value PROTO((tree)); /* Concatenate a list of STRING_CST nodes into one STRING_CST. */ @@ -174,7 +181,14 @@ extern tree convert_and_check PROTO((tree, tree)); extern void overflow_warning PROTO((tree)); extern void unsigned_conversion_warning PROTO((tree, tree)); /* Read the rest of the current #-directive line. */ -extern char *get_directive_line STDIO_PROTO((FILE *)); +#if USE_CPPLIB +extern char *get_directive_line PROTO((void)); +#define GET_DIRECTIVE_LINE() get_directive_line () +#else +extern char *get_directive_line PROTO((FILE *)); +#define GET_DIRECTIVE_LINE() get_directive_line (finput) +#endif + /* Subroutine of build_binary_op, used for comparison operations. See if the operands have both been converted from subword integer types and, if so, perhaps change them both back to their original type. */ @@ -199,6 +213,7 @@ extern tree double_ftype_double; extern tree double_ftype_double_double; extern tree double_type_node; extern tree float_type_node; +extern tree intTI_type_node; extern tree intDI_type_node; extern tree intHI_type_node; extern tree intQI_type_node; @@ -228,6 +243,7 @@ extern tree signed_wchar_type_node; extern tree string_ftype_ptr_ptr; extern tree string_type_node; extern tree unsigned_char_type_node; +extern tree unsigned_intTI_type_node; extern tree unsigned_intDI_type_node; extern tree unsigned_intHI_type_node; extern tree unsigned_intQI_type_node; @@ -248,7 +264,7 @@ extern tree build_enumerator PROTO((tree, tree)); extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *)); /* Add qualifiers to a type, in the fashion for C. */ extern tree c_build_type_variant PROTO((tree, int, int)); -extern int c_decode_option PROTO((char *)); +extern int c_decode_option PROTO((int, char **)); extern void c_mark_varargs PROTO((void)); extern tree check_identifier PROTO((tree, tree)); extern void clear_parm_order PROTO((void)); @@ -285,12 +301,9 @@ extern void pending_xref_error PROTO((void)); extern void pop_c_function_context PROTO((void)); extern void pop_label_level PROTO((void)); extern tree poplevel PROTO((int, int, int)); -extern void print_lang_decl STDIO_PROTO((FILE *, tree, - int)); -extern void print_lang_identifier STDIO_PROTO((FILE *, tree, - int)); -extern void print_lang_type STDIO_PROTO((FILE *, tree, - int)); +extern void print_lang_decl PROTO((FILE *, tree, int)); +extern void print_lang_identifier PROTO((FILE *, tree, int)); +extern void print_lang_type PROTO((FILE *, tree, int)); extern void push_c_function_context PROTO((void)); extern void push_label_level PROTO((void)); extern void push_parm_decl PROTO((tree)); @@ -365,6 +378,7 @@ extern void c_expand_return PROTO((tree)); extern tree c_expand_start_case PROTO((tree)); /* in c-iterate.c */ +extern void init_iterators PROTO((void)); extern void iterator_expand PROTO((tree)); extern void iterator_for_loop_start PROTO((tree)); extern void iterator_for_loop_end PROTO((tree)); @@ -382,6 +396,11 @@ extern int current_function_returns_value; extern int current_function_returns_null; +/* Nonzero means the expression being parsed will never be evaluated. + This is a count, since unevaluated expressions can nest. */ + +extern int skip_evaluation; + /* Nonzero means `$' can be in an identifier. */ extern int dollars_in_ident; @@ -395,6 +414,10 @@ extern int flag_cond_mismatch; extern int flag_no_asm; +/* Nonzero means environment is hosted (i.e., not freestanding) */ + +extern int flag_hosted; + /* Nonzero means ignore `#ident' directives. */ extern int flag_no_ident; @@ -458,6 +481,10 @@ extern int warn_char_subscripts; extern int warn_conversion; +/* Warn if main is suspicious. */ + +extern int warn_main; + /* Nonzero means do some things the same way PCC does. */ extern int flag_traditional; @@ -474,10 +501,13 @@ extern int warn_parentheses; extern int warn_missing_braces; -/* Nonzero means this is a function to call to perform comptypes - on two record types. */ +/* Warn about comparison of signed and unsigned values. */ -extern int (*comptypes_record_hook) (); +extern int warn_sign_compare; + +/* Warn about multicharacter constants. */ + +extern int warn_multichar; /* Nonzero means we are reading code that came from a system header file. */ @@ -487,4 +517,7 @@ extern int system_header_p; extern int doing_objc_thang; +/* In c-decl.c */ +extern void finish_incomplete_decl PROTO((tree)); + #endif /* not _C_TREE_H */ diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c index bae52e3..4ccc1a3 100644 --- a/contrib/gcc/c-typeck.c +++ b/contrib/gcc/c-typeck.c @@ -1,5 +1,5 @@ /* Build expressions with type checking for C compiler. - Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 91-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -29,20 +29,20 @@ Boston, MA 02111-1307, USA. */ like a strange sort of assignment). */ #include "config.h" -#include +#include "system.h" #include "tree.h" #include "c-tree.h" #include "flags.h" #include "output.h" +#include "rtl.h" +#include "expr.h" +#include "toplev.h" /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ static int missing_braces_mentioned; -extern char *index (); -extern char *rindex (); - -static tree quality_type PROTO((tree, tree)); +static tree qualify_type PROTO((tree, tree)); static int comp_target_types PROTO((tree, tree)); static int function_types_compatible_p PROTO((tree, tree)); static int type_lists_compatible_p PROTO((tree, tree)); @@ -71,6 +71,8 @@ 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)); static void output_pending_init_elements PROTO((int)); +static void add_pending_init PROTO((tree, tree)); +static int pending_init_member PROTO((tree)); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -192,40 +194,8 @@ common_type (t1, t2) if (t2 == error_mark_node) return t1; - /* Merge the attributes */ - - { register tree a1, a2; - a1 = TYPE_ATTRIBUTES (t1); - a2 = TYPE_ATTRIBUTES (t2); - - /* Either one unset? Take the set one. */ - - if (!(attributes = a1)) - attributes = a2; - - /* One that completely contains the other? Take it. */ - - else if (a2 && !attribute_list_contained (a1, a2)) - if (attribute_list_contained (a2, a1)) - attributes = a2; - else - { - /* Pick the longest list, and hang on the other list. */ - /* ??? For the moment we punt on the issue of attrs with args. */ - - if (list_length (a1) < list_length (a2)) - attributes = a2, a2 = a1; - - for (; a2; a2 = TREE_CHAIN (a2)) - if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), - attributes) == NULL_TREE) - { - a1 = copy_node (a2); - TREE_CHAIN (a1) = attributes; - attributes = a1; - } - } - } + /* Merge the attributes. */ + attributes = merge_machine_type_attributes (t1, t2); /* Treat an enum type as the unsigned integer type of the same width. */ @@ -293,6 +263,12 @@ common_type (t1, t2) return build_type_attribute_variant (t1, attributes); } + /* Likewise, prefer long double to double even if same size. */ + if (TYPE_MAIN_VARIANT (t1) == long_double_type_node + || TYPE_MAIN_VARIANT (t2) == long_double_type_node) + return build_type_attribute_variant (long_double_type_node, + attributes); + /* Otherwise prefer the unsigned one. */ if (TREE_UNSIGNED (t1)) @@ -427,7 +403,7 @@ common_type (t1, t2) } t1 = build_function_type (valtype, newargs); - /* ... falls through ... */ + /* ... falls through ... */ } default: @@ -450,7 +426,8 @@ comptypes (type1, type2) /* Suppress errors caused by previously reported errors. */ - if (t1 == t2 || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK) + if (t1 == t2 || !t1 || !t2 + || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK) return 1; /* Treat an enum type as the integer type of the same width and @@ -477,7 +454,7 @@ comptypes (type1, type2) /* Allow for two different type nodes which have essentially the same definition. Note that we already checked for equality of the type - type qualifiers (just above). */ + qualifiers (just above). */ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; @@ -539,6 +516,9 @@ comptypes (type1, type2) if (maybe_objc_comptypes (t1, t2, 0) == 1) val = 1; break; + + default: + break; } return attrval == 2 && val == 1 ? 2 : val; } @@ -553,7 +533,7 @@ comp_target_types (ttl, ttr) int val; /* Give maybe_objc_comptypes a crack at letting these types through. */ - if (val = maybe_objc_comptypes (ttl, ttr, 1) >= 0) + if ((val = maybe_objc_comptypes (ttl, ttr, 1)) >= 0) return val; val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), @@ -767,7 +747,8 @@ unsigned_type (type) return unsigned_intHI_type_node; if (type1 == intQI_type_node) return unsigned_intQI_type_node; - return type; + + return signed_or_unsigned_type (1, type); } /* Return a signed type the same as TYPE in other respects. */ @@ -795,7 +776,8 @@ signed_type (type) return intHI_type_node; if (type1 == unsigned_intQI_type_node) return intQI_type_node; - return type; + + return signed_or_unsigned_type (0, type); } /* Return a type the same as TYPE except unsigned or @@ -806,7 +788,8 @@ signed_or_unsigned_type (unsignedp, type) int unsignedp; tree type; { - if (! INTEGRAL_TYPE_P (type)) + if ((! INTEGRAL_TYPE_P (type) && ! POINTER_TYPE_P (type)) + || TREE_UNSIGNED (type) == unsignedp) return type; if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; @@ -854,6 +837,7 @@ c_sizeof (type) /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node))); + t = convert (sizetype, t); /* size_binop does not put the constant in range, so do it now. */ if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0)) TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1; @@ -877,6 +861,7 @@ c_sizeof_nowarn (type) /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node))); + t = convert (sizetype, t); force_fit_type (t, 0); return t; } @@ -905,6 +890,7 @@ c_size_in_bytes (type) /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (BITS_PER_UNIT)); + t = convert (sizetype, t); force_fit_type (t, 0); return t; } @@ -940,7 +926,7 @@ c_alignof_expr (expr) return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT); 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"); return size_int (1); @@ -970,16 +956,16 @@ c_alignof_expr (expr) else return c_alignof (TREE_TYPE (expr)); } + /* Return either DECL or its known constant value (if it has one). */ static tree decl_constant_value (decl) tree decl; { - if (! TREE_PUBLIC (decl) - /* Don't change a variable array bound or initial value to a constant + if (/* Don't change a variable array bound or initial value to a constant in a place where a variable is invalid. */ - && current_function_decl != 0 + current_function_decl != 0 && ! pedantic && ! TREE_THIS_VOLATILE (decl) && TREE_READONLY (decl) && ! ITERATOR_P (decl) @@ -1037,11 +1023,30 @@ default_conversion (exp) type = type_for_size (MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)), ((flag_traditional - || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)) + || (TYPE_PRECISION (type) + >= TYPE_PRECISION (integer_type_node))) && TREE_UNSIGNED (type))); return convert (type, exp); } + if (TREE_CODE (exp) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))) + { + tree width = DECL_SIZE (TREE_OPERAND (exp, 1)); + HOST_WIDE_INT low = TREE_INT_CST_LOW (width); + + /* If it's thinner than an int, promote it like a + C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone. */ + + if (low < TYPE_PRECISION (integer_type_node)) + { + if (flag_traditional && TREE_UNSIGNED (type)) + return convert (unsigned_type_node, exp); + else + return convert (integer_type_node, exp); + } + } + if (C_PROMOTING_INTEGER_TYPE_P (type)) { /* Traditionally, unsignedness is preserved in default promotions. @@ -1096,7 +1101,7 @@ default_conversion (exp) TREE_OPERAND (exp, 0), op1); } - if (!lvalue_p (exp) + if (! lvalue_p (exp) && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) { error ("invalid use of non-lvalue array"); @@ -1162,10 +1167,13 @@ lookup_field (type, component, indirect) /* Step through all anon unions in linear fashion. */ while (DECL_NAME (field_array[bot]) == NULL_TREE) { - tree anon, junk; + tree anon = 0, junk; field = field_array[bot++]; - anon = lookup_field (TREE_TYPE (field), component, &junk); + if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + anon = lookup_field (TREE_TYPE (field), component, &junk); + if (anon != NULL_TREE) { *indirect = field; @@ -1201,7 +1209,12 @@ lookup_field (type, component, indirect) if (DECL_NAME (field) == NULL_TREE) { tree junk; - tree anon = lookup_field (TREE_TYPE (field), component, &junk); + tree anon = 0; + + if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + anon = lookup_field (TREE_TYPE (field), component, &junk); + if (anon != NULL_TREE) { *indirect = field; @@ -1245,6 +1258,9 @@ build_component_ref (datum, component) (TREE_OPERAND (datum, 0), build_component_ref (TREE_OPERAND (datum, 1), component), build_component_ref (TREE_OPERAND (datum, 2), component)); + + default: + break; } /* See if there is a field or component with name COMPONENT. */ @@ -1331,7 +1347,7 @@ build_indirect_ref (ptr, errorstring) error ("dereferencing pointer to incomplete type"); return error_mark_node; } - if (TREE_CODE (t) == VOID_TYPE) + if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0) warning ("dereferencing `void *' pointer"); /* We *must* set TREE_READONLY when dereferencing a pointer to const, @@ -1465,6 +1481,14 @@ build_array_ref (array, index) tree ar = default_conversion (array); tree ind = default_conversion (index); + /* Do the same warning check as above, but only on the part that's + syntactically the index and only if it is also semantically + the index. */ + if (warn_char_subscripts + && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) + warning ("subscript has type `char'"); + /* Put the integer in IND to simplify error checking. */ if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) { @@ -1476,7 +1500,8 @@ build_array_ref (array, index) if (ar == error_mark_node) return ar; - if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE) + if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE) { error ("subscripted value is neither array nor pointer"); return error_mark_node; @@ -1567,6 +1592,8 @@ build_function_call (function, params) if (coerced_params == 0) return integer_zero_node; return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0); + default: + break; } { @@ -1734,7 +1761,7 @@ convert_arguments (typelist, values, name, fundecl) } parmval = convert_for_assignment (type, val, - (char *)0, /* arg passing */ + (char *) 0, /* arg passing */ fundecl, name, parmnum + 1); #ifdef PROMOTE_PROTOTYPES @@ -2109,7 +2136,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) case RSHIFT_EXPR: if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - if (TREE_CODE (op1) == INTEGER_CST) + if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { if (tree_int_cst_sgn (op1) < 0) warning ("right shift count is negative"); @@ -2141,7 +2168,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) case LSHIFT_EXPR: if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - if (TREE_CODE (op1) == INTEGER_CST) + if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { if (tree_int_cst_sgn (op1) < 0) warning ("left shift count is negative"); @@ -2169,7 +2196,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) case LROTATE_EXPR: if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - if (TREE_CODE (op1) == INTEGER_CST) + if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { if (tree_int_cst_sgn (op1) < 0) warning ("shift count is negative"); @@ -2327,6 +2354,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) pedwarn ("comparison between pointer and integer"); } break; + + default: + break; } if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) @@ -2471,7 +2501,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) converted = 1; resultcode = xresultcode; - if (extra_warnings) + if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare != 0) + && skip_evaluation == 0) { int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0)); int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1)); @@ -2513,9 +2544,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) not use the most significant bit of result_type. */ else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR) && ((op0_signed && TREE_CODE (xop1) == INTEGER_CST - && int_fits_type_p (xop1, signed_type (result_type)) + && int_fits_type_p (xop1, signed_type (result_type))) || (op1_signed && TREE_CODE (xop0) == INTEGER_CST - && int_fits_type_p (xop0, signed_type (result_type)))))) + && int_fits_type_p (xop0, signed_type (result_type))))) /* OK */; else warning ("comparison between signed and unsigned"); @@ -2677,11 +2708,13 @@ pointer_int_sum (resultcode, ptrop, intop) intop = convert (int_type, TREE_OPERAND (intop, 0)); } - /* Convert the integer argument to a type the same size as a pointer + /* Convert the integer argument to a type the same size as sizetype so the multiply won't overflow spuriously. */ - if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE) - intop = convert (type_for_size (POINTER_SIZE, 0), intop); + if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype) + || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype)) + intop = convert (type_for_size (TYPE_PRECISION (sizetype), + TREE_UNSIGNED (sizetype)), intop); /* Replace the integer argument with a suitable product by the object size. Do this multiplication as signed, then convert to the appropriate @@ -2722,10 +2755,12 @@ pointer_diff (op0, op1) } /* First do the subtraction as integers; - then drop through to build the divide operator. */ + then drop through to build the divide operator. + Do not do default conversions on the minus operator + in case restype is a short type. */ op0 = build_binary_op (MINUS_EXPR, convert (restype, op0), - convert (restype, op1), 1); + convert (restype, op1), 0); /* This generates an error if op1 is pointer to incomplete type. */ if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0) error ("arithmetic on pointer to an incomplete type"); @@ -3070,7 +3105,7 @@ build_unary_op (code, xarg, noconvert) addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0); - if (DECL_BIT_FIELD (field)) + if (DECL_C_BIT_FIELD (field)) { error ("attempt to take address of bit-field structure member `%s'", IDENTIFIER_POINTER (DECL_NAME (field))); @@ -3101,6 +3136,9 @@ build_unary_op (code, xarg, noconvert) TREE_CONSTANT (addr) = 1; return addr; } + + default: + break; } if (!errstring) @@ -3169,12 +3207,16 @@ lvalue_p (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; + return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); + + case BIND_EXPR: + case RTL_EXPR: + return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; + + default: + return 0; } - return 0; } /* Return nonzero if REF is an lvalue valid for this language; @@ -3206,7 +3248,12 @@ unary_complex_lvalue (code, arg) if (TREE_CODE (arg) == COMPOUND_EXPR) { tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0); - pedantic_lvalue_warning (COMPOUND_EXPR); + + /* If this returns a function type, it isn't really being used as + an lvalue, so don't issue a warning about it. */ + if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE) + pedantic_lvalue_warning (COMPOUND_EXPR); + return build (COMPOUND_EXPR, TREE_TYPE (real_result), TREE_OPERAND (arg, 0), real_result); } @@ -3215,6 +3262,9 @@ unary_complex_lvalue (code, arg) if (TREE_CODE (arg) == COND_EXPR) { pedantic_lvalue_warning (COND_EXPR); + if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE) + pedantic_lvalue_warning (COMPOUND_EXPR); + return (build_conditional_expr (TREE_OPERAND (arg, 0), build_unary_op (code, TREE_OPERAND (arg, 1), 0), @@ -3287,8 +3337,17 @@ mark_addressable (exp) while (1) switch (TREE_CODE (x)) { - case ADDR_EXPR: case COMPONENT_REF: + if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) + { + error ("cannot take address of bitfield `%s'", + IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); + return 0; + } + + /* ... fall through ... */ + + case ADDR_EXPR: case ARRAY_REF: case REALPART_EXPR: case IMAGPART_EXPR: @@ -3366,15 +3425,6 @@ build_conditional_expr (ifexp, op1, op2) register tree result_type = NULL; tree orig_op1 = op1, orig_op2 = op2; - /* If second operand is omitted, it is the same as the first one; - make sure it is calculated only once. */ - if (op1 == 0) - { - if (pedantic) - pedwarn ("ANSI C forbids omitting the middle term of a ?: expression"); - ifexp = op1 = save_expr (ifexp); - } - ifexp = truthvalue_conversion (default_conversion (ifexp)); #if 0 /* Produces wrong result if within sizeof. */ @@ -3721,11 +3771,18 @@ build_c_cast (type, expr) && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE) { - if (TYPE_VOLATILE (TREE_TYPE (otype)) - && ! TYPE_VOLATILE (TREE_TYPE (type))) + /* Go to the innermost object being pointed to. */ + tree in_type = type; + tree in_otype = otype; + + while (TREE_CODE (in_type) == POINTER_TYPE) + 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 (TREE_TYPE (otype)) - && ! TYPE_READONLY (TREE_TYPE (type))) + if (TYPE_READONLY (in_otype) && ! TYPE_READONLY (in_type)) pedwarn ("cast discards `const' from pointer target type"); } @@ -3735,6 +3792,11 @@ build_c_cast (type, expr) && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE + /* Don't warn about opaque types, where the actual alignment + restriction is unknown. */ + && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) + && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) warning ("cast increases required alignment of target type"); @@ -3851,6 +3913,8 @@ build_modify_expr (lhs, modifycode, rhs) /* But cast it to void to avoid an "unused" error. */ convert (void_type_node, rhs), cond); } + default: + break; } /* If a binary op has been requested, combine the old LHS value with the RHS @@ -3892,6 +3956,9 @@ build_modify_expr (lhs, modifycode, rhs) pedantic_lvalue_warning (CONVERT_EXPR); return convert (TREE_TYPE (lhs), result); } + + default: + break; } /* Now we have handled acceptable kinds of LHS that are not truly lvalues. @@ -4014,26 +4081,27 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) || coder == COMPLEX_TYPE)) return convert_and_check (type, rhs); - /* Conversion to a union from its member types. */ - else if (codel == UNION_TYPE) + /* Conversion to a transparent union from its member types. + This applies only to function arguments. */ + else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype) { tree memb_types; + tree marginal_memb_type = 0; for (memb_types = TYPE_FIELDS (type); memb_types; memb_types = TREE_CHAIN (memb_types)) { - if (comptypes (TREE_TYPE (memb_types), TREE_TYPE (rhs))) - { - if (pedantic - && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl))) - pedwarn ("ANSI C prohibits argument conversion to union type"); - return build1 (NOP_EXPR, type, rhs); - } + tree memb_type = TREE_TYPE (memb_types); + + if (comptypes (TYPE_MAIN_VARIANT (memb_type), + TYPE_MAIN_VARIANT (rhstype))) + break; + + if (TREE_CODE (memb_type) != POINTER_TYPE) + continue; - else if (coder == POINTER_TYPE - && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE) + if (coder == POINTER_TYPE) { - tree memb_type = TREE_TYPE (memb_types); register tree ttl = TREE_TYPE (memb_type); register tree ttr = TREE_TYPE (rhstype); @@ -4045,50 +4113,76 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) || TYPE_MAIN_VARIANT (ttr) == void_type_node || comp_target_types (memb_type, rhstype)) { - /* Const and volatile mean something different for function - types, so the usual warnings are not appropriate. */ - 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); - if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) - warn_for_assignment ("%s discards `volatile' from pointer target type", - get_spelling (errtype), funname, - parmnum); - } - else - { - /* Because const and volatile on functions are - restrictions 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 (pedantic - && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl))) - pedwarn ("ANSI C prohibits argument conversion to union type"); - return build1 (NOP_EXPR, type, rhs); + /* 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)))) + break; + + /* Keep looking for a better type, but remember this one. */ + if (! marginal_memb_type) + marginal_memb_type = memb_type; } } /* Can convert integer zero to any pointer type. */ - else if (TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE - && (integer_zerop (rhs) - || (TREE_CODE (rhs) == NOP_EXPR - && integer_zerop (TREE_OPERAND (rhs, 0))))) - return build1 (NOP_EXPR, type, null_pointer_node); + if (integer_zerop (rhs) + || (TREE_CODE (rhs) == NOP_EXPR + && integer_zerop (TREE_OPERAND (rhs, 0)))) + { + rhs = null_pointer_node; + break; + } + } + + if (memb_types || marginal_memb_type) + { + if (! memb_types) + { + /* We have only a marginally acceptable member type; + it needs a warning. */ + register tree ttl = TREE_TYPE (marginal_memb_type); + register tree ttr = TREE_TYPE (rhstype); + + /* Const and volatile mean something different for function + types, so the usual warnings are not appropriate. */ + if (TREE_CODE (ttr) == FUNCTION_TYPE + && TREE_CODE (ttl) == FUNCTION_TYPE) + { + /* Because const and volatile on functions are + restrictions 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); + } + 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 (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl)) + pedwarn ("ANSI C prohibits argument conversion to union type"); + + return build1 (NOP_EXPR, type, rhs); } } @@ -4270,7 +4364,8 @@ initializer_constant_valid_p (value, endtype) case CONSTRUCTOR: if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) - && TREE_CONSTANT (value)) + && TREE_CONSTANT (value) + && CONSTRUCTOR_ELTS (value)) return initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)), endtype); @@ -4377,9 +4472,10 @@ initializer_constant_valid_p (value, endtype) return null_pointer_node; return 0; } - } - return 0; + default: + return 0; + } } /* If VALUE is a compound expr all of whose expressions are constant, then @@ -4600,7 +4696,7 @@ print_spelling (buffer) { if (p->kind == SPELLING_MEMBER) *d++ = '.'; - for (s = p->u.s; *d = *s++; d++) + for (s = p->u.s; (*d = *s++); d++) ; } *d++ = '\0'; @@ -4994,20 +5090,29 @@ static int constructor_erroneous; /* 1 if have called defer_addressed_constants. */ static int constructor_subconstants_deferred; -/* List of pending elements at this constructor level. +/* Structure for managing pending initializer elements, organized as an + AVL tree. */ + +struct init_node +{ + struct init_node *left, *right; + struct init_node *parent; + int balance; + tree purpose; + tree value; +}; + +/* Tree of pending elements at this constructor level. These are elements encountered out of order which belong at places we haven't reached yet in actually writing the output. */ -static tree constructor_pending_elts; +static struct init_node *constructor_pending_elts; /* The SPELLING_DEPTH of this constructor. */ static int constructor_depth; /* 0 if implicitly pushing constructor levels is allowed. */ -int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */ - -/* 1 if this constructor level was entered implicitly. */ -static int constructor_implicit; +int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */ static int require_constant_value; static int require_constant_elements; @@ -5027,9 +5132,6 @@ static char *constructor_asmspec; /* Nonzero if this is an initializer for a top-level decl. */ static int constructor_top_level; -/* When we finish reading a constructor expression - (constructor_decl is 0), the CONSTRUCTOR goes here. */ -static tree constructor_result; /* This stack has a level for each implicit or explicit level of structuring in the initializer, including the outermost one. It @@ -5048,7 +5150,7 @@ struct constructor_stack tree bit_index; tree elements; int offset; - tree pending_elts; + struct init_node *pending_elts; int depth; /* If nonzero, this value should replace the entire constructor at this level. */ @@ -5247,11 +5349,12 @@ really_start_incremental_init (type) { constructor_fields = TYPE_FIELDS (constructor_type); /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields) + while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) && DECL_NAME (constructor_fields) == 0) constructor_fields = TREE_CHAIN (constructor_fields); constructor_unfilled_fields = constructor_fields; constructor_bit_index = copy_node (integer_zero_node); + TREE_TYPE (constructor_bit_index) = sbitsizetype; } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { @@ -5320,23 +5423,32 @@ push_init_level (implicit) break; } - /* Structure elements may require alignment. Do this now - if necessary for the subaggregate. */ + /* Structure elements may require alignment. Do this now if necessary + for the subaggregate, and if it comes next in sequence. Don't do + this for subaggregates that will go on the pending list. */ if (constructor_incremental && constructor_type != 0 - && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields) + && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields + && constructor_fields == constructor_unfilled_fields) { /* Advance to offset of this element. */ if (! tree_int_cst_equal (constructor_bit_index, DECL_FIELD_BITPOS (constructor_fields))) { - int next = (TREE_INT_CST_LOW - (DECL_FIELD_BITPOS (constructor_fields)) - / BITS_PER_UNIT); - int here = (TREE_INT_CST_LOW (constructor_bit_index) - / BITS_PER_UNIT); - - assemble_zeros (next - here); + /* By using unsigned arithmetic, the result will be correct even + in case of overflows, if BITS_PER_UNIT is a power of two. */ + unsigned next = (TREE_INT_CST_LOW + (DECL_FIELD_BITPOS (constructor_fields)) + / (unsigned)BITS_PER_UNIT); + unsigned here = (TREE_INT_CST_LOW (constructor_bit_index) + / (unsigned)BITS_PER_UNIT); + + assemble_zeros ((next - here) + * (unsigned)BITS_PER_UNIT + / (unsigned)BITS_PER_UNIT); } + /* Indicate that we have now filled the structure up to the current + field. */ + constructor_unfilled_fields = constructor_fields; } p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack)); @@ -5419,11 +5531,12 @@ push_init_level (implicit) { constructor_fields = TYPE_FIELDS (constructor_type); /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields) + while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) && DECL_NAME (constructor_fields) == 0) constructor_fields = TREE_CHAIN (constructor_fields); constructor_unfilled_fields = constructor_fields; constructor_bit_index = copy_node (integer_zero_node); + TREE_TYPE (constructor_bit_index) = sbitsizetype; } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { @@ -5461,7 +5574,7 @@ check_init_type_bitfields (type) for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail)) { - if (DECL_BIT_FIELD (tail) + if (DECL_C_BIT_FIELD (tail) /* This catches cases like `int foo : 8;'. */ || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail))) { @@ -5506,6 +5619,17 @@ pop_init_level (implicit) if (constructor_type != 0) size = int_size_in_bytes (constructor_type); + /* Warn when some struct elements are implicitly initialized to zero. */ + if (extra_warnings + && constructor_type + && TREE_CODE (constructor_type) == RECORD_TYPE + && constructor_unfilled_fields) + { + push_member_name (constructor_unfilled_fields); + warning_init ("missing initializer%s", " for `%s'", NULL); + RESTORE_SPELLING_DEPTH (constructor_depth); + } + /* Now output all pending elements. */ output_pending_init_elements (1); @@ -5729,10 +5853,8 @@ set_init_index (first, last) error_init ("duplicate array index in initializer%s", " for `%s'", NULL); else { - TREE_INT_CST_LOW (constructor_index) - = TREE_INT_CST_LOW (first); - TREE_INT_CST_HIGH (constructor_index) - = TREE_INT_CST_HIGH (first); + 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); @@ -5782,6 +5904,251 @@ set_init_label (fieldname) } } +/* Add a new initializer to the tree of pending initializers. PURPOSE + indentifies the initializer, either array index or field in a structure. + VALUE is the value of that index or field. */ + +static void +add_pending_init (purpose, value) + tree purpose, value; +{ + struct init_node *p, **q, *r; + + q = &constructor_pending_elts; + p = 0; + + if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + while (*q != 0) + { + p = *q; + if (tree_int_cst_lt (purpose, p->purpose)) + q = &p->left; + else if (tree_int_cst_lt (p->purpose, purpose)) + q = &p->right; + else + abort (); + } + } + else + { + while (*q != NULL) + { + p = *q; + if (tree_int_cst_lt (DECL_FIELD_BITPOS (purpose), + DECL_FIELD_BITPOS (p->purpose))) + q = &p->left; + else if (tree_int_cst_lt (DECL_FIELD_BITPOS (p->purpose), + DECL_FIELD_BITPOS (purpose))) + q = &p->right; + else + abort (); + } + } + + r = (struct init_node *) oballoc (sizeof (struct init_node)); + r->purpose = purpose; + r->value = value; + + *q = r; + r->parent = p; + r->left = 0; + r->right = 0; + r->balance = 0; + + while (p) + { + struct init_node *s; + + if (r == p->left) + { + if (p->balance == 0) + p->balance = -1; + else if (p->balance < 0) + { + if (r->balance < 0) + { + /* L rotation. */ + p->left = r->right; + if (p->left) + p->left->parent = p; + r->right = p; + + p->balance = 0; + r->balance = 0; + + s = p->parent; + p->parent = r; + r->parent = s; + if (s) + { + if (s->left == p) + s->left = r; + else + s->right = r; + } + else + constructor_pending_elts = r; + } + else + { + /* LR rotation. */ + struct init_node *t = r->right; + + r->right = t->left; + if (r->right) + r->right->parent = r; + t->left = r; + + p->left = t->right; + if (p->left) + p->left->parent = p; + t->right = p; + + p->balance = t->balance < 0; + r->balance = -(t->balance > 0); + t->balance = 0; + + s = p->parent; + p->parent = t; + r->parent = t; + t->parent = s; + if (s) + { + if (s->left == p) + s->left = t; + else + s->right = t; + } + else + constructor_pending_elts = t; + } + break; + } + else + { + /* p->balance == +1; growth of left side balances the node. */ + p->balance = 0; + break; + } + } + else /* r == p->right */ + { + if (p->balance == 0) + /* Growth propagation from right side. */ + p->balance++; + else if (p->balance > 0) + { + if (r->balance > 0) + { + /* R rotation. */ + p->right = r->left; + if (p->right) + p->right->parent = p; + r->left = p; + + p->balance = 0; + r->balance = 0; + + s = p->parent; + p->parent = r; + r->parent = s; + if (s) + { + if (s->left == p) + s->left = r; + else + s->right = r; + } + else + constructor_pending_elts = r; + } + else /* r->balance == -1 */ + { + /* RL rotation */ + struct init_node *t = r->left; + + r->left = t->right; + if (r->left) + r->left->parent = r; + t->right = r; + + p->right = t->left; + if (p->right) + p->right->parent = p; + t->left = p; + + r->balance = (t->balance < 0); + p->balance = -(t->balance > 0); + t->balance = 0; + + s = p->parent; + p->parent = t; + r->parent = t; + t->parent = s; + if (s) + { + if (s->left == p) + s->left = t; + else + s->right = t; + } + else + constructor_pending_elts = t; + } + break; + } + else + { + /* p->balance == -1; growth of right side balances the node. */ + p->balance = 0; + break; + } + } + + r = p; + p = p->parent; + } +} + +/* Return nonzero if FIELD is equal to the index of a pending initializer. */ + +static int +pending_init_member (field) + tree field; +{ + struct init_node *p; + + p = constructor_pending_elts; + if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + while (p) + { + if (tree_int_cst_equal (field, p->purpose)) + return 1; + else if (tree_int_cst_lt (field, p->purpose)) + p = p->left; + else + p = p->right; + } + } + else + { + while (p) + { + if (field == p->purpose) + return 1; + else if (tree_int_cst_lt (DECL_FIELD_BITPOS (field), + DECL_FIELD_BITPOS (p->purpose))) + p = p->left; + else + p = p->right; + } + } + + return 0; +} + /* "Output" the next constructor element. At top level, really output it to assembler code now. Otherwise, collect it in a list from which we will make a CONSTRUCTOR. @@ -5815,7 +6182,8 @@ output_init_element (value, type, field, pending) else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0 || ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) - && DECL_BIT_FIELD (field) && TREE_CODE (value) != INTEGER_CST)) + && DECL_C_BIT_FIELD (field) + && TREE_CODE (value) != INTEGER_CST)) constructor_simple = 0; if (require_constant_value && ! TREE_CONSTANT (value)) @@ -5839,25 +6207,10 @@ output_init_element (value, type, field, pending) if (pending) { if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + || TREE_CODE (constructor_type) == UNION_TYPE + || TREE_CODE (constructor_type) == ARRAY_TYPE) { - if (purpose_member (field, constructor_pending_elts)) - { - error_init ("duplicate initializer%s", " for `%s'", NULL); - duplicate = 1; - } - } - if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - tree tail; - for (tail = constructor_pending_elts; tail; - tail = TREE_CHAIN (tail)) - if (TREE_PURPOSE (tail) != 0 - && TREE_CODE (TREE_PURPOSE (tail)) == INTEGER_CST - && tree_int_cst_equal (TREE_PURPOSE (tail), constructor_index)) - break; - - if (tail != 0) + if (pending_init_member (field)) { error_init ("duplicate initializer%s", " for `%s'", NULL); duplicate = 1; @@ -5873,11 +6226,9 @@ output_init_element (value, type, field, pending) if (! duplicate) /* The copy_node is needed in case field is actually constructor_index, which is modified in place. */ - constructor_pending_elts - = tree_cons (copy_node (field), - digest_init (type, value, require_constant_value, - require_constant_elements), - constructor_pending_elts); + add_pending_init (copy_node (field), + digest_init (type, value, require_constant_value, + require_constant_elements)); } else if (TREE_CODE (constructor_type) == RECORD_TYPE && field != constructor_unfilled_fields) @@ -5886,11 +6237,9 @@ output_init_element (value, type, field, pending) no matter which field is specified, it can be initialized right away since it starts at the beginning of the union. */ if (!duplicate) - constructor_pending_elts - = tree_cons (field, - digest_init (type, value, require_constant_value, - require_constant_elements), - constructor_pending_elts); + add_pending_init (field, + digest_init (type, value, require_constant_value, + require_constant_elements)); } else { @@ -5919,12 +6268,19 @@ output_init_element (value, type, field, pending) if (! tree_int_cst_equal (constructor_bit_index, DECL_FIELD_BITPOS (field))) { - int next = (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)) - / BITS_PER_UNIT); - int here = (TREE_INT_CST_LOW (constructor_bit_index) - / BITS_PER_UNIT); - - assemble_zeros (next - here); + /* By using unsigned arithmetic, the result will be + correct even in case of overflows, if BITS_PER_UNIT + is a power of two. */ + unsigned next = (TREE_INT_CST_LOW + (DECL_FIELD_BITPOS (field)) + / (unsigned)BITS_PER_UNIT); + unsigned here = (TREE_INT_CST_LOW + (constructor_bit_index) + / (unsigned)BITS_PER_UNIT); + + assemble_zeros ((next - here) + * (unsigned)BITS_PER_UNIT + / (unsigned)BITS_PER_UNIT); } } output_constant (digest_init (type, value, @@ -5983,56 +6339,109 @@ static void output_pending_init_elements (all) int all; { - tree tail; + struct init_node *elt = constructor_pending_elts; tree next; retry: - /* Look thru the whole pending list. + /* Look thru the whole pending tree. If we find an element that should be output now, output it. Otherwise, set NEXT to the element that comes first among those still pending. */ next = 0; - for (tail = constructor_pending_elts; tail; - tail = TREE_CHAIN (tail)) + while (elt) { if (TREE_CODE (constructor_type) == ARRAY_TYPE) { - if (tree_int_cst_equal (TREE_PURPOSE (tail), + if (tree_int_cst_equal (elt->purpose, constructor_unfilled_index)) + output_init_element (elt->value, + TREE_TYPE (constructor_type), + constructor_unfilled_index, 0); + else if (tree_int_cst_lt (constructor_unfilled_index, + elt->purpose)) { - output_init_element (TREE_VALUE (tail), - TREE_TYPE (constructor_type), - constructor_unfilled_index, 0); - goto retry; + /* Advance to the next smaller node. */ + if (elt->left) + elt = elt->left; + else + { + /* We have reached the smallest node bigger than the + current unfilled index. Fill the space first. */ + next = elt->purpose; + break; + } + } + else + { + /* Advance to the next bigger node. */ + if (elt->right) + elt = elt->right; + else + { + /* We have reached the biggest node in a subtree. Find + the parent of it, which is the next bigger node. */ + while (elt->parent && elt->parent->right == elt) + elt = elt->parent; + elt = elt->parent; + if (elt && tree_int_cst_lt (constructor_unfilled_index, + elt->purpose)) + { + next = elt->purpose; + break; + } + } } - else if (tree_int_cst_lt (TREE_PURPOSE (tail), - constructor_unfilled_index)) - ; - else if (next == 0 - || tree_int_cst_lt (TREE_PURPOSE (tail), next)) - next = TREE_PURPOSE (tail); } else if (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) { - if (TREE_PURPOSE (tail) == constructor_unfilled_fields) + /* If the current record is complete we are done. */ + if (constructor_unfilled_fields == 0) + break; + if (elt->purpose == constructor_unfilled_fields) { - output_init_element (TREE_VALUE (tail), + output_init_element (elt->value, TREE_TYPE (constructor_unfilled_fields), constructor_unfilled_fields, 0); - goto retry; } - else if (constructor_unfilled_fields == 0 - || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)), - DECL_FIELD_BITPOS (constructor_unfilled_fields))) - ; - else if (next == 0 - || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)), - DECL_FIELD_BITPOS (next))) - next = TREE_PURPOSE (tail); + else if (tree_int_cst_lt (DECL_FIELD_BITPOS (constructor_unfilled_fields), + DECL_FIELD_BITPOS (elt->purpose))) + { + /* Advance to the next smaller node. */ + if (elt->left) + elt = elt->left; + else + { + /* We have reached the smallest node bigger than the + current unfilled field. Fill the space first. */ + next = elt->purpose; + break; + } + } + else + { + /* Advance to the next bigger node. */ + if (elt->right) + elt = elt->right; + else + { + /* We have reached the biggest node in a subtree. Find + the parent of it, which is the next bigger node. */ + while (elt->parent && elt->parent->right == elt) + elt = elt->parent; + elt = elt->parent; + if (elt + && tree_int_cst_lt (DECL_FIELD_BITPOS (constructor_unfilled_fields), + DECL_FIELD_BITPOS (elt->purpose))) + { + next = elt->purpose; + break; + } + } + } } } @@ -6050,6 +6459,7 @@ output_pending_init_elements (all) if (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) { + tree tail; /* Find the last field written out, if any. */ for (tail = TYPE_FIELDS (constructor_type); tail; tail = TREE_CHAIN (tail)) @@ -6115,6 +6525,8 @@ output_pending_init_elements (all) } } + /* ELT now points to the node in the pending tree with the next + initializer to output. */ goto retry; } @@ -6172,7 +6584,9 @@ process_init_element (value) && constructor_fields == 0) process_init_element (pop_init_level (1)); else if (TREE_CODE (constructor_type) == ARRAY_TYPE - && tree_int_cst_lt (constructor_max_index, constructor_index)) + && (constructor_max_index == 0 + || tree_int_cst_lt (constructor_max_index, + constructor_index))) process_init_element (pop_init_level (1)); else break; @@ -6239,7 +6653,8 @@ process_init_element (value) constructor_fields = TREE_CHAIN (constructor_fields); /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields) + while (constructor_fields != 0 + && DECL_C_BIT_FIELD (constructor_fields) && DECL_NAME (constructor_fields) == 0) constructor_fields = TREE_CHAIN (constructor_fields); break; @@ -6331,9 +6746,23 @@ process_init_element (value) break; } - /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */ + /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */ if (constructor_range_end) - value = save_expr (value); + { + if (constructor_max_index != 0 + && tree_int_cst_lt (constructor_max_index, + constructor_range_end)) + { + pedwarn_init ("excess elements in array initializer%s", + " after `%s'", NULL_PTR); + TREE_INT_CST_HIGH (constructor_range_end) + = TREE_INT_CST_HIGH (constructor_max_index); + TREE_INT_CST_LOW (constructor_range_end) + = TREE_INT_CST_LOW (constructor_max_index); + } + + value = save_expr (value); + } /* Now output the actual element. Ordinarily, output once. @@ -6351,10 +6780,8 @@ process_init_element (value) tem = size_binop (PLUS_EXPR, constructor_index, integer_one_node); - TREE_INT_CST_LOW (constructor_index) - = TREE_INT_CST_LOW (tem); - TREE_INT_CST_HIGH (constructor_index) - = TREE_INT_CST_HIGH (tem); + TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (tem); + TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (tem); if (!value) /* If we are doing the bookkeeping for an element that was @@ -6446,7 +6873,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) if (o[i] != TREE_VALUE (tail)) { expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), - 0, VOIDmode, 0); + NULL_RTX, VOIDmode, EXPAND_NORMAL); free_temp_slots (); } /* Detect modification of read-only values. @@ -6549,6 +6976,9 @@ c_expand_return (retval) && DECL_CONTEXT (inner) == current_function_decl) warning ("function returns address of local variable"); break; + + default: + break; } break; diff --git a/contrib/gcc/caller-save.c b/contrib/gcc/caller-save.c index 6dc9018..4a2deb6 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, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1989, 1992, 94-95, 1997, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,6 +19,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "rtl.h" #include "insn-config.h" #include "flags.h" @@ -28,6 +29,7 @@ Boston, MA 02111-1307, USA. */ #include "basic-block.h" #include "reload.h" #include "expr.h" +#include "toplev.h" #ifndef MAX_MOVE_MAX #define MAX_MOVE_MAX MOVE_MAX @@ -143,11 +145,11 @@ init_caller_save () if (i == FIRST_PSEUDO_REGISTER) abort (); - addr_reg = gen_rtx (REG, Pmode, i); + addr_reg = gen_rtx_REG (Pmode, i); for (offset = 1 << (HOST_BITS_PER_INT / 2); offset; offset >>= 1) { - address = gen_rtx (PLUS, Pmode, addr_reg, GEN_INT (offset)); + address = gen_rtx_PLUS (Pmode, addr_reg, GEN_INT (offset)); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (regno_save_mode[i][1] != VOIDmode @@ -171,10 +173,10 @@ init_caller_save () for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++) if (regno_save_mode[i][j] != VOIDmode) { - rtx mem = gen_rtx (MEM, regno_save_mode[i][j], address); - rtx reg = gen_rtx (REG, regno_save_mode[i][j], i); - rtx savepat = gen_rtx (SET, VOIDmode, mem, reg); - rtx restpat = gen_rtx (SET, VOIDmode, reg, mem); + rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address); + rtx reg = gen_rtx_REG (regno_save_mode[i][j], i); + rtx savepat = gen_rtx_SET (VOIDmode, mem, reg); + rtx restpat = gen_rtx_SET (VOIDmode, reg, mem); rtx saveinsn = emit_insn (savepat); rtx restinsn = emit_insn (restpat); int ok; @@ -182,7 +184,8 @@ init_caller_save () reg_save_code[i][j] = recog_memoized (saveinsn); reg_restore_code[i][j] = recog_memoized (restinsn); - /* Now extract both insns and see if we can meet their constraints. */ + /* 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); if (ok) { @@ -261,7 +264,7 @@ setup_save_areas (pchanged) /* Find and record all call-used hard-registers in this function. */ CLEAR_HARD_REG_SET (hard_regs_used); for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) - if (reg_renumber[i] >= 0 && reg_n_calls_crossed[i] > 0) + if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0) { int regno = reg_renumber[i]; int endregno @@ -307,7 +310,7 @@ setup_save_areas (pchanged) ok &= (TEST_HARD_REG_BIT (hard_regs_used, regno) != 0); } - /* We have found an acceptable mode to store in. */ + /* We have found an acceptable mode to store in. */ if (ok) { @@ -315,13 +318,13 @@ setup_save_areas (pchanged) = 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... */ + /* 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)); + 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); @@ -356,8 +359,7 @@ save_call_clobbered_regs (insn_mode) { regset regs_live = basic_block_live_at_start[b]; rtx prev_block_last = PREV_INSN (basic_block_head[b]); - REGSET_ELT_TYPE bit; - int offset, i, j; + int i, j; int regno; /* Compute hard regs live at start of block -- this is the @@ -366,31 +368,20 @@ save_call_clobbered_regs (insn_mode) saved because we restore all of them before the end of the basic block. */ -#ifdef HARD_REG_SET - hard_regs_live = *regs_live; -#else - COPY_HARD_REG_SET (hard_regs_live, regs_live); -#endif - + 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; - for (offset = 0, i = 0; offset < regset_size; offset++) - { - if (regs_live[offset] == 0) - i += REGSET_ELT_BITS; - else - for (bit = 1; bit && i < max_regno; bit <<= 1, i++) - if ((regs_live[offset] & bit) - && (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); - - } + 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 @@ -515,7 +506,8 @@ save_call_clobbered_regs (insn_mode) static void set_reg_live (reg, setter) - rtx reg, setter; + rtx reg; + rtx setter ATTRIBUTE_UNUSED; { register int regno, endregno, i; enum machine_mode mode = GET_MODE (reg); @@ -650,9 +642,9 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore) enum machine_mode insn_mode; int maxrestore; { - rtx pat; - enum insn_code code; - int i, numregs; + 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 @@ -702,8 +694,9 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore) if (! ok) continue; - pat = gen_rtx (SET, VOIDmode, regno_save_mem[regno][i], - gen_rtx (REG, GET_MODE (regno_save_mem[regno][i]), regno)); + 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]; /* Set hard_regs_saved for all the registers we saved. */ @@ -741,9 +734,9 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore) if (! ok) continue; - pat = gen_rtx (SET, VOIDmode, - gen_rtx (REG, GET_MODE (regno_save_mem[regno][i]), - regno), + 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]; diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c index ad05be4..8b14019 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, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,16 +19,20 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" -#include "rtl.h" -#include "tree.h" -#include "flags.h" -#include "expr.h" #ifdef __STDC__ #include #else #include #endif +#include "system.h" +#include "rtl.h" +#include "tree.h" +#include "flags.h" +#include "expr.h" +#include "regs.h" #include "insn-flags.h" +#include "toplev.h" +#include "output.h" /* Decide whether a function's arguments should be processed from first to last or from last to first. @@ -60,7 +64,7 @@ struct arg_data /* Initially-compute RTL value for argument; only for const functions. */ rtx initial_value; /* Register to pass this argument in, 0 if passed on stack, or an - EXPR_LIST if the arg is to be copied into multiple different + PARALLEL if the arg is to be copied into multiple non-contiguous registers. */ rtx reg; /* If REG was promoted from the actual mode of the argument expression, @@ -95,14 +99,12 @@ struct arg_data /* Place that this stack area has been saved, if needed. */ rtx save_area; #endif -#ifdef STRICT_ALIGNMENT /* If an argument's alignment does not permit direct copying into registers, copy in smaller-sized pieces into pseudos. These are stored in a block pointed to by this field. The next field says how many word-sized pseudos we made. */ rtx *aligned_regs; int n_aligned_regs; -#endif }; #ifdef ACCUMULATE_OUTGOING_ARGS @@ -125,7 +127,8 @@ int stack_arg_under_construction; static int calls_function PROTO((tree, int)); static int calls_function_1 PROTO((tree, int)); -static void emit_call_1 PROTO((rtx, tree, tree, int, int, rtx, rtx, +static void emit_call_1 PROTO((rtx, tree, tree, HOST_WIDE_INT, + HOST_WIDE_INT, rtx, rtx, int, rtx, int)); static void store_one_arg PROTO ((struct arg_data *, rtx, int, int, tree, int)); @@ -234,6 +237,9 @@ calls_function_1 (exp, which) case RTL_EXPR: return 0; + + default: + break; } for (i = 0; i < length; i++) @@ -263,20 +269,17 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen) funexp = protect_from_queue (funexp, 0); if (fndecl != 0) - /* Get possible static chain value for nested function in C. */ + /* Get possible static chain value for nested function in C. */ static_chain_value = lookup_static_chain (fndecl); /* Make a valid memory address and copy constants thru pseudo-regs, but not for a constant address if -fno-function-cse. */ if (GET_CODE (funexp) != SYMBOL_REF) - funexp = -#ifdef SMALL_REGISTER_CLASSES /* If we are using registers for parameters, force the - function address into a register now. */ - reg_parm_seen ? force_not_mem (memory_address (FUNCTION_MODE, funexp)) - : -#endif - memory_address (FUNCTION_MODE, funexp); + function address into a register now. */ + funexp = ((SMALL_REGISTER_CLASSES && reg_parm_seen) + ? force_not_mem (memory_address (FUNCTION_MODE, funexp)) + : memory_address (FUNCTION_MODE, funexp)); else { #ifndef NO_FUNCTION_CSE @@ -303,12 +306,14 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen) and optionally pop the results. The CALL_INSN is the first insn generated. - FNDECL is the declaration node of the function. This is given ot the + FNDECL is the declaration node of the function. This is given to the macro RETURN_POPS_ARGS to determine whether this function pops its own args. - FUNTYPE is the data type of the function, or, for a library call, - the identifier for the name of the call. This is given to the - macro RETURN_POPS_ARGS to determine whether this function pops its own args. + FUNTYPE is the data type of the function. This is given to the macro + RETURN_POPS_ARGS to determine whether this function pops its own args. + We used to allow an identifier for library functions, but that doesn't + work when the return type is an aggregate type and the calling convention + 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. @@ -345,8 +350,8 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size, rtx funexp; tree fndecl; tree funtype; - int stack_size; - int struct_value_size; + HOST_WIDE_INT stack_size; + HOST_WIDE_INT struct_value_size; rtx next_arg_reg; rtx valreg; int old_inhibit_defer_pop; @@ -356,7 +361,9 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size, rtx stack_size_rtx = GEN_INT (stack_size); rtx struct_value_size_rtx = GEN_INT (struct_value_size); rtx call_insn; +#ifndef ACCUMULATE_OUTGOING_ARGS int already_popped = 0; +#endif /* Ensure address is valid. SYMBOL_REF is already valid, so no need, and we don't want to load it into a register as an optimization, @@ -378,10 +385,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), + gen_rtx_MEM (FUNCTION_MODE, funexp), stack_size_rtx, next_arg_reg, n_pop); else - pat = gen_call_pop (gen_rtx (MEM, FUNCTION_MODE, funexp), + pat = gen_call_pop (gen_rtx_MEM (FUNCTION_MODE, funexp), stack_size_rtx, next_arg_reg, n_pop); emit_call_insn (pat); @@ -396,11 +403,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), + gen_rtx_MEM (FUNCTION_MODE, funexp), stack_size_rtx, next_arg_reg, NULL_RTX)); else - emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp), + emit_call_insn (gen_call (gen_rtx_MEM (FUNCTION_MODE, funexp), stack_size_rtx, next_arg_reg, struct_value_size_rtx)); } @@ -451,10 +458,10 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size, if (stack_size != 0 && RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 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)); + 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); } @@ -485,8 +492,6 @@ expand_call (exp, target, ignore) tree actparms = TREE_OPERAND (exp, 1); /* RTX for the function to be called. */ rtx funexp; - /* Tree node for the function to be called (not the address!). */ - tree funtree; /* Data type of the function. */ tree funtype; /* Declaration of the function being called, @@ -507,7 +512,7 @@ expand_call (exp, target, ignore) /* Size of aggregate value wanted, or zero if none wanted or if we are using the non-reentrant PCC calling convention or expecting the value in registers. */ - int struct_value_size = 0; + HOST_WIDE_INT struct_value_size = 0; /* Nonzero if called function returns an aggregate in memory PCC style, by returning the address of where to find it. */ int pcc_struct_value = 0; @@ -534,7 +539,6 @@ expand_call (exp, target, ignore) /* Nonzero if a reg parm has been scanned. */ int reg_parm_seen; /* Nonzero if this is an indirect function call. */ - int current_call_is_indirect = 0; /* Nonzero if we must avoid push-insns in the args for this call. If stack space is allocated for register parameters, but not by the @@ -542,15 +546,11 @@ expand_call (exp, target, ignore) So the entire argument block must then be preallocated (i.e., we ignore PUSH_ROUNDING in that case). */ -#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) - int must_preallocate = 1; -#else #ifdef PUSH_ROUNDING int must_preallocate = 0; #else int must_preallocate = 1; #endif -#endif /* Size of the stack reserved for parameter registers. */ int reg_parm_stack_space = 0; @@ -563,6 +563,8 @@ expand_call (exp, target, ignore) /* Nonzero if it is plausible that this is a call to alloca. */ int may_be_alloca; + /* Nonzero if this is a call to malloc or a related function. */ + int is_malloc; /* Nonzero if this is a call to setjmp or a related function. */ int returns_twice; /* Nonzero if this is a call to `longjmp'. */ @@ -584,17 +586,23 @@ expand_call (exp, target, ignore) #ifdef ACCUMULATE_OUTGOING_ARGS int initial_highest_arg_in_use = highest_outgoing_arg_in_use; char *initial_stack_usage_map = stack_usage_map; + int old_stack_arg_under_construction; #endif rtx old_stack_level = 0; int old_pending_adj = 0; - int old_stack_arg_under_construction; int old_inhibit_defer_pop = inhibit_defer_pop; - tree old_cleanups = cleanups_this_call; rtx call_fusage = 0; register tree p; register int i, j; + /* 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) + target = 0; + /* See if we can find a DECL-node for the actual function. As a result, decide whether this is a call to an integrable function. */ @@ -609,7 +617,8 @@ expand_call (exp, target, ignore) if (!flag_no_inline && fndecl != current_function_decl && DECL_INLINE (fndecl) - && DECL_SAVED_INSNS (fndecl)) + && DECL_SAVED_INSNS (fndecl) + && RTX_INTEGRATED_P (DECL_SAVED_INSNS (fndecl))) is_integrable = 1; else if (! TREE_ADDRESSABLE (fndecl)) { @@ -618,7 +627,8 @@ expand_call (exp, target, ignore) Use abstraction instead of setting TREE_ADDRESSABLE directly. */ - if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline) + if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline + && optimize > 0) { warning_with_decl (fndecl, "can't inline call to `%s'"); warning ("called from here"); @@ -651,6 +661,11 @@ expand_call (exp, target, ignore) #endif #endif +#if defined(PUSH_ROUNDING) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) + if (reg_parm_stack_space > 0) + must_preallocate = 1; +#endif + /* Warn if this value is an aggregate type, regardless of which calling convention we are using for it. */ if (warn_aggregate_return && AGGREGATE_TYPE_P (TREE_TYPE (exp))) @@ -685,7 +700,8 @@ expand_call (exp, target, ignore) structure_value_addr = XEXP (target, 0); else { - /* Assign a temporary on the stack to hold the value. */ + /* Assign a temporary to hold the value. */ + tree d; /* For variable-sized objects, we must be called with a target specified. If we were to allocate space on the stack here, @@ -694,10 +710,13 @@ expand_call (exp, target, ignore) if (struct_value_size < 0) abort (); - structure_value_addr - = XEXP (assign_stack_temp (BLKmode, struct_value_size, 1), 0); - MEM_IN_STRUCT_P (structure_value_addr) - = AGGREGATE_TYPE_P (TREE_TYPE (exp)); + /* This DECL is just something to feed to mark_addressable; + it doesn't get pushed. */ + d = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp)); + DECL_RTL (d) = assign_temp (TREE_TYPE (exp), 1, 0, 1); + mark_addressable (d); + structure_value_addr = XEXP (DECL_RTL (d), 0); + TREE_USED (d) = 1; target = 0; } } @@ -709,26 +728,17 @@ expand_call (exp, target, ignore) if (is_integrable) { rtx temp; +#ifdef ACCUMULATE_OUTGOING_ARGS rtx before_call = get_last_insn (); +#endif temp = expand_inline_function (fndecl, actparms, target, ignore, TREE_TYPE (exp), structure_value_addr); /* If inlining succeeded, return. */ - if ((HOST_WIDE_INT) temp != -1) + if (temp != (rtx) (HOST_WIDE_INT) -1) { - if (flag_short_temps) - { - /* Perform all cleanups needed for the arguments of this - call (i.e. destructors in C++). It is ok if these - destructors clobber RETURN_VALUE_REG, because the - only time we care about this is when TARGET is that - register. But in C++, we take care to never return - that register directly. */ - expand_cleanups_to (old_cleanups); - } - #ifdef ACCUMULATE_OUTGOING_ARGS /* If the outgoing argument list must be preserved, push the stack before executing the inlined function if it @@ -740,7 +750,9 @@ expand_call (exp, target, ignore) if (stack_arg_under_construction || i >= 0) { - rtx insn = NEXT_INSN (before_call), seq; + rtx first_insn + = before_call ? NEXT_INSN (before_call) : get_insns (); + rtx insn, seq; /* Look for a call in the inline function code. If OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) is @@ -748,7 +760,7 @@ expand_call (exp, target, ignore) to scan the insns. */ if (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) == 0) - for (; insn; insn = NEXT_INSN (insn)) + for (insn = first_insn; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == CALL_INSN) break; @@ -762,25 +774,25 @@ expand_call (exp, target, ignore) outgoing argument list in addition to the requested space, but there is no way to ask for stack space such that an argument list of a certain length can be - safely constructed. */ + safely constructed. - int adjust = OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)); -#ifdef REG_PARM_STACK_SPACE - /* Add the stack space reserved for register arguments - in the inline function. What is really needed is the + Add the stack space reserved for register arguments, if + any, in the inline function. What is really needed is the largest value of reg_parm_stack_space in the inline function, but that is not available. Using the current value of reg_parm_stack_space is wrong, but gives correct results on all supported machines. */ - adjust += reg_parm_stack_space; -#endif + + int adjust = (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) + + reg_parm_stack_space); + start_sequence (); emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); allocate_dynamic_stack_space (GEN_INT (adjust), NULL_RTX, BITS_PER_UNIT); seq = get_insns (); end_sequence (); - emit_insns_before (seq, NEXT_INSN (before_call)); + emit_insns_before (seq, first_insn); emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); } } @@ -798,7 +810,7 @@ expand_call (exp, target, ignore) separately after all. If function was declared inline, give a warning. */ if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline - && ! TREE_ADDRESSABLE (fndecl)) + && optimize > 0 && ! TREE_ADDRESSABLE (fndecl)) { warning_with_decl (fndecl, "inlining failed in call to `%s'"); warning ("called from here"); @@ -816,29 +828,20 @@ expand_call (exp, target, ignore) if (fndecl && DECL_NAME (fndecl)) name = IDENTIFIER_POINTER (DECL_NAME (fndecl)); - /* On some machines (such as the PA) indirect calls have a different - calling convention than normal calls. FUNCTION_ARG in the target - description can look at current_call_is_indirect to determine which - calling convention to use. */ - current_call_is_indirect = (fndecl == 0); -#if 0 - = TREE_CODE (TREE_OPERAND (exp, 0)) == NON_LVALUE_EXPR ? 1 : 0; -#endif - #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); + 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 + may_be_alloca + = (name && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6 && name[0] == 'a' && ! strcmp (name, "alloca")) || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16 @@ -851,8 +854,13 @@ expand_call (exp, target, ignore) returns_twice = 0; is_longjmp = 0; + is_malloc = 0; - if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 15) + 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; @@ -890,6 +898,18 @@ expand_call (exp, target, ignore) 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; } if (may_be_alloca) @@ -913,8 +933,13 @@ expand_call (exp, target, ignore) we make. */ push_temp_slots (); - /* Start updating where the next arg would go. */ - INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX); + /* Start updating where the next arg would go. + + On some machines (such as the PA) indirect calls have a different + calling convention than normal calls. The last argument in + INIT_CUMULATIVE_ARGS tells the backend if this is an indirect call + or not. */ + INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, (fndecl == 0)); /* If struct_value_rtx is 0, it means pass the address as if it were an extra parameter. */ @@ -947,11 +972,11 @@ expand_call (exp, target, ignore) /* Compute number of named args. Normally, don't include the last named arg if anonymous args follow. - We do include the last named arg if STRICT_ARGUMENT_NAMING is defined. + We do include the last named arg if STRICT_ARGUMENT_NAMING is nonzero. (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 not, + 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 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 @@ -960,18 +985,20 @@ expand_call (exp, target, ignore) If SETUP_INCOMING_VARARGS is not defined, we do not have any reliable way to pass unnamed args in registers, so we must force them into memory. */ -#if !defined(SETUP_INCOMING_VARARGS) || defined(STRICT_ARGUMENT_NAMING) - if (TYPE_ARG_TYPES (funtype) != 0) + + if ((STRICT_ARGUMENT_NAMING +#ifndef SETUP_INCOMING_VARARGS + || 1 +#endif + ) + && TYPE_ARG_TYPES (funtype) != 0) n_named_args = (list_length (TYPE_ARG_TYPES (funtype)) -#ifndef STRICT_ARGUMENT_NAMING /* Don't include the last named arg. */ - - 1 -#endif + - (STRICT_ARGUMENT_NAMING ? 0 : 1) /* Count the struct value address, if it is passed as a parm. */ + structure_value_addr_parm); else -#endif /* If we know nothing, treat all args as named. */ n_named_args = num_actuals; @@ -1037,14 +1064,19 @@ expand_call (exp, target, ignore) #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 - if (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)) + || (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), @@ -1052,14 +1084,17 @@ expand_call (exp, target, ignore) type = build_pointer_type (type); } else -#endif { /* 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) + || 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. */ @@ -1072,10 +1107,10 @@ expand_call (exp, target, ignore) pending_stack_adjust = 0; } - copy = gen_rtx (MEM, BLKmode, - allocate_dynamic_stack_space (size_rtx, - NULL_RTX, - TYPE_ALIGN (type))); + copy = gen_rtx_MEM (BLKmode, + allocate_dynamic_stack_space (size_rtx, + NULL_RTX, + TYPE_ALIGN (type))); } else { @@ -1086,6 +1121,7 @@ expand_call (exp, target, ignore) 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), @@ -1114,12 +1150,12 @@ expand_call (exp, target, ignore) args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type); - /* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that - we are to pass this arg in the register(s) designated by FOO, but - also to pass it in the stack. */ - if (args[i].reg && GET_CODE (args[i].reg) == EXPR_LIST - && XEXP (args[i].reg, 0) == 0) - args[i].pass_on_stack = 1, args[i].reg = XEXP (args[i].reg, 1); + /* 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. @@ -1137,9 +1173,7 @@ expand_call (exp, target, ignore) /* Compute the stack-size of this argument. */ if (args[i].reg == 0 || args[i].partial != 0 -#ifdef REG_PARM_STACK_SPACE || reg_parm_stack_space > 0 -#endif || args[i].pass_on_stack) locate_and_pad_parm (mode, type, #ifdef STACK_PARMS_IN_REG_PARM_AREA @@ -1154,14 +1188,12 @@ expand_call (exp, target, ignore) args[i].slot_offset = args_size; #endif -#ifndef REG_PARM_STACK_SPACE /* If a part of the arg was put into registers, don't include that part in the amount pushed. */ - if (! args[i].pass_on_stack) + 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)); -#endif /* Update ARGS_SIZE, the total stack space for args so far. */ @@ -1218,12 +1250,11 @@ expand_call (exp, target, ignore) args_size.var = round_up (args_size.var, STACK_BYTES); #endif -#ifdef REG_PARM_STACK_SPACE if (reg_parm_stack_space > 0) { args_size.var = size_binop (MAX_EXPR, args_size.var, - size_int (REG_PARM_STACK_SPACE (fndecl))); + size_int (reg_parm_stack_space)); #ifndef OUTGOING_REG_PARM_STACK_SPACE /* The area corresponding to register parameters is not to count in @@ -1233,7 +1264,6 @@ expand_call (exp, target, ignore) size_int (reg_parm_stack_space)); #endif } -#endif } else { @@ -1242,17 +1272,17 @@ expand_call (exp, target, ignore) / STACK_BYTES) * STACK_BYTES); #endif -#ifdef REG_PARM_STACK_SPACE 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 -#endif } /* See if we have or want to preallocate stack space. @@ -1362,7 +1392,7 @@ expand_call (exp, target, ignore) /* Now we are about to start emitting insns that can be deleted if a libcall is deleted. */ - if (is_const) + if (is_const || is_malloc) start_sequence (); /* If we have no actual push instructions, or shouldn't use them, @@ -1394,8 +1424,9 @@ expand_call (exp, target, ignore) int needed = args_size.constant; - /* Store the maximum argument space used. It will be pushed by the - prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow checking). */ + /* Store the maximum argument space used. It will be pushed by + the prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow + checking). */ if (needed > current_function_outgoing_args_size) current_function_outgoing_args_size = needed; @@ -1416,7 +1447,7 @@ expand_call (exp, target, ignore) Another approach might be to try to reorder the argument evaluations to avoid this conflicting stack usage. */ -#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) +#ifndef OUTGOING_REG_PARM_STACK_SPACE /* Since we will be writing into the entire argument area, the map must be allocated for its entire size, not just the part that is the responsibility of the caller. */ @@ -1488,7 +1519,7 @@ expand_call (exp, target, ignore) to initialize an argument. */ if (stack_arg_under_construction) { -#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) +#ifndef OUTGOING_REG_PARM_STACK_SPACE rtx push_size = GEN_INT (reg_parm_stack_space + args_size.constant); #else rtx push_size = GEN_INT (args_size.constant); @@ -1545,20 +1576,20 @@ expand_call (exp, target, ignore) if (GET_CODE (offset) == CONST_INT) addr = plus_constant (arg_reg, INTVAL (offset)); else - addr = gen_rtx (PLUS, Pmode, arg_reg, offset); + addr = gen_rtx_PLUS (Pmode, arg_reg, offset); addr = plus_constant (addr, arg_offset); - args[i].stack = gen_rtx (MEM, args[i].mode, addr); + 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 = 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); + args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr); } } @@ -1597,6 +1628,12 @@ expand_call (exp, target, ignore) 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 (); } @@ -1613,7 +1650,7 @@ 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. */ + 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) @@ -1655,16 +1692,13 @@ expand_call (exp, target, ignore) && GET_CODE (SUBREG_REG (args[i].value)) == REG))) && args[i].mode != BLKmode && rtx_cost (args[i].value, SET) > 2 -#ifdef SMALL_REGISTER_CLASSES - && (reg_parm_seen || preserve_subexpressions_p ()) -#else - && preserve_subexpressions_p () -#endif - ) + && ((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. @@ -1699,17 +1733,17 @@ expand_call (exp, target, ignore) BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1))) save_mode = BLKmode; - stack_area = gen_rtx (MEM, save_mode, - memory_address (save_mode, - #ifdef ARGS_GROW_DOWNWARD - plus_constant (argblock, - - high_to_save) + stack_area = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + - high_to_save))); #else - plus_constant (argblock, - low_to_save) + 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); @@ -1738,68 +1772,73 @@ expand_call (exp, target, ignore) store_one_arg (&args[i], argblock, may_be_alloca, args_size.var != 0, fndecl, reg_parm_stack_space); -#ifdef STRICT_ALIGNMENT /* 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. */ - for (i = 0; i < num_actuals; i++) - if (args[i].reg != 0 && ! args[i].pass_on_stack + 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; + && (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].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); + 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)); + /* 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. */ - - emit_insn (gen_rtx (CLOBBER, VOIDmode, reg)); - - 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); - } - } - } -#endif + 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); + } + } + } /* Now store any partially-in-registers parm. This is the last place a block-move can happen. */ @@ -1834,6 +1873,16 @@ expand_call (exp, target, ignore) force_reg (Pmode, force_operand (structure_value_addr, NULL_RTX))); + + /* Mark the memory for the aggregate as write-only. */ + if (flag_check_memory_usage) + emit_library_call (chkr_set_right_libfunc, 1, + VOIDmode, 3, + structure_value_addr, ptr_mode, + GEN_INT (struct_value_size), TYPE_MODE (sizetype), + GEN_INT (MEMORY_USE_WO), + TYPE_MODE (integer_type_node)); + if (GET_CODE (struct_value_rtx) == REG) use_reg (&call_fusage, struct_value_rtx); } @@ -1847,22 +1896,18 @@ expand_call (exp, target, ignore) 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 list = args[i].reg; + rtx reg = args[i].reg; int partial = args[i].partial; + int nregs; - while (list) + if (reg) { - rtx reg; - int nregs; - - /* Process each register that needs to get this arg. */ - if (GET_CODE (list) == EXPR_LIST) - reg = XEXP (list, 0), list = XEXP (list, 1); - else - reg = list, list = 0; - /* 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 @@ -1873,36 +1918,45 @@ expand_call (exp, target, ignore) + (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. */ - if (nregs == -1) + else if (nregs == -1) emit_move_insn (reg, args[i].value); -#ifdef STRICT_ALIGNMENT /* 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), + emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg) + j), args[i].aligned_regs[j]); -#endif - else if (args[i].partial == 0 || args[i].pass_on_stack) + else if (partial == 0 || args[i].pass_on_stack) move_block_to_reg (REGNO (reg), validize_mem (args[i].value), nregs, args[i].mode); - if (nregs == -1) + /* 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); - - /* PARTIAL referred only to the first register, so clear it for the - next time. */ - partial = 0; } } @@ -1918,23 +1972,31 @@ expand_call (exp, target, ignore) /* If call is cse'able, make appropriate pair of reg-notes around it. Test valreg so we don't crash; may safely ignore `const' - if return type is void. */ - if (is_const && valreg != 0) + if return type is void. Disable for PARALLEL return values, because + we have no way to move such values into a pseudo register. */ + if (is_const && valreg != 0 && GET_CODE (valreg) != PARALLEL) { rtx note = 0; rtx temp = gen_reg_rtx (GET_MODE (valreg)); rtx insns; + /* Mark the return value as a pointer if needed. */ + if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE) + { + tree pointed_to = TREE_TYPE (TREE_TYPE (exp)); + mark_reg_pointer (temp, TYPE_ALIGN (pointed_to) / BITS_PER_UNIT); + } + /* Construct an "equal form" for the value which mentions all the arguments in order as well as the function name. */ #ifdef PUSH_ARGS_REVERSED for (i = 0; i < num_actuals; i++) - note = gen_rtx (EXPR_LIST, VOIDmode, args[i].initial_value, note); + note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note); #else for (i = num_actuals - 1; i >= 0; i--) - note = gen_rtx (EXPR_LIST, VOIDmode, args[i].initial_value, note); + note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note); #endif - note = gen_rtx (EXPR_LIST, VOIDmode, funexp, note); + note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note); insns = get_insns (); end_sequence (); @@ -1951,6 +2013,29 @@ expand_call (exp, target, ignore) end_sequence (); emit_insns (insns); } + else if (is_malloc) + { + rtx temp = gen_reg_rtx (GET_MODE (valreg)); + rtx last, insns; + + /* The return value from a malloc-like function is a pointer. */ + if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE) + mark_reg_pointer (temp, BIGGEST_ALIGNMENT / BITS_PER_UNIT); + + emit_move_insn (temp, valreg); + + /* The return value from a malloc-like function can not alias + anything else. */ + last = get_last_insn (); + REG_NOTES (last) = + gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last)); + + /* Write out the sequence. */ + insns = get_insns (); + end_sequence (); + emit_insns (insns); + valreg = temp; + } /* For calls to `setjmp', etc., inform flow.c it should complain if nonvolatile values are live. */ @@ -1974,8 +2059,9 @@ expand_call (exp, target, ignore) /* If value type not void, return an rtx for the value. */ - /* If there are cleanups to be called, don't use a hard reg as target. */ - if (cleanups_this_call != old_cleanups + /* If there are cleanups to be called, don't use a hard reg as target. + We need to double check this and see if it matters anymore. */ + if (any_pending_cleanups (1) && target && REG_P (target) && REGNO (target) < FIRST_PSEUDO_REGISTER) target = 0; @@ -1989,44 +2075,36 @@ expand_call (exp, target, ignore) { if (target == 0 || GET_CODE (target) != MEM) { - target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), - memory_address (TYPE_MODE (TREE_TYPE (exp)), - structure_value_addr)); + 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)); } } else if (pcc_struct_value) { + /* This is the special C++ case where we need to + know what the true target was. We take care to + 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)); + } + /* Handle calls that return values in multiple non-contiguous locations. + The Irix 6 ABI has examples of this. */ + else if (GET_CODE (valreg) == PARALLEL) + { + int bytes = int_size_in_bytes (TREE_TYPE (exp)); + if (target == 0) { - /* We used leave the value in the location that it is - returned in, but that causes problems if it is used more - than once in one expression. Rather than trying to track - when a copy is required, we always copy when TARGET is - not specified. This calling sequence is only used on - a few machines and TARGET is usually nonzero. */ - if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode) - { - target = assign_stack_temp (BLKmode, - int_size_in_bytes (TREE_TYPE (exp)), - 0); - - MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp)); - - /* Save this temp slot around the pop below. */ - preserve_temp_slots (target); - } - else - target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), bytes, 0); + MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp)); + preserve_temp_slots (target); } - if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode) - emit_move_insn (target, gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), - copy_to_reg (valreg))); - else - emit_block_move (target, gen_rtx (MEM, BLKmode, copy_to_reg (valreg)), - expr_size (exp), - TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); + emit_group_store (target, valreg, bytes, + TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); } else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)) && GET_MODE (target) == GET_MODE (valreg)) @@ -2045,10 +2123,7 @@ expand_call (exp, target, ignore) Deal with them explicitly by copying from the return registers into the target MEM locations. */ int bytes = int_size_in_bytes (TREE_TYPE (exp)); - int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - int i; - enum machine_mode tmpmode; - rtx src, dst; + rtx src = NULL, dst = NULL; int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (exp)), BITS_PER_WORD); int bitpos, xbitpos, big_endian_correction = 0; @@ -2063,7 +2138,7 @@ expand_call (exp, target, ignore) 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 (SImode, valreg, + valreg = convert_to_mode (word_mode, valreg, TREE_UNSIGNED (TREE_TYPE (exp))); /* Structures whose size is not a multiple of a word are aligned @@ -2128,19 +2203,12 @@ expand_call (exp, target, ignore) != promote_mode (type, TYPE_MODE (type), &unsignedp, 1)) abort (); - target = gen_rtx (SUBREG, TYPE_MODE (type), target, 0); + target = gen_rtx_SUBREG (TYPE_MODE (type), target, 0); SUBREG_PROMOTED_VAR_P (target) = 1; SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp; } #endif - if (flag_short_temps) - { - /* Perform all cleanups needed for the arguments of this call - (i.e. destructors in C++). */ - expand_cleanups_to (old_cleanups); - } - /* If size of args is variable or this was a constructor call for a stack argument, restore saved stack-pointer value. */ @@ -2161,15 +2229,19 @@ expand_call (exp, target, ignore) if (save_area) { enum machine_mode save_mode = GET_MODE (save_area); - rtx stack_area - = gen_rtx (MEM, save_mode, - memory_address (save_mode, #ifdef ARGS_GROW_DOWNWARD - plus_constant (argblock, - high_to_save) + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + - high_to_save))); #else - plus_constant (argblock, low_to_save) + 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); @@ -2186,9 +2258,9 @@ expand_call (exp, target, ignore) { enum machine_mode save_mode = GET_MODE (args[i].save_area); rtx stack_area - = gen_rtx (MEM, save_mode, - memory_address (save_mode, - XEXP (args[i].stack_slot, 0))); + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + XEXP (args[i].stack_slot, 0))); if (save_mode != BLKmode) emit_move_insn (stack_area, args[i].save_area); @@ -2205,7 +2277,7 @@ expand_call (exp, target, ignore) /* If this was alloca, record the new stack level for nonlocal gotos. Check for the handler slots since we might not have a save area - for non-local gotos. */ + for non-local gotos. */ if (may_be_alloca && nonlocal_goto_handler_slot != 0) emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX); @@ -2257,12 +2329,32 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, rtx argblock = 0; CUMULATIVE_ARGS args_so_far; struct arg { rtx value; enum machine_mode mode; rtx reg; int partial; - struct args_size offset; struct args_size size; }; + struct args_size offset; struct args_size size; rtx save_area; }; struct arg *argvec; int old_inhibit_defer_pop = inhibit_defer_pop; rtx call_fusage = 0; - /* library calls are never indirect calls. */ - int current_call_is_indirect = 0; + int reg_parm_stack_space = 0; +#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) + /* Define the boundary of the register parm stack space that needs to be + save, if any. */ + int low_to_save = -1, high_to_save; + rtx save_area = 0; /* Place that it is saved */ +#endif + +#ifdef ACCUMULATE_OUTGOING_ARGS + int initial_highest_arg_in_use = highest_outgoing_arg_in_use; + char *initial_stack_usage_map = stack_usage_map; + int needed; +#endif + +#ifdef REG_PARM_STACK_SPACE + /* Size of the stack reserved for parameter registers. */ +#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); +#endif +#endif VA_START (p, nargs); @@ -2283,8 +2375,10 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, library functions shouldn't have many args. */ argvec = (struct arg *) alloca (nargs * sizeof (struct arg)); + bzero ((char *) argvec, nargs * sizeof (struct arg)); + - INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun); + INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0); args_size.constant = 0; args_size.var = 0; @@ -2333,7 +2427,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, argvec[count].mode = mode; argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); - if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) + if (argvec[count].reg && GET_CODE (argvec[count].reg) == PARALLEL) abort (); #ifdef FUNCTION_ARG_PARTIAL_NREGS argvec[count].partial @@ -2350,35 +2444,22 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, if (argvec[count].size.var) abort (); -#ifndef REG_PARM_STACK_SPACE - if (argvec[count].partial) + if (reg_parm_stack_space == 0 && argvec[count].partial) argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD; -#endif if (argvec[count].reg == 0 || argvec[count].partial != 0 -#ifdef REG_PARM_STACK_SPACE - || 1 -#endif - ) + || reg_parm_stack_space > 0) args_size.constant += argvec[count].size.constant; -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If this arg is actually passed on the stack, it might be - clobbering something we already put there (this library call might - be inside the evaluation of an argument to a function whose call - requires the stack). This will only occur when the library call - has sufficient args to run out of argument registers. Abort in - this case; if this ever occurs, code must be added to save and - restore the arg slot. */ - - if (argvec[count].reg == 0 || argvec[count].partial != 0) - abort (); -#endif - - FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1); + FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1); } va_end (p); +#ifdef FINAL_REG_PARM_STACK_SPACE + reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant, + args_size.var); +#endif + /* If this machine requires an external definition for library functions, write one out. */ assemble_external_libcall (fun); @@ -2389,24 +2470,67 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, / STACK_BYTES) * STACK_BYTES); #endif -#ifdef REG_PARM_STACK_SPACE args_size.constant = MAX (args_size.constant, - REG_PARM_STACK_SPACE (NULL_TREE)); + reg_parm_stack_space); + #ifndef OUTGOING_REG_PARM_STACK_SPACE - args_size.constant -= REG_PARM_STACK_SPACE (NULL_TREE); -#endif + args_size.constant -= reg_parm_stack_space; #endif if (args_size.constant > current_function_outgoing_args_size) current_function_outgoing_args_size = args_size.constant; #ifdef ACCUMULATE_OUTGOING_ARGS - args_size.constant = 0; + /* Since the stack pointer will never be pushed, it is possible for + the evaluation of a parm to clobber something we have already + written to the stack. Since most function calls on RISC machines + do not use the stack, this is uncommon, but must work correctly. + + Therefore, we save any area of the stack that was already written + and that we are using. Here we set up to do this by making a new + stack usage map from the old one. + + Another approach might be to try to reorder the argument + evaluations to avoid this conflicting stack usage. */ + + needed = args_size.constant; + +#ifndef OUTGOING_REG_PARM_STACK_SPACE + /* Since we will be writing into the entire argument area, the + map must be allocated for its entire size, not just the part that + is the responsibility of the caller. */ + needed += reg_parm_stack_space; #endif +#ifdef ARGS_GROW_DOWNWARD + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed + 1); +#else + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed); +#endif + stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); + + if (initial_highest_arg_in_use) + bcopy (initial_stack_usage_map, stack_usage_map, + initial_highest_arg_in_use); + + if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) + bzero (&stack_usage_map[initial_highest_arg_in_use], + highest_outgoing_arg_in_use - initial_highest_arg_in_use); + needed = 0; + + /* The address of the outgoing argument list must not be copied to a + register here, because argblock would be left pointing to the + wrong place after the call to allocate_dynamic_stack_space below. + */ + + argblock = virtual_outgoing_args_rtx; +#else /* not ACCUMULATE_OUTGOING_ARGS */ #ifndef PUSH_ROUNDING argblock = push_block (GEN_INT (args_size.constant), 0, 0); #endif +#endif #ifdef PUSH_ARGS_REVERSED #ifdef STACK_BOUNDARY @@ -2426,19 +2550,131 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, argnum = 0; #endif +#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 (count = 0; count < reg_parm_stack_space + 1; count++) +#else + for (count = 0; count < reg_parm_stack_space; count++) +#endif + { + if (count >= highest_outgoing_arg_in_use + || stack_usage_map[count] == 0) + continue; + + if (low_to_save == -1) + low_to_save = count; + + high_to_save = count; + } + + 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); + } + } +#endif + /* Push the args that need to be pushed. */ + /* ARGNUM indexes the ARGVEC array in the order in which the arguments + are to be pushed. */ for (count = 0; count < nargs; count++, argnum += inc) { register enum machine_mode mode = argvec[argnum].mode; register rtx val = argvec[argnum].value; rtx reg = argvec[argnum].reg; int partial = argvec[argnum].partial; +#ifdef ACCUMULATE_OUTGOING_ARGS + int lower_bound, upper_bound, i; +#endif if (! (reg != 0 && partial == 0)) - emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, - argblock, GEN_INT (argvec[count].offset.constant)); - NO_DEFER_POP; + { +#ifdef ACCUMULATE_OUTGOING_ARGS + /* If this is being stored into a pre-allocated, fixed-size, stack + area, save any previous data at that location. */ + +#ifdef ARGS_GROW_DOWNWARD + /* stack_slot is negative, but we want to index stack_usage_map + with positive values. */ + upper_bound = -argvec[argnum].offset.constant + 1; + lower_bound = upper_bound - argvec[argnum].size.constant; +#else + lower_bound = argvec[argnum].offset.constant; + upper_bound = lower_bound + argvec[argnum].size.constant; +#endif + + for (i = lower_bound; i < upper_bound; i++) + if (stack_usage_map[i] + /* Don't store things in the fixed argument area at this point; + it has already been saved. */ + && i > reg_parm_stack_space) + break; + + if (i != upper_bound) + { + /* We need to make a save area. See what mode we can make it. */ + enum machine_mode save_mode + = mode_for_size (argvec[argnum].size.constant * BITS_PER_UNIT, + MODE_INT, 1); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, argvec[argnum].offset.constant))); + argvec[argnum].save_area = gen_reg_rtx (save_mode); + emit_move_insn (argvec[argnum].save_area, stack_area); + } +#endif + emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, + argblock, GEN_INT (argvec[argnum].offset.constant), + reg_parm_stack_space); + +#ifdef ACCUMULATE_OUTGOING_ARGS + /* Now mark the segment we just used. */ + for (i = lower_bound; i < upper_bound; i++) + stack_usage_map[i] = 1; +#endif + + NO_DEFER_POP; + } } #ifndef PUSH_ARGS_REVERSED @@ -2461,9 +2697,10 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, /* Now load any reg parms into their regs. */ + /* ARGNUM indexes the ARGVEC array in the order in which the arguments + are to be pushed. */ for (count = 0; count < nargs; count++, argnum += inc) { - register enum machine_mode mode = argvec[argnum].mode; register rtx val = argvec[argnum].value; rtx reg = argvec[argnum].reg; int partial = argvec[argnum].partial; @@ -2489,9 +2726,16 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which will set inhibit_defer_pop to that value. */ + /* The return type is needed to decide how many bytes the function pops. + Signedness plays no role in that, so for simplicity, we pretend it's + always signed. We also assume that the list of arguments passed has + no impact, so we pretend it is unknown. */ + emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), - get_identifier (XSTR (orgfun, 0)), args_size.constant, 0, + build_function_type (outmode == VOIDmode ? void_type_node + : type_for_mode (outmode, 0), NULL_TREE), + 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); @@ -2500,6 +2744,50 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, /* Now restore inhibit_defer_pop to its actual original value. */ OK_DEFER_POP; + +#ifdef ACCUMULATE_OUTGOING_ARGS +#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))); +#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 (count = 0; count < nargs; count++) + if (argvec[count].save_area) + { + enum machine_mode save_mode = GET_MODE (argvec[count].save_area); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, argvec[count].offset.constant))); + + emit_move_insn (stack_area, argvec[count].save_area); + } + + highest_outgoing_arg_in_use = initial_highest_arg_in_use; + stack_usage_map = initial_stack_usage_map; +#endif } /* Like emit_library_call except that an extra argument, VALUE, @@ -2533,16 +2821,39 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, rtx argblock = 0; CUMULATIVE_ARGS args_so_far; struct arg { rtx value; enum machine_mode mode; rtx reg; int partial; - struct args_size offset; struct args_size size; }; + struct args_size offset; struct args_size size; rtx save_area; }; struct arg *argvec; int old_inhibit_defer_pop = inhibit_defer_pop; rtx call_fusage = 0; rtx mem_value = 0; int pcc_struct_value = 0; int struct_value_size = 0; - /* library calls are never indirect calls. */ - int current_call_is_indirect = 0; int is_const; + int reg_parm_stack_space = 0; +#ifdef ACCUMULATE_OUTGOING_ARGS + int needed; +#endif + +#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE) + /* Define the boundary of the register parm stack space that needs to be + save, if any. */ + int low_to_save = -1, high_to_save; + rtx save_area = 0; /* Place that it is saved */ +#endif + +#ifdef ACCUMULATE_OUTGOING_ARGS + /* Size of the stack reserved for parameter registers. */ + int initial_highest_arg_in_use = highest_outgoing_arg_in_use; + char *initial_stack_usage_map = stack_usage_map; +#endif + +#ifdef REG_PARM_STACK_SPACE +#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); +#endif +#endif VA_START (p, nargs); @@ -2565,7 +2876,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, rtx pointer_reg = hard_function_value (build_pointer_type (type_for_mode (outmode, 0)), 0); - mem_value = gen_rtx (MEM, outmode, pointer_reg); + mem_value = gen_rtx_MEM (outmode, pointer_reg); pcc_struct_value = 1; if (value == 0) value = gen_reg_rtx (outmode); @@ -2591,8 +2902,9 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, library functions shouldn't have many args. */ argvec = (struct arg *) alloca ((nargs + 1) * sizeof (struct arg)); + bzero ((char *) argvec, (nargs + 1) * sizeof (struct arg)); - INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun); + INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0); args_size.constant = 0; args_size.var = 0; @@ -2630,13 +2942,10 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, if (argvec[count].reg == 0 || argvec[count].partial != 0 -#ifdef REG_PARM_STACK_SPACE - || 1 -#endif - ) + || reg_parm_stack_space > 0) args_size.constant += argvec[count].size.constant; - FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree)0, 1); + FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1); count++; } @@ -2683,7 +2992,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, argvec[count].mode = mode; argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); - if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) + if (argvec[count].reg && GET_CODE (argvec[count].reg) == PARALLEL) abort (); #ifdef FUNCTION_ARG_PARTIAL_NREGS argvec[count].partial @@ -2700,35 +3009,21 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, if (argvec[count].size.var) abort (); -#ifndef REG_PARM_STACK_SPACE - if (argvec[count].partial) + if (reg_parm_stack_space == 0 && argvec[count].partial) argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD; -#endif if (argvec[count].reg == 0 || argvec[count].partial != 0 -#ifdef REG_PARM_STACK_SPACE - || 1 -#endif - ) + || reg_parm_stack_space > 0) args_size.constant += argvec[count].size.constant; -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If this arg is actually passed on the stack, it might be - clobbering something we already put there (this library call might - be inside the evaluation of an argument to a function whose call - requires the stack). This will only occur when the library call - has sufficient args to run out of argument registers. Abort in - this case; if this ever occurs, code must be added to save and - restore the arg slot. */ - - if (argvec[count].reg == 0 || argvec[count].partial != 0) - abort (); -#endif - - FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1); + FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1); } va_end (p); +#ifdef FINAL_REG_PARM_STACK_SPACE + reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant, + args_size.var); +#endif /* If this machine requires an external definition for library functions, write one out. */ assemble_external_libcall (fun); @@ -2739,24 +3034,67 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, / STACK_BYTES) * STACK_BYTES); #endif -#ifdef REG_PARM_STACK_SPACE args_size.constant = MAX (args_size.constant, - REG_PARM_STACK_SPACE (NULL_TREE)); + reg_parm_stack_space); + #ifndef OUTGOING_REG_PARM_STACK_SPACE - args_size.constant -= REG_PARM_STACK_SPACE (NULL_TREE); -#endif + args_size.constant -= reg_parm_stack_space; #endif if (args_size.constant > current_function_outgoing_args_size) current_function_outgoing_args_size = args_size.constant; #ifdef ACCUMULATE_OUTGOING_ARGS - args_size.constant = 0; + /* Since the stack pointer will never be pushed, it is possible for + the evaluation of a parm to clobber something we have already + written to the stack. Since most function calls on RISC machines + do not use the stack, this is uncommon, but must work correctly. + + Therefore, we save any area of the stack that was already written + and that we are using. Here we set up to do this by making a new + stack usage map from the old one. + + Another approach might be to try to reorder the argument + evaluations to avoid this conflicting stack usage. */ + + needed = args_size.constant; + +#ifndef OUTGOING_REG_PARM_STACK_SPACE + /* Since we will be writing into the entire argument area, the + map must be allocated for its entire size, not just the part that + is the responsibility of the caller. */ + needed += reg_parm_stack_space; +#endif + +#ifdef ARGS_GROW_DOWNWARD + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed + 1); +#else + highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, + needed); #endif + stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); + if (initial_highest_arg_in_use) + bcopy (initial_stack_usage_map, stack_usage_map, + initial_highest_arg_in_use); + + if (initial_highest_arg_in_use != highest_outgoing_arg_in_use) + bzero (&stack_usage_map[initial_highest_arg_in_use], + highest_outgoing_arg_in_use - initial_highest_arg_in_use); + needed = 0; + + /* The address of the outgoing argument list must not be copied to a + register here, because argblock would be left pointing to the + wrong place after the call to allocate_dynamic_stack_space below. + */ + + argblock = virtual_outgoing_args_rtx; +#else /* not ACCUMULATE_OUTGOING_ARGS */ #ifndef PUSH_ROUNDING argblock = push_block (GEN_INT (args_size.constant), 0, 0); #endif +#endif #ifdef PUSH_ARGS_REVERSED #ifdef STACK_BOUNDARY @@ -2776,19 +3114,132 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, argnum = 0; #endif +#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 (count = 0; count < reg_parm_stack_space + 1; count++) +#else + for (count = 0; count < reg_parm_stack_space; count++) +#endif + { + if (count >= highest_outgoing_arg_in_use + || stack_usage_map[count] == 0) + continue; + + if (low_to_save == -1) + low_to_save = count; + + high_to_save = count; + } + + 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); + } + } +#endif + /* Push the args that need to be pushed. */ + /* ARGNUM indexes the ARGVEC array in the order in which the arguments + are to be pushed. */ for (count = 0; count < nargs; count++, argnum += inc) { register enum machine_mode mode = argvec[argnum].mode; register rtx val = argvec[argnum].value; rtx reg = argvec[argnum].reg; int partial = argvec[argnum].partial; +#ifdef ACCUMULATE_OUTGOING_ARGS + int lower_bound, upper_bound, i; +#endif if (! (reg != 0 && partial == 0)) - emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, - argblock, GEN_INT (argvec[count].offset.constant)); - NO_DEFER_POP; + { +#ifdef ACCUMULATE_OUTGOING_ARGS + /* If this is being stored into a pre-allocated, fixed-size, stack + area, save any previous data at that location. */ + +#ifdef ARGS_GROW_DOWNWARD + /* stack_slot is negative, but we want to index stack_usage_map + with positive values. */ + upper_bound = -argvec[argnum].offset.constant + 1; + lower_bound = upper_bound - argvec[argnum].size.constant; +#else + lower_bound = argvec[argnum].offset.constant; + upper_bound = lower_bound + argvec[argnum].size.constant; +#endif + + for (i = lower_bound; i < upper_bound; i++) + if (stack_usage_map[i] + /* Don't store things in the fixed argument area at this point; + it has already been saved. */ + && i > reg_parm_stack_space) + break; + + if (i != upper_bound) + { + /* We need to make a save area. See what mode we can make it. */ + enum machine_mode save_mode + = mode_for_size (argvec[argnum].size.constant * BITS_PER_UNIT, + MODE_INT, 1); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + argvec[argnum].offset.constant))); + argvec[argnum].save_area = gen_reg_rtx (save_mode); + emit_move_insn (argvec[argnum].save_area, stack_area); + } +#endif + emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, + argblock, GEN_INT (argvec[argnum].offset.constant), + reg_parm_stack_space); + +#ifdef ACCUMULATE_OUTGOING_ARGS + /* Now mark the segment we just used. */ + for (i = lower_bound; i < upper_bound; i++) + stack_usage_map[i] = 1; +#endif + + NO_DEFER_POP; + } } #ifndef PUSH_ARGS_REVERSED @@ -2811,9 +3262,10 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, /* Now load any reg parms into their regs. */ + /* ARGNUM indexes the ARGVEC array in the order in which the arguments + are to be pushed. */ for (count = 0; count < nargs; count++, argnum += inc) { - register enum machine_mode mode = argvec[argnum].mode; register rtx val = argvec[argnum].value; rtx reg = argvec[argnum].reg; int partial = argvec[argnum].partial; @@ -2851,14 +3303,15 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which will set inhibit_defer_pop to that value. */ + /* See the comment in emit_library_call about the function type we build + and pass here. */ emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), - get_identifier (XSTR (orgfun, 0)), args_size.constant, - struct_value_size, + build_function_type (type_for_mode (outmode, 0), NULL_TREE), + args_size.constant, struct_value_size, FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), - (outmode != VOIDmode && mem_value == 0 - ? hard_libcall_value (outmode) : NULL_RTX), + mem_value == 0 ? hard_libcall_value (outmode) : NULL_RTX, old_inhibit_defer_pop + 1, call_fusage, is_const); /* Now restore inhibit_defer_pop to its actual original value. */ @@ -2882,6 +3335,49 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, value = hard_libcall_value (outmode); } +#ifdef ACCUMULATE_OUTGOING_ARGS +#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))); +#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 (count = 0; count < nargs; count++) + if (argvec[count].save_area) + { + enum machine_mode save_mode = GET_MODE (argvec[count].save_area); + rtx stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, plus_constant (argblock, + argvec[count].offset.constant))); + + emit_move_insn (stack_area, argvec[count].save_area); + } + + highest_outgoing_arg_in_use = initial_highest_arg_in_use; + stack_usage_map = initial_stack_usage_map; +#endif + return value; } @@ -2915,11 +3411,11 @@ target_for_arg (type, size, args_addr, offset) { /* I have no idea how to guarantee that this will work in the presence of register parameters. */ - target = gen_rtx (PLUS, Pmode, args_addr, offset_rtx); + target = gen_rtx_PLUS (Pmode, args_addr, offset_rtx); target = memory_address (QImode, target); } - return gen_rtx (MEM, BLKmode, target); + return gen_rtx_MEM (BLKmode, target); } #endif @@ -2953,7 +3449,9 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, rtx reg = 0; int partial = 0; int used = 0; +#ifdef ACCUMULATE_OUTGOING_ARGS int i, lower_bound, upper_bound; +#endif if (TREE_CODE (pval) == ERROR_MARK) return; @@ -2968,12 +3466,12 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, if (argblock && ! variable_size && arg->stack) { #ifdef ARGS_GROW_DOWNWARD - /* stack_slot is negative, but we want to index stack_usage_map */ - /* with positive values. */ + /* stack_slot is negative, but we want to index stack_usage_map + with positive values. */ if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS) upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1; else - abort (); + upper_bound = 0; lower_bound = upper_bound - arg->size.constant; #else @@ -2987,12 +3485,9 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, for (i = lower_bound; i < upper_bound; i++) if (stack_usage_map[i] -#ifdef REG_PARM_STACK_SPACE /* Don't store things in the fixed argument area at this point; it has already been saved. */ - && i > reg_parm_stack_space -#endif - ) + && i > reg_parm_stack_space) break; if (i != upper_bound) @@ -3001,8 +3496,9 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, enum machine_mode save_mode = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1); rtx stack_area - = gen_rtx (MEM, save_mode, - memory_address (save_mode, XEXP (arg->stack_slot, 0))); + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + XEXP (arg->stack_slot, 0))); if (save_mode == BLKmode) { @@ -3034,19 +3530,11 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, this case. */ abort (); -#ifdef STRICT_ALIGNMENT /* If this arg needs special alignment, don't load the registers here. */ if (arg->n_aligned_regs != 0) reg = 0; -#endif - /* If this is being partially passed in a register, but multiple locations - are specified, we assume that the one partially used is the one that is - listed first. */ - if (reg && GET_CODE (reg) == EXPR_LIST) - reg = XEXP (reg, 0); - /* If this is being passed partially in a register, we can't evaluate it directly into its stack slot. Otherwise, we can. */ if (arg->value == 0) @@ -3098,8 +3586,21 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, do_pending_stack_adjust (); if (arg->value == arg->stack) - /* If the value is already in the stack slot, we are done. */ - ; + { + /* If the value is already in the stack slot, we are done. */ + if (flag_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)), + TYPE_MODE (sizetype), + GEN_INT (MEMORY_USE_RW), + TYPE_MODE (integer_type_node)); + } + } else if (arg->mode != BLKmode) { register int size; @@ -3132,9 +3633,9 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, /* This isn't already where we want it on the stack, so put it there. This can either be done with push or copy insns. */ - emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, - 0, partial, reg, used - size, - argblock, ARGS_SIZE_RTX (arg->offset)); + emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 0, + partial, reg, used - size, argblock, + ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space); } else { @@ -3166,7 +3667,8 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx, TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT, partial, - reg, excess, argblock, ARGS_SIZE_RTX (arg->offset)); + reg, excess, argblock, ARGS_SIZE_RTX (arg->offset), + reg_parm_stack_space); } diff --git a/contrib/gcc/cccp.1 b/contrib/gcc/cccp.1 index 8664c61..84eb19e 100644 --- a/contrib/gcc/cccp.1 +++ b/contrib/gcc/cccp.1 @@ -631,21 +631,14 @@ This option is available only when you call \c .B \-$ Forbid the use of `\|\c .B $\c -\&\|' in identifiers. This is required for ANSI -conformance. \c -.B gcc\c -\& automatically supplies this option to the -preprocessor if you specify `\|\c -.B \-ansi\c -\&\|', but \c +\&\|' in identifiers. This was formerly required for strict conformance +to the C Standard before the standard was corrected. \c + +This option is available only when you call \c +.B cpp\c +\& directly; .B gcc\c -\& doesn't -recognize the `\|\c -.B \-$\c -\&\|' option itself\(em\&to use it without the other -effects of `\|\c -.B \-ansi\c -\&\|', you must call the preprocessor directly. +\& will not pass it from its command line. .SH "SEE ALSO" .RB "`\|" Cpp "\|'" entry in diff --git a/contrib/gcc/cccp.c b/contrib/gcc/cccp.c index 39f1a5a..2e87c36 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, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc. Written by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 @@ -16,249 +16,77 @@ 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. +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! */ - -typedef unsigned char U_CHAR; - -#ifdef EMACS -#define NO_SHORTNAMES -#include "../src/config.h" -#ifdef open -#undef open -#undef read -#undef write -#endif /* open */ -#endif /* EMACS */ - -/* The macro EMACS is defined when cpp is distributed as part of Emacs, - for the sake of machines with limited C compilers. */ -#ifndef EMACS #include "config.h" -#endif /* not EMACS */ - -#ifndef STANDARD_INCLUDE_DIR -#define STANDARD_INCLUDE_DIR "/usr/include" -#endif - -#ifndef LOCAL_INCLUDE_DIR -#define LOCAL_INCLUDE_DIR "/usr/local/include" -#endif - -#if 0 /* We can't get ptrdiff_t, so I arranged not to need PTR_INT_TYPE. */ #ifdef __STDC__ -#define PTR_INT_TYPE ptrdiff_t +# include #else -#define PTR_INT_TYPE long +# include #endif -#endif /* 0 */ -#include "pcp.h" +#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n) -/* By default, colon separates directories in a path. */ -#ifndef PATH_SEPARATOR -#define PATH_SEPARATOR ':' -#endif +#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 +#include "system.h" #include -#include -#include #include -/* The following symbols should be autoconfigured: - HAVE_FCNTL_H - HAVE_STDLIB_H - HAVE_SYS_TIME_H - HAVE_UNISTD_H - STDC_HEADERS - TIME_WITH_SYS_TIME - In the mean time, we'll get by with approximations based - on existing GCC configuration symbols. */ - -#ifdef POSIX -# ifndef HAVE_STDLIB_H -# define HAVE_STDLIB_H 1 -# endif -# ifndef HAVE_UNISTD_H -# define HAVE_UNISTD_H 1 -# endif -# ifndef STDC_HEADERS -# define STDC_HEADERS 1 -# endif -#endif /* defined (POSIX) */ - -#if defined (POSIX) || (defined (USG) && !defined (VMS)) -# ifndef HAVE_FCNTL_H -# define HAVE_FCNTL_H 1 -# endif -#endif - -#ifndef RLIMIT_STACK -# include -#else -# if TIME_WITH_SYS_TIME -# include -# include -# else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -# endif +#ifdef HAVE_SYS_RESOURCE_H # include #endif -#if HAVE_FCNTL_H -# include -#endif +typedef unsigned char U_CHAR; -/* This defines "errno" properly for VMS, and gives us EACCES. */ -#include +#include "gansidecl.h" +#include "pcp.h" -#if HAVE_STDLIB_H -# include -#else -char *getenv (); +#ifndef GET_ENVIRONMENT +#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME) #endif -#if STDC_HEADERS -# include -# ifndef bcmp -# define bcmp(a, b, n) memcmp (a, b, n) -# endif -# ifndef bcopy -# define bcopy(s, d, n) memcpy (d, s, n) -# endif -# ifndef bzero -# define bzero(d, n) memset (d, 0, n) -# endif -#else /* !STDC_HEADERS */ -char *index (); -char *rindex (); - -# if !defined (BSTRING) && (defined (USG) || defined (VMS)) - -# ifndef bcmp -# define bcmp my_bcmp -static int -my_bcmp (a, b, n) - register char *a; - register char *b; - register unsigned n; -{ - while (n-- > 0) - if (*a++ != *b++) - return 1; - - return 0; -} -# endif /* !defined (bcmp) */ - -# ifndef bcopy -# define bcopy my_bcopy -static void -my_bcopy (s, d, n) - register char *s; - register char *d; - register unsigned n; -{ - while (n-- > 0) - *d++ = *s++; -} -# endif /* !defined (bcopy) */ - -# ifndef bzero -# define bzero my_bzero -static void -my_bzero (b, length) - register char *b; - register unsigned length; -{ - while (length-- > 0) - *b++ = 0; -} -# endif /* !defined (bzero) */ - -# endif /* !defined (BSTRING) && (defined (USG) || defined (VMS)) */ -#endif /* ! STDC_HEADERS */ - -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) -# define __attribute__(x) +#ifndef STANDARD_INCLUDE_DIR +# define STANDARD_INCLUDE_DIR "/usr/include" #endif -#ifndef PROTO -# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -# define PROTO(ARGS) ARGS -# else -# define PROTO(ARGS) () -# endif +/* By default, colon separates directories in a path. */ +#ifndef PATH_SEPARATOR +# define PATH_SEPARATOR ':' #endif -#if defined (__STDC__) && defined (HAVE_VPRINTF) -# include -# define VA_START(va_list, var) va_start (va_list, var) -# define PRINTF_ALIST(msg) char *msg, ... -# define PRINTF_DCL(msg) -# define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (printf, m, n))) +/* By default, the suffix for object files is ".o". */ +#ifdef OBJECT_SUFFIX +# define HAVE_OBJECT_SUFFIX #else -# include -# define VA_START(va_list, var) va_start (va_list) -# define PRINTF_ALIST(msg) msg, va_alist -# define PRINTF_DCL(msg) char *msg; va_dcl -# define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (printf, m, n))) -# define vfprintf(file, msg, args) \ - { \ - char *a0 = va_arg(args, char *); \ - char *a1 = va_arg(args, char *); \ - char *a2 = va_arg(args, char *); \ - char *a3 = va_arg(args, char *); \ - fprintf (file, msg, a0, a1, a2, a3); \ - } -#endif - -#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) - -#if HAVE_UNISTD_H -# include +# define OBJECT_SUFFIX ".o" #endif /* VMS-specific definitions */ #ifdef VMS #include -#define O_RDONLY 0 /* Open arg for Read/Only */ -#define O_WRONLY 1 /* Open arg for Write/Only */ -#define read(fd,buf,size) VMS_read (fd,buf,size) -#define write(fd,buf,size) VMS_write (fd,buf,size) +#include +#include #define open(fname,mode,prot) VMS_open (fname,mode,prot) #define fopen(fname,mode) VMS_fopen (fname,mode) #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile) -#define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt) #define fstat(fd,stbuf) VMS_fstat (fd,stbuf) static int VMS_fstat (), VMS_stat (); -static char * VMS_strncat (); -static int VMS_read (); -static int VMS_write (); static int VMS_open (); -static FILE * VMS_fopen (); -static FILE * VMS_freopen (); -static void hack_vms_include_specification (); -typedef struct { unsigned :16, :16, :16; } vms_ino_t; -#define ino_t vms_ino_t -#define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */ -#ifdef __GNUC__ -#define BSTRING /* VMS/GCC supplies the bstring routines */ -#endif /* __GNUC__ */ +static FILE *VMS_fopen (); +static FILE *VMS_freopen (); +static int hack_vms_include_specification (); +#define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a))) +#define INO_T_HASH(a) 0 +#define INCLUDE_LEN_FUDGE 12 /* leave room for VMS syntax conversion */ #endif /* VMS */ -#ifndef O_RDONLY -#define O_RDONLY 0 +/* Windows does not natively support inodes, and neither does MSDOS. */ +#if (defined (_WIN32) && ! defined (CYGWIN32)) || defined (__MSDOS__) +#define INO_T_EQ(a, b) 0 #endif #undef MIN @@ -266,18 +94,24 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t; #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 +/* 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 +# 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 @@ -288,22 +122,12 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t; #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif -/* Define a generic NULL if one hasn't already been defined. */ - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef GENERIC_PTR -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#define GENERIC_PTR void * -#else -#define GENERIC_PTR char * -#endif +#ifndef INO_T_EQ +#define INO_T_EQ(a, b) ((a) == (b)) #endif -#ifndef NULL_PTR -#define NULL_PTR ((GENERIC_PTR)0) +#ifndef INO_T_HASH +#define INO_T_HASH(a) (a) #endif #ifndef INCLUDE_LEN_FUDGE @@ -313,26 +137,9 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t; /* External declarations. */ extern char *version_string; -#ifndef VMS -#ifndef HAVE_STRERROR -extern int sys_nerr; -#if defined(bsd4_4) -extern const char *const sys_errlist[]; -#else -extern char *sys_errlist[]; -#endif -#else /* HAVE_STRERROR */ -char *strerror (); -#endif -#else /* VMS */ -char *strerror (int,...); -#endif -int parse_escape PROTO((char **)); -HOST_WIDE_INT parse_c_expression PROTO((char *)); - -#ifndef errno -extern int errno; -#endif +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)); /* Name under which this program was invoked. */ @@ -414,6 +221,10 @@ static enum {dump_none, dump_only, dump_names, dump_definitions} where they are defined. */ static int debug_output = 0; +/* Nonzero means pass #include lines through to the output, + even if they are ifdefed out. */ +static int dump_includes; + /* Nonzero indicates special processing used by the pcp program. The special effects of this mode are: @@ -429,7 +240,7 @@ static FILE *pcp_outfile; /* Nonzero means we are inside an IF during a -pcp run. In this mode macro expansion is done, and preconditions are output for all macro - uses requiring them. */ + uses requiring them. */ static int pcp_inside_if; /* Nonzero means never to include precompiled files. @@ -449,7 +260,8 @@ static int pedantic_errors; static int inhibit_warnings = 0; -/* Nonzero means warn if slash-star appears in a comment. */ +/* Nonzero means warn if slash-star appears in a slash-star comment, + or if newline-backslash appears in a slash-slash comment. */ static int warn_comments; @@ -462,6 +274,10 @@ static int warn_stringify; static int warn_trigraphs; +/* Nonzero means warn if undefined identifiers are evaluated in an #if. */ + +static int warn_undef; + /* Nonzero means warn if #import is used. */ static int warn_import = 1; @@ -474,12 +290,19 @@ static int warnings_are_errors; int traditional; +/* Nonzero for the 1989 C Standard, including corrigenda and amendments. */ + +int c89; + /* Nonzero causes output not to be done, but directives such as #define that have side effects are still obeyed. */ static int no_output; +/* Nonzero means we should look for header.gcc files that remap file names. */ +static int remap; + /* Nonzero means this file was included with a -imacros or -include command line and should not be recorded as an include file. */ @@ -505,6 +328,10 @@ static struct file_buf { char *fname; /* Filename specified with #line directive. */ char *nominal_fname; + /* The length of nominal_fname, which may contain embedded NULs. */ + size_t nominal_fname_len; + /* Include file description. */ + struct include_file *inc; /* Record where in the search path this file was found. For #include_next. */ struct file_name_list *dir; @@ -521,7 +348,7 @@ static struct file_buf { struct if_stack *if_stack; /* Object to be freed at end of input at this level. */ U_CHAR *free_ptr; - /* True if this is a header file included using . */ + /* True if this is a system header file; see is_system_include. */ char system_header_p; } instack[INPUT_STACK_MAX]; @@ -546,7 +373,7 @@ typedef struct file_buf FILE_BUF; /* The output buffer. Its LENGTH field is the amount of room allocated for the buffer, not the number of chars actually present. To get - that, subtract outbuf.buf from outbuf.bufp. */ + that, subtract outbuf.buf from outbuf.bufp. */ #define OUTBUF_SIZE 10 /* initial size of output buffer */ static FILE_BUF outbuf; @@ -561,25 +388,28 @@ static FILE_BUF outbuf; 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 + /* If the following is 1, 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; + /* The include directory status. */ + struct stat st; + /* The include prefix: "" denotes the working directory, + otherwise fname must end in '/'. + The actual size is dynamically allocated. */ + char fname[1]; }; -/* #include "file" looks in source file dir, then stack. */ -/* #include just looks in the stack. */ -/* -I directories are added to the end, then the defaults are added. */ +/* #include "file" looks in source file dir, then stack. */ +/* #include 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 @@ -590,33 +420,43 @@ static struct default_include { #else = { /* Pick up GNU C++ specific include files. */ - { GPLUSPLUS_INCLUDE_DIR, 1, 1 }, + { 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, 0, 0 }, + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, /* For cross-compilation, this dir name is generated automatically in Makefile.in. */ - { CROSS_INCLUDE_DIR, 0, 0 }, + { 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, 0, 0 }, + { TOOL_INCLUDE_DIR, "BINUTILS", 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, 1 }, + { 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, 0, 0 }, + { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 }, +#endif /* This is the dir for fixincludes. Put it just before the files that we fix. */ - { GCC_INCLUDE_DIR, 0, 0 }, + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, /* Some systems have an extra dir of include files. */ #ifdef SYSTEM_INCLUDE_DIR - { SYSTEM_INCLUDE_DIR, 0, 0 }, + { SYSTEM_INCLUDE_DIR, 0, 0, 0 }, #endif - { STANDARD_INCLUDE_DIR, 0, 0 }, +#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, 0, 0, 0 } }; #endif /* no INCLUDE_DEFAULTS */ @@ -643,18 +483,33 @@ static struct file_name_list *last_after_include = 0; /* Last in chain */ static struct file_name_list *before_system = 0; static struct file_name_list *last_before_system = 0; /* Last in chain */ -/* List of included files that contained #pragma once. */ -static struct file_name_list *dont_repeat_files = 0; - -/* 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. */ -static struct file_name_list *all_include_files = 0; - /* Directory prefix that should replace `/usr' in the standard include file directories. */ static char *include_prefix; +/* Maintain and search list of included files. */ + +struct include_file { + struct include_file *next; /* for include_hashtab */ + struct include_file *next_ino; /* for include_ino_hashtab */ + char *fname; + /* If the following is the empty string, it means #pragma once + was seen in this include file, or #import was applied to the file. + Otherwise, if it is nonzero, it is a macro name. + Don't include the file again if that macro is defined. */ + U_CHAR *control_macro; + /* Nonzero if the dependency on this include file has been output. */ + int deps_output; + struct stat st; +}; + +/* Hash tables of files already included with #include or #import. + include_hashtab is by full name; include_ino_hashtab is by inode number. */ + +#define INCLUDE_HASHSIZE 61 +static struct include_file *include_hashtab[INCLUDE_HASHSIZE]; +static struct include_file *include_ino_hashtab[INCLUDE_HASHSIZE]; + /* Global list of strings read in from precompiled files. This list is kept in the order the strings are read in, with new strings being added at the end through stringlist_tailp. We use this list to output @@ -702,7 +557,7 @@ enum sharp_token_type { #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and pattern list { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } - where (x, y) means (nchars, argno). */ + where (x, y) means (nchars, argno). */ typedef struct definition DEFINITION; struct definition { @@ -713,6 +568,7 @@ struct definition { U_CHAR *expansion; int line; /* Line number of definition */ char *file; /* File of definition */ + size_t file_len; /* Length of file (which can contain NULs) */ char rest_args; /* Nonzero if last arg. absorbs the rest */ struct reflist { struct reflist *next; @@ -736,7 +592,7 @@ struct definition { }; /* different kinds of things that can appear in the value field - of a hash node. Actually, this may be useless now. */ + of a hash node. Actually, this may be useless now. */ union hashval { char *cpval; DEFINITION *defn; @@ -763,7 +619,7 @@ static char rest_extension[] = "..."; plus some special tokens like __LINE__ (these each have their own type, and the appropriate code is run when that type of node is seen. It does not contain control words like "#define", which are recognized - by a separate piece of code. */ + by a separate piece of code. */ /* different flavors of hash nodes --- also used in keyword table */ enum node_type { @@ -812,7 +668,7 @@ struct hashnode { struct hashnode *prev; struct hashnode **bucket_hdr; /* 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. */ + of the chain and gets deleted. */ enum node_type type; /* type of special token */ int length; /* length of token, for quick comparison */ U_CHAR *name; /* the actual name */ @@ -826,7 +682,7 @@ typedef struct hashnode HASHNODE; loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to the hashf () function. Hashf () only exists for the sake of - politeness, for use when speed isn't so important. */ + politeness, for use when speed isn't so important. */ #define HASHSIZE 1403 static HASHNODE *hashtab[HASHSIZE]; @@ -900,7 +756,7 @@ struct assertion_hashnode { 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. */ + 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 */ @@ -915,7 +771,7 @@ typedef struct assertion_hashnode ASSERTION_HASHNODE; loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to the hashf function. hashf only exists for the sake of - politeness, for use when speed isn't so important. */ + politeness, for use when speed isn't so important. */ #define ASSERTION_HASHSIZE 37 static ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE]; @@ -932,12 +788,12 @@ struct directive { int length; /* Length of name */ int (*func) DO_PROTO; /* Function to handle directive */ char *name; /* Name of directive */ - enum node_type type; /* Code which describes which directive. */ - char angle_brackets; /* Nonzero => <...> is special. */ - char traditional_comments; /* Nonzero: keep comments if -traditional. */ - char pass_thru; /* Copy preprocessed directive to output file. */ + enum node_type type; /* Code which describes which directive. */ }; +#define IS_INCLUDE_DIRECTIVE_TYPE(t) \ +((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT) + /* These functions are declared to return int instead of void since they are going to be placed in the table and some old compilers have trouble with pointers to functions returning void. */ @@ -964,7 +820,7 @@ static int do_xifdef DO_PROTO; /* Here is the actual list of #-directives, most-often-used first. */ static struct directive directive_table[] = { - { 6, do_define, "define", T_DEFINE, 0, 1}, + { 6, do_define, "define", T_DEFINE}, { 2, do_if, "if", T_IF}, { 5, do_xifdef, "ifdef", T_IFDEF}, { 6, do_xifdef, "ifndef", T_IFNDEF}, @@ -972,16 +828,16 @@ static struct directive directive_table[] = { { 4, do_else, "else", T_ELSE}, { 4, do_elif, "elif", T_ELIF}, { 4, do_line, "line", T_LINE}, - { 7, do_include, "include", T_INCLUDE, 1}, - { 12, do_include, "include_next", T_INCLUDE_NEXT, 1}, - { 6, do_include, "import", T_IMPORT, 1}, + { 7, do_include, "include", T_INCLUDE}, + { 12, do_include, "include_next", T_INCLUDE_NEXT}, + { 6, do_include, "import", T_IMPORT}, { 5, do_undef, "undef", T_UNDEF}, { 5, do_error, "error", T_ERROR}, { 7, do_warning, "warning", T_WARNING}, #ifdef SCCS_DIRECTIVE { 4, do_sccs, "sccs", T_SCCS}, #endif - { 6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1}, + { 6, do_pragma, "pragma", T_PRAGMA}, { 5, do_ident, "ident", T_IDENT}, { 6, do_assert, "assert", T_ASSERT}, { 8, do_unassert, "unassert", T_UNASSERT}, @@ -992,14 +848,14 @@ static struct directive directive_table[] = { this points to the # (or the : of the %:) that started the directive. */ U_CHAR *directive_start; -/* table to tell if char can be part of a C identifier. */ +/* 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. */ +/* 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]; +static U_CHAR is_hor_space[256]; /* table to tell if c is horizontal or vertical space. */ -static U_CHAR is_space[256]; +U_CHAR is_space[256]; /* names of some characters */ static char *char_name[256]; @@ -1011,18 +867,6 @@ static int errors = 0; /* Error counter for exit code */ /* Name of output file, for error messages. */ static char *out_fname; -/* Zero means dollar signs are punctuation. - -$ stores 0; -traditional may store 1. Default is 1 for VMS, 0 otherwise. - This must be 0 for correct processing of this ANSI C program: - #define foo(a) #a - #define lose(b) foo (b) - #define test$ - lose (test) */ -static int dollars_in_ident; -#ifndef DOLLARS_IN_IDENTIFIERS -#define DOLLARS_IN_IDENTIFIERS 1 -#endif - /* Stack of conditionals currently in progress (including both successful and failing conditionals). */ @@ -1030,6 +874,7 @@ static int dollars_in_ident; struct if_stack { struct if_stack *next; /* for chaining to the next stack frame */ char *fname; /* copied from input when frame is made */ + size_t fname_len; /* similarly */ int lineno; /* similarly */ int if_succeeded; /* true if a leg of this if-group has been passed through rescan */ @@ -1058,6 +903,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)); int main PROTO((int, char **)); @@ -1081,22 +927,21 @@ static int handle_directive PROTO((FILE_BUF *, FILE_BUF *)); static struct tm *timestamp PROTO((void)); static void special_symbol PROTO((HASHNODE *, FILE_BUF *)); -static int redundant_include_p PROTO((char *)); static int is_system_include PROTO((char *)); -static char *skip_redundant_dir_prefix PROTO((char *)); +static char *base_name PROTO((char *)); +static int absolute_filename PROTO((char *)); +static size_t simplify_filename PROTO((char *)); static char *read_filename_string PROTO((int, FILE *)); static struct file_name_map *read_name_map PROTO((char *)); -static int open_include_file PROTO((char *, struct file_name_list *)); +static int open_include_file PROTO((char *, struct file_name_list *, U_CHAR *, struct include_file **)); +static char *remap_include_file PROTO((char *, struct file_name_list *)); +static int lookup_ino_include PROTO((struct include_file *)); -static void finclude PROTO((int, char *, FILE_BUF *, int, struct file_name_list *)); -static void record_control_macro PROTO((char *, U_CHAR *)); +static void finclude PROTO((int, struct include_file *, FILE_BUF *, int, struct file_name_list *)); +static void record_control_macro PROTO((struct include_file *, U_CHAR *)); -static int import_hash PROTO((char *)); -static int lookup_import PROTO((char *, struct file_name_list *)); -static void add_import PROTO((int, char *)); - -static char *check_precompiled PROTO((int, char *, 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 pcstring_used PROTO((HASHNODE *)); @@ -1126,11 +971,11 @@ static void do_once PROTO((void)); static HOST_WIDE_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 *)); +static void validate_else PROTO((U_CHAR *, U_CHAR *)); static U_CHAR *skip_to_end_of_comment PROTO((FILE_BUF *, int *, int)); static U_CHAR *skip_quoted_string PROTO((U_CHAR *, U_CHAR *, int, int *, int *, int *)); -static char *quote_string PROTO((char *, char *)); +static char *quote_string PROTO((char *, char *, size_t)); static U_CHAR *skip_paren_group PROTO((FILE_BUF *)); /* Last arg to output_line_directive. */ @@ -1142,13 +987,13 @@ static void macroexpand PROTO((HASHNODE *, FILE_BUF *)); struct argdata; static char *macarg PROTO((struct argdata *, int)); -static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, int *, int *, int *, int)); +static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int)); static int discard_comments PROTO((U_CHAR *, int, int)); static int change_newlines PROTO((U_CHAR *, int)); -char *my_strerror PROTO((int)); +static char *my_strerror PROTO((int)); void error PRINTF_PROTO_1((char *, ...)); static void verror PROTO((char *, va_list)); static void error_from_errno PROTO((char *)); @@ -1160,7 +1005,7 @@ 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_3((char *, int, char *, ...)); +static void pedwarn_with_file_and_line PRINTF_PROTO_4((char *, size_t, int, char *, ...)); static void print_containing_files PROTO((void)); @@ -1185,8 +1030,10 @@ static void make_undef PROTO((char *, FILE_BUF *)); static void make_assertion PROTO((char *, char *)); +static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, char *, char *, 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 void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn)); @@ -1200,11 +1047,11 @@ 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 int file_size_and_mode PROTO((int, int *, long int *)); +static void print_help PROTO((void)); /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME, - retrying if necessary. Return a negative value if an error occurs, + 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. */ @@ -1214,9 +1061,16 @@ safe_read (desc, ptr, len) char *ptr; int len; { - int left = len; + int left, rcount, nchars; + + left = len; while (left > 0) { - int nchars = read (desc, ptr, left); + 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 @@ -1234,7 +1088,8 @@ safe_read (desc, ptr, len) } /* Write LEN bytes at PTR to descriptor DESC, - retrying if necessary, and treating any real error as fatal. */ + retrying if necessary, and treating any real error as fatal. + If MAX_WRITE_LEN is defined, write at most that many bytes at a time. */ static void safe_write (desc, ptr, len) @@ -1242,8 +1097,15 @@ safe_write (desc, ptr, len) char *ptr; int len; { + int wcount, written; + while (len > 0) { - int written = write (desc, ptr, len); + wcount = len; +#ifdef MAX_WRITE_LEN + if (wcount > MAX_WRITE_LEN) + wcount = MAX_WRITE_LEN; +#endif + written = write (desc, ptr, wcount); if (written < 0) { #ifdef EINTR @@ -1256,14 +1118,108 @@ safe_write (desc, ptr, len) len -= written; } } + +/* Print a string to stderr, with extra handling in case it contains + embedded NUL characters. Any present are written as is. + + Using fwrite for this purpose produces undesireable results on VMS + when stderr happens to be a record oriented file, such as a batch log + file, rather than a stream oriented one. */ + +static void +eprint_string (string, length) + char *string; + size_t length; +{ + size_t segment_length; + + do { + fprintf(stderr, "%s", string); + length -= (segment_length = strlen(string)); + if (length > 0) + { + fputc('\0', stderr); + length -= 1; + /* Advance past the portion which has already been printed. */ + string += segment_length + 1; + } + } while (length > 0); +} + + +static void +print_help () +{ + printf ("Usage: %s [switches] input output\n", progname); + printf ("Switches:\n"); + printf (" -include Include the contents of before other files\n"); + printf (" -imacros Accept definition of marcos in \n"); + printf (" -iprefix Specify as a prefix for next two options\n"); + printf (" -iwithprefix Add to the end of the system include paths\n"); + printf (" -iwithprefixbefore Add to the end of the main include paths\n"); + printf (" -isystem Add to the start of the system include paths\n"); + printf (" -idirafter Add to the end of the system include paths\n"); + printf (" -I Add 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 Put output into \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 Define a with string '1' as its value\n"); + printf (" -D= Define a with as its value\n"); + printf (" -A () Assert the to \n"); + printf (" -U Undefine \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"); +} int main (argc, argv) int argc; char **argv; { - int st_mode; - long st_size; + struct stat st; char *in_fname; char *cp; int f, i; @@ -1298,42 +1254,31 @@ main (argc, argv) /* Target-name to write with the dependency information. */ char *deps_target = 0; -#ifdef RLIMIT_STACK +#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT) /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca (particularly stringtab - * in dbxread.c) does not fail. */ + in dbxread.c) does not fail. */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } -#endif /* RLIMIT_STACK defined */ +#endif #ifdef SIGPIPE signal (SIGPIPE, pipe_closed); #endif - cp = argv[0] + strlen (argv[0]); - while (cp != argv[0] && cp[-1] != '/' -#ifdef DIR_SEPARATOR - && cp[-1] != DIR_SEPARATOR -#endif - ) - --cp; - progname = cp; + progname = base_name (argv[0]); #ifdef VMS { - /* Remove directories from PROGNAME. */ + /* Remove extension from PROGNAME. */ char *p; - char *s = progname; + char *s = progname = savestring (progname); - if ((p = rindex (s, ':')) != 0) s = p + 1; /* skip device */ - if ((p = rindex (s, ']')) != 0) s = p + 1; /* skip directory */ - if ((p = rindex (s, '>')) != 0) s = p + 1; /* alternate (int'n'l) dir */ - s = progname = savestring (s); if ((p = rindex (s, ';')) != 0) *p = '\0'; /* strip version number */ if ((p = rindex (s, '.')) != 0 /* strip type iff ".exe" */ && (p[1] == 'e' || p[1] == 'E') @@ -1347,10 +1292,8 @@ main (argc, argv) in_fname = NULL; out_fname = NULL; - /* Initialize is_idchar to allow $. */ - dollars_in_ident = 1; + /* Initialize is_idchar. */ initialize_char_syntax (); - dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0; no_line_directives = 0; no_trigraphs = 1; @@ -1370,7 +1313,10 @@ main (argc, argv) for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { if (out_fname != NULL) - fatal ("Usage: %s [switches] input output", argv[0]); + { + print_help (); + fatal ("Too many arguments"); + } else if (in_fname != NULL) out_fname = argv[i]; else @@ -1380,16 +1326,20 @@ main (argc, argv) case 'i': if (!strcmp (argv[i], "-include")) { + int temp = i; + if (i + 1 == argc) fatal ("Filename missing after `-include' option"); else - pend_includes[i] = argv[i+1], i++; + simplify_filename (pend_includes[temp] = argv[++i]); } if (!strcmp (argv[i], "-imacros")) { + int temp = i; + if (i + 1 == argc) fatal ("Filename missing after `-imacros' option"); else - pend_files[i] = argv[i+1], i++; + simplify_filename (pend_files[temp] = argv[++i]); } if (!strcmp (argv[i], "-iprefix")) { if (i + 1 == argc) @@ -1403,17 +1353,10 @@ main (argc, argv) if (!strcmp (argv[i], "-isystem")) { struct file_name_list *dirtmp; - if (i + 1 == argc) - fatal ("Filename missing after `-isystem' option"); - - dirtmp = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - dirtmp->next = 0; - dirtmp->control_macro = 0; + if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, + "", argv[++i]))) + break; dirtmp->c_system_include_path = 1; - dirtmp->fname = xmalloc (strlen (argv[i+1]) + 1); - strcpy (dirtmp->fname, argv[++i]); - dirtmp->got_name_map = 0; if (before_system == 0) before_system = dirtmp; @@ -1436,18 +1379,9 @@ main (argc, argv) 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) - fatal ("Directory name missing after `-iwithprefix' option"); - - dirtmp->fname = xmalloc (strlen (argv[i+1]) + strlen (prefix) + 1); - strcpy (dirtmp->fname, prefix); - strcat (dirtmp->fname, argv[++i]); - dirtmp->got_name_map = 0; + if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, + prefix, argv[++i]))) + break; if (after_include == 0) after_include = dirtmp; @@ -1470,35 +1404,16 @@ main (argc, argv) 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) - fatal ("Directory name missing after `-iwithprefixbefore' option"); - - dirtmp->fname = xmalloc (strlen (argv[i+1]) + strlen (prefix) + 1); - strcpy (dirtmp->fname, prefix); - strcat (dirtmp->fname, argv[++i]); - dirtmp->got_name_map = 0; - + dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, prefix, argv[++i]); append_include_chain (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) - fatal ("Directory name missing after `-idirafter' option"); - else - dirtmp->fname = argv[++i]; - dirtmp->got_name_map = 0; + if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, + "", argv[++i]))) + break; if (after_include == 0) after_include = dirtmp; @@ -1529,10 +1444,10 @@ main (argc, argv) if (i + 1 == argc) fatal ("Filename missing after -pcp option"); pcp_fname = argv[++i]; - pcp_outfile = - ((pcp_fname[0] != '-' || pcp_fname[1] != '\0') - ? fopen (pcp_fname, "w") - : stdout); + pcp_outfile + = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0') + ? fopen (pcp_fname, "w") + : stdout); if (pcp_outfile == 0) pfatal_with_name (pcp_fname); no_precomp = 1; @@ -1543,8 +1458,6 @@ main (argc, argv) if (!strcmp (argv[i], "-traditional")) { traditional = 1; cplusplus_comments = 0; - if (dollars_in_ident > 0) - dollars_in_ident = 1; } else if (!strcmp (argv[i], "-trigraphs")) { no_trigraphs = 0; } @@ -1552,15 +1465,15 @@ main (argc, argv) case 'l': if (! strcmp (argv[i], "-lang-c")) - cplusplus = 0, cplusplus_comments = 1, objc = 0; + cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 0; if (! strcmp (argv[i], "-lang-c89")) - cplusplus = 0, cplusplus_comments = 0, objc = 0; + cplusplus = 0, cplusplus_comments = 0, c89 = 1, objc = 0; if (! strcmp (argv[i], "-lang-c++")) - cplusplus = 1, cplusplus_comments = 1, objc = 0; + cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 0; if (! strcmp (argv[i], "-lang-objc")) - objc = 1, cplusplus = 0, cplusplus_comments = 1; + cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 1; if (! strcmp (argv[i], "-lang-objc++")) - objc = 1, cplusplus = 1, cplusplus_comments = 1; + cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 1; if (! strcmp (argv[i], "-lang-asm")) lang_asm = 1; if (! strcmp (argv[i], "-lint")) @@ -1592,6 +1505,10 @@ main (argc, argv) warn_stringify = 1; else if (!strcmp (argv[i], "-Wno-traditional")) warn_stringify = 0; + else if (!strcmp (argv[i], "-Wundef")) + warn_undef = 1; + else if (!strcmp (argv[i], "-Wno-undef")) + warn_undef = 0; else if (!strcmp (argv[i], "-Wimport")) warn_import = 1; else if (!strcmp (argv[i], "-Wno-import")) @@ -1666,6 +1583,9 @@ main (argc, argv) case 'D': dump_macros = dump_definitions; break; + case 'I': + dump_includes = 1; + break; } } } @@ -1676,6 +1596,13 @@ main (argc, argv) debug_output = 1; break; + case '-': + if (strcmp (argv[i], "--help") != 0) + return i; + print_help (); + exit (0); + break; + case 'v': fprintf (stderr, "GNU CPP version %s", version_string); #ifdef TARGET_VERSION @@ -1746,7 +1673,7 @@ main (argc, argv) break; case '$': /* Don't include $ in identifiers. */ - dollars_in_ident = 0; + is_idchar['$'] = is_idstart['$'] = 0; break; case 'I': /* Add directory to path for includes. */ @@ -1759,18 +1686,8 @@ main (argc, argv) 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) - fatal ("Directory name missing after -I option"); - else - dirtmp->fname = argv[++i]; - dirtmp->got_name_map = 0; + dirtmp = new_include_prefix (last_include, NULL_PTR, "", + argv[i][2] ? argv[i] + 2 : argv[++i]); append_include_chain (dirtmp, dirtmp); } } @@ -1788,6 +1705,11 @@ main (argc, argv) no_precomp = 1; break; + case 'r': + if (!strcmp (argv[i], "-remap")) + remap = 1; + break; + case 'u': /* Sun compiler passes undocumented switch "-undef". Let's assume it means to inhibit the predefined symbols. */ @@ -1815,13 +1737,10 @@ 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. */ - cp = getenv ("CPATH"); + GET_ENVIRONMENT (cp, "CPATH"); if (cp && ! no_standard_includes) path_include (cp); - /* Now that dollars_in_ident is known, initialize is_idchar. */ - initialize_char_syntax (); - /* Initialize output buffer */ outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE); @@ -1835,6 +1754,7 @@ main (argc, argv) if (in_fname == NULL) in_fname = ""; fp->nominal_fname = fp->fname = in_fname; + fp->nominal_fname_len = strlen (in_fname); fp->lineno = 0; /* In C++, wchar_t is a distinct basic type, and we can expect @@ -1851,6 +1771,63 @@ main (argc, argv) 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; @@ -1938,28 +1915,27 @@ main (argc, argv) done_initializing = 1; - { /* read the appropriate environment variable and if it exists - replace include_defaults with the listed path. */ + { /* Read the appropriate environment variable and if it exists + replace include_defaults with the listed path. */ char *epath = 0; switch ((objc << 1) + cplusplus) { case 0: - epath = getenv ("C_INCLUDE_PATH"); + GET_ENVIRONMENT (epath, "C_INCLUDE_PATH"); break; case 1: - epath = getenv ("CPLUS_INCLUDE_PATH"); + GET_ENVIRONMENT (epath, "CPLUS_INCLUDE_PATH"); break; case 2: - epath = getenv ("OBJC_INCLUDE_PATH"); + GET_ENVIRONMENT (epath, "OBJC_INCLUDE_PATH"); break; case 3: - epath = getenv ("OBJCPLUS_INCLUDE_PATH"); + 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; @@ -1973,30 +1949,20 @@ main (argc, argv) startp = endp = epath; num_dirs = 0; while (1) { - /* Handle cases like c:/usr/lib:d:/gcc/lib */ - if ((*endp == PATH_SEPARATOR -#if 0 /* Obsolete, now that we use semicolons as the path separator. */ -#ifdef __MSDOS__ - && (endp-startp != 1 || !isalpha (*startp)) -#endif -#endif - ) - || *endp == 0) { - strncpy (nstore, startp, endp-startp); - if (endp == startp) - strcpy (nstore, "."); - else - nstore[endp-startp] = '\0'; - - include_defaults[num_dirs].fname = savestring (nstore); + char c = *endp++; + if (c == PATH_SEPARATOR || !c) { + endp[-1] = 0; + include_defaults[num_dirs].fname + = startp == endp ? "." : savestring (startp); + endp[-1] = c; + include_defaults[num_dirs].component = 0; include_defaults[num_dirs].cplusplus = cplusplus; include_defaults[num_dirs].cxx_aware = 1; num_dirs++; - if (*endp == '\0') + if (!c) break; - endp = startp = endp + 1; - } else - endp++; + startp = endp; + } } /* Put the usual defaults back in at the end. */ bcopy ((char *) include_defaults_array, @@ -2030,18 +1996,14 @@ main (argc, argv) 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 = 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 (new, new); - if (first_system_include == 0) - first_system_include = new; + = new_include_prefix (NULL_PTR, NULL_PTR, specd_prefix, + p->fname + default_len); + if (new) { + new->c_system_include_path = !p->cxx_aware; + append_include_chain (new, new); + if (first_system_include == 0) + first_system_include = new; + } } } } @@ -2050,14 +2012,13 @@ main (argc, argv) /* Some standard dirs are only for C++. */ if (!p->cplusplus || (cplusplus && !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 = p->fname; - new->got_name_map = 0; - append_include_chain (new, new); - if (first_system_include == 0) - first_system_include = new; + = new_include_prefix (NULL_PTR, p->component, "", p->fname); + if (new) { + new->c_system_include_path = !p->cxx_aware; + append_include_chain (new, new); + if (first_system_include == 0) + first_system_include = new; + } } } } @@ -2074,37 +2035,17 @@ main (argc, argv) for (p = include; p; p = p->next) { if (p == first_bracket_include) fprintf (stderr, "#include <...> search starts here:\n"); - fprintf (stderr, " %s\n", p->fname); + if (!p->fname[0]) + fprintf (stderr, " .\n"); + else if (!strcmp (p->fname, "/") || !strcmp (p->fname, "//")) + fprintf (stderr, " %s\n", p->fname); + else + /* Omit trailing '/'. */ + fprintf (stderr, " %.*s\n", (int) strlen (p->fname) - 1, 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. */ - - no_output++; no_record_file++; - for (i = 1; i < argc; i++) - if (pend_files[i]) { - int fd = open (pend_files[i], O_RDONLY, 0666); - if (fd < 0) { - perror_with_name (pend_files[i]); - return FATAL_EXIT_CODE; - } - finclude (fd, pend_files[i], &outbuf, 0, NULL_PTR); - } - no_output--; no_record_file--; - - /* Copy the entire contents of the main input file into - the stacked input buffer previously allocated for it. */ - - /* JF check for stdin */ - if (in_fname == NULL || *in_fname == 0) { - in_fname = ""; - f = 0; - } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0) - goto perror; - /* -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. */ @@ -2166,15 +2107,7 @@ main (argc, argv) char *p, *q; int len; - /* Discard all directory prefixes from filename. */ - if ((q = rindex (in_fname, '/')) != NULL -#ifdef DIR_SEPARATOR - && (q = rindex (in_fname, DIR_SEPARATOR)) != NULL -#endif - ) - ++q; - else - q = in_fname; + q = base_name (in_fname); /* Copy remainder to mungable area. */ p = (char *) alloca (strlen(q) + 8); @@ -2206,23 +2139,48 @@ main (argc, argv) q = p + (len - 4); /* Supply our own suffix. */ -#ifndef VMS - strcpy (q, ".o"); -#else - strcpy (q, ".obj"); -#endif + strcpy (q, OBJECT_SUFFIX); deps_output (p, ':'); deps_output (in_fname, ' '); } } - file_size_and_mode (f, &st_mode, &st_size); + /* Scan the -imacros files before the main input. + Much like #including them, but with no_output set + so that only their macro definitions matter. */ + + no_output++; no_record_file++; + for (i = 1; i < argc; i++) + if (pend_files[i]) { + struct include_file *inc; + int fd = open_include_file (pend_files[i], NULL_PTR, NULL_PTR, &inc); + if (fd < 0) { + perror_with_name (pend_files[i]); + return FATAL_EXIT_CODE; + } + finclude (fd, inc, &outbuf, 0, NULL_PTR); + } + no_output--; no_record_file--; + + /* Copy the entire contents of the main input file into + the stacked input buffer previously allocated for it. */ + + /* JF check for stdin */ + if (in_fname == NULL || *in_fname == 0) { + in_fname = ""; + f = 0; + } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0) + goto perror; + + if (fstat (f, &st) != 0) + pfatal_with_name (in_fname); fp->nominal_fname = fp->fname = in_fname; + fp->nominal_fname_len = strlen (in_fname); fp->lineno = 1; fp->system_header_p = 0; /* JF all this is mine about reading pipes and ttys */ - if (! S_ISREG (st_mode)) { + if (! S_ISREG (st.st_mode)) { /* Read input from a file that is not a normal disk file. We cannot preallocate a buffer with the correct size, so we must read in the file a piece at the time and make it bigger. */ @@ -2230,6 +2188,9 @@ main (argc, argv) int bsize; int cnt; + if (S_ISDIR (st.st_mode)) + fatal ("Input file `%s' is a directory", in_fname); + bsize = 2000; size = 0; fp->buf = (U_CHAR *) xmalloc (bsize + 2); @@ -2244,9 +2205,12 @@ main (argc, argv) fp->length = size; } else { /* Read a file whose size we can determine in advance. - For the sake of VMS, st_size is just an upper bound. */ - fp->buf = (U_CHAR *) xmalloc (st_size + 2); - fp->length = safe_read (f, (char *) fp->buf, st_size); + For the sake of VMS, st.st_size is just an upper bound. */ + size_t s = (size_t) st.st_size; + if (s != st.st_size || s + 2 < s) + memory_full (); + fp->buf = (U_CHAR *) xmalloc (s + 2); + fp->length = safe_read (f, (char *) fp->buf, s); if (fp->length < 0) goto perror; } fp->bufp = fp->buf; @@ -2281,12 +2245,13 @@ main (argc, argv) no_record_file++; for (i = 1; i < argc; i++) if (pend_includes[i]) { - int fd = open (pend_includes[i], O_RDONLY, 0666); + struct include_file *inc; + int fd = open_include_file (pend_includes[i], NULL_PTR, NULL_PTR, &inc); if (fd < 0) { perror_with_name (pend_includes[i]); return FATAL_EXIT_CODE; } - finclude (fd, pend_includes[i], &outbuf, 0, NULL_PTR); + finclude (fd, inc, &outbuf, 0, NULL_PTR); } no_record_file--; @@ -2353,38 +2318,23 @@ path_include (path) if (*p) while (1) { char *q = p; - char *name; + char c; 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 = xmalloc (2); - name[0] = '.'; - name[1] = 0; - } else { - /* Otherwise use the directory that is named. */ - name = xmalloc (q - p + 1); - bcopy (p, name, q - p); - name[q - p] = 0; - } + while ((c = *q++) != PATH_SEPARATOR && c) + continue; - 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; + q[-1] = 0; + dirtmp = new_include_prefix (last_include, NULL_PTR, + "", p == q ? "." : p); + q[-1] = c; append_include_chain (dirtmp, dirtmp); /* Advance past this name. */ p = q; - if (*p == 0) + if (! c) break; - /* Skip the colon. */ - p++; } } @@ -2423,7 +2373,7 @@ index0 (s, c, n) Using an extra pass through the buffer takes a little extra time, but is infinitely less hairy than trying to handle trigraphs inside strings, etc. everywhere, and also makes sure that trigraphs are - only translated in the top level of processing. */ + only translated in the top level of processing. */ static void trigraph_pcp (buf) @@ -2474,7 +2424,7 @@ trigraph_pcp (buf) len = sptr - fptr - 2; /* BSD doc says bcopy () works right for overlapping strings. In ANSI - C, this will be memmove (). */ + C, this will be memmove (). */ if (bptr != fptr && len > 0) bcopy ((char *) fptr, (char *) bptr, len); @@ -2488,7 +2438,8 @@ trigraph_pcp (buf) buf->length -= fptr - bptr; buf->buf[buf->length] = '\0'; if (warn_trigraphs && fptr != bptr) - warning_with_line (0, "%d trigraph(s) encountered", (fptr - bptr) / 2); + warning_with_line (0, "%lu trigraph(s) encountered", + (unsigned long) (fptr - bptr) / 2); } /* Move all backslash-newline pairs out of embarrassing places. @@ -2568,8 +2519,7 @@ name_newline_fix (bp) Upon return, any arg will be pointed to with argstart and will be arglen long. Note that we don't parse that arg since it will just - be printed out again. -*/ + be printed out again. */ static char * get_lintcmd (ibp, limit, argstart, arglen, cmdlen) @@ -2578,7 +2528,7 @@ get_lintcmd (ibp, limit, argstart, arglen, cmdlen) U_CHAR **argstart; /* point to command arg */ int *arglen, *cmdlen; /* how long they are */ { - long linsize; + HOST_WIDE_INT linsize; register U_CHAR *numptr; /* temp for arg parsing */ *arglen = 0; @@ -2605,10 +2555,10 @@ get_lintcmd (ibp, limit, argstart, arglen, cmdlen) if ((linsize >= 7) && !bcmp (ibp, "VARARGS", 7)) { *cmdlen = 7; ibp += 7; linsize -= 7; - if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS"; + if ((linsize == 0) || ! ISDIGIT (*ibp)) return "VARARGS"; /* OK, read a number */ - for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr); + for (numptr = *argstart = ibp; (numptr < limit) && ISDIGIT (*numptr); numptr++); *arglen = numptr - *argstart; return "VARARGS"; @@ -2773,7 +2723,7 @@ do { ip = &instack[indepth]; \ if (ident_length) goto specialchar; /* Copy #foo (bar lose) without macro expansion. */ - obp[-1] = '#'; /* In case it was '%'. */ + obp[-1] = '#'; /* In case it was '%'. */ SKIP_WHITE_SPACE (ibp); while (is_idchar[*ibp]) *obp++ = *ibp++; @@ -2900,9 +2850,14 @@ do { ip = &instack[indepth]; \ /* A single quoted string is treated like a double -- some programs (e.g., troff) are perverse this way */ - if (ident_length) - goto specialchar; - + /* Handle any pending identifier; + but the L in L'...' or L"..." is not an identifier. */ + if (ident_length) { + if (! (ident_length == 1 && hash == HASHSTEP (0, 'L'))) + goto specialchar; + ident_length = hash = 0; + } + start_line = ip->lineno; /* Skip ahead to a matching quote. */ @@ -2920,9 +2875,11 @@ do { ip = &instack[indepth]; \ if (!traditional) { error_with_line (line_for_error (start_line), "unterminated string or character constant"); - error_with_line (multiline_string_line, - "possible real start of unterminated constant"); - multiline_string_line = 0; + if (multiline_string_line) { + error_with_line (multiline_string_line, + "possible real start of unterminated constant"); + multiline_string_line = 0; + } } break; } @@ -2942,29 +2899,34 @@ do { ip = &instack[indepth]; \ "unterminated character constant"); goto while2end; } - if (pedantic && multiline_string_line == 0) { - pedwarn_with_line (line_for_error (start_line), - "string constant runs past end of line"); - } - if (multiline_string_line == 0) + if (multiline_string_line == 0) { + if (pedantic) + pedwarn_with_line (line_for_error (start_line), + "string constant runs past end of line"); multiline_string_line = ip->lineno - 1; + } break; case '\\': - if (ibp >= limit) - break; if (*ibp == '\n') { - /* Backslash newline is replaced by nothing at all, - but keep the line counts correct. */ - --obp; + /* Backslash newline is replaced by nothing at all, but + keep the line counts correct. But if we are reading + from a macro, keep the backslash newline, since backslash + newlines have already been processed. */ + if (ip->macro) + *obp++ = '\n'; + else + --obp; ++ibp; ++ip->lineno; } else { /* ANSI stupidly requires that in \\ the second \ is *not* prevented from combining with a newline. */ - while (*ibp == '\\' && ibp[1] == '\n') { - ibp += 2; - ++ip->lineno; + if (!ip->macro) { + while (*ibp == '\\' && ibp[1] == '\n') { + ibp += 2; + ++ip->lineno; + } } *obp++ = *ibp++; } @@ -2981,22 +2943,21 @@ do { ip = &instack[indepth]; \ break; case '/': + if (ip->macro != 0) + goto randomchar; if (*ibp == '\\' && ibp[1] == '\n') newline_fix (ibp); - if (*ibp != '*' && !(cplusplus_comments && *ibp == '/')) goto randomchar; - if (ip->macro != 0) - goto randomchar; if (ident_length) goto specialchar; if (*ibp == '/') { - /* C++ style comment... */ + /* C++ style comment... */ start_line = ip->lineno; - /* Comments are equivalent to spaces. */ + /* Comments are equivalent to spaces. */ if (! put_out_comments) obp[-1] = ' '; @@ -3012,6 +2973,8 @@ do { ip = &instack[indepth]; \ } 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 @@ -3029,7 +2992,7 @@ do { ip = &instack[indepth]; \ start_line = ip->lineno; - ++ibp; /* Skip the star. */ + ++ibp; /* Skip the star. */ /* If this cpp is for lint, we peek inside the comments: */ if (for_lint) { @@ -3080,18 +3043,17 @@ do { ip = &instack[indepth]; \ { U_CHAR *before_bp = ibp; - while (ibp < limit) { + for (;;) { switch (*ibp++) { - case '/': - if (warn_comments && *ibp == '*') - warning ("`/*' within comment"); - break; case '*': + if (ibp[-2] == '/' && warn_comments) + warning ("`/*' within comment"); if (*ibp == '\\' && ibp[1] == '\n') newline_fix (ibp); - if (ibp >= limit || *ibp == '/') + if (*ibp == '/') goto comment_end; break; + case '\n': ++ip->lineno; /* Copy the newline into the output buffer, in order to @@ -3100,26 +3062,32 @@ do { ip = &instack[indepth]; \ if (!put_out_comments) *obp++ = '\n'; ++op->lineno; + break; + + case 0: + if (limit < ibp) { + error_with_line (line_for_error (start_line), + "unterminated comment"); + goto limit_reached; + } + break; } } comment_end: - if (ibp >= limit) - error_with_line (line_for_error (start_line), - "unterminated comment"); - else { - ibp++; - if (put_out_comments) { - bcopy ((char *) before_bp, (char *) obp, ibp - before_bp); - obp += ibp - before_bp; - } + ibp++; + if (put_out_comments) { + bcopy ((char *) before_bp, (char *) obp, ibp - before_bp); + obp += ibp - before_bp; } } break; case '$': - if (!dollars_in_ident) + if (! is_idchar['$']) goto randomchar; + if (pedantic) + pedwarn ("`$' in identifier"); goto letter; case '0': case '1': case '2': case '3': case '4': @@ -3132,9 +3100,11 @@ do { ip = &instack[indepth]; \ if (ident_length == 0) { for (;;) { - while (ibp[0] == '\\' && ibp[1] == '\n') { - ++ip->lineno; - ibp += 2; + if (!ip->macro) { + while (ibp[0] == '\\' && ibp[1] == '\n') { + ++ip->lineno; + ibp += 2; + } } c = *ibp++; if (!is_idchar[c] && c != '.') { @@ -3143,16 +3113,19 @@ do { ip = &instack[indepth]; \ } *obp++ = c; /* A sign can be part of a preprocessing number - if it follows an e. */ - if (c == 'e' || c == 'E') { - while (ibp[0] == '\\' && ibp[1] == '\n') { - ++ip->lineno; - ibp += 2; + if it follows an `e' or `p'. */ + if (c == 'e' || c == 'E' || c == 'p' || c == 'P') { + if (!ip->macro) { + while (ibp[0] == '\\' && ibp[1] == '\n') { + ++ip->lineno; + ibp += 2; + } } if (*ibp == '+' || *ibp == '-') { *obp++ = *ibp++; - /* But traditional C does not let the token go past the sign. */ - if (traditional) + /* But traditional C does not let the token go past the sign, + and C89 does not allow `p'. */ + if (traditional || (c89 && (c == 'p' || c == 'P'))) break; } } @@ -3251,6 +3224,7 @@ do { ip = &instack[indepth]; \ /* Our input really contains a null character. */ goto randomchar; + limit_reached: /* At end of a macro-expansion level, pop it and read next level. */ if (ip->macro != 0) { obp--; @@ -3405,35 +3379,6 @@ randomchar: old_iln = ip->lineno; old_oln = op->lineno; } - /* A comment: copy it unchanged or discard it. */ - else if (*ibp == '/' && ibp[1] == '*') { - if (put_out_comments) { - *obp++ = '/'; - *obp++ = '*'; - } else if (! traditional) { - *obp++ = ' '; - } - ibp += 2; - while (ibp + 1 != limit - && !(ibp[0] == '*' && ibp[1] == '/')) { - /* We need not worry about newline-marks, - since they are never found in comments. */ - if (*ibp == '\n') { - /* Newline in a file. Count it. */ - ++ip->lineno; - ++op->lineno; - } - if (put_out_comments) - *obp++ = *ibp++; - else - ibp++; - } - ibp += 2; - if (put_out_comments) { - *obp++ = '*'; - *obp++ = '/'; - } - } else if (is_space[*ibp]) { *obp++ = *ibp++; if (ibp[-1] == '\n') { @@ -3460,6 +3405,59 @@ randomchar: } } } + else if (ip->macro) + break; + else if (*ibp == '/') { + /* If a comment, copy it unchanged or discard it. */ + if (ibp[1] == '\\' && ibp[2] == '\n') + newline_fix (ibp + 1); + if (ibp[1] == '*') { + if (put_out_comments) { + *obp++ = '/'; + *obp++ = '*'; + } else if (! traditional) { + *obp++ = ' '; + } + for (ibp += 2; ibp < limit; ibp++) { + /* We need not worry about newline-marks, + since they are never found in comments. */ + if (ibp[0] == '*') { + if (ibp[1] == '\\' && ibp[2] == '\n') + newline_fix (ibp + 1); + if (ibp[1] == '/') { + ibp += 2; + if (put_out_comments) { + *obp++ = '*'; + *obp++ = '/'; + } + break; + } + } + if (*ibp == '\n') { + /* Newline in a file. Count it. */ + ++ip->lineno; + ++op->lineno; + } + if (put_out_comments) + *obp++ = *ibp; + } + } else if (ibp[1] == '/' && cplusplus_comments) { + if (put_out_comments) { + *obp++ = '/'; + *obp++ = '/'; + } else if (! traditional) { + *obp++ = ' '; + } + for (ibp += 2; *ibp != '\n' || ibp[-1] == '\\'; ibp++) + if (put_out_comments) + *obp++ = *ibp; + } else + break; + } + else if (ibp[0] == '\\' && ibp[1] == '\n') { + ibp += 2; + ++ip->lineno; + } else break; } if (*ibp != '(') { @@ -3493,9 +3491,9 @@ randomchar: if (!traditional && obp != op->buf) { switch (obp[-1]) { case '!': case '%': case '&': case '*': - case '+': case '-': case '/': case ':': - case '<': case '=': case '>': case '^': - case '|': + case '+': case '-': case '.': case '/': + case ':': case '<': case '=': case '>': + case '^': case '|': /* If we are expanding a macro arg, make a newline marker to separate the tokens. If we are making real output, a plain space will do. */ @@ -3604,9 +3602,14 @@ expand_to_temp_buffer (buf, limit, output_marks, assertions) obuf.length = length * 2 + 100; /* Usually enough. Why be stingy? */ obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length); + obuf.nominal_fname = 0; + obuf.inc = 0; + obuf.dir = 0; obuf.fname = 0; obuf.macro = 0; + obuf.if_stack = 0; obuf.free_ptr = 0; + obuf.system_header_p = 0; CHECK_DEPTH ({return obuf;}); @@ -3615,6 +3618,8 @@ expand_to_temp_buffer (buf, limit, output_marks, assertions) ip = &instack[indepth]; ip->fname = 0; ip->nominal_fname = 0; + ip->nominal_fname_len = 0; + ip->inc = 0; ip->system_header_p = 0; ip->macro = 0; ip->free_ptr = 0; @@ -3680,8 +3685,11 @@ handle_directive (ip, op) if (*bp != ' ' && *bp != '\t' && pedantic) pedwarn ("%s in preprocessing directive", char_name[*bp]); bp++; - } else if (*bp == '/' && (bp[1] == '*' - || (cplusplus_comments && bp[1] == '/'))) { + } else if (*bp == '/') { + if (bp[1] == '\\' && bp[2] == '\n') + newline_fix (bp + 1); + if (! (bp[1] == '*' || (cplusplus_comments && bp[1] == '/'))) + break; ip->bufp = bp + 2; skip_to_end_of_comment (ip, &ip->lineno, 0); bp = ip->bufp; @@ -3773,7 +3781,7 @@ handle_directive (ip, op) limit = ip->buf + ip->length; unterminated = 0; already_output = 0; - keep_comments = traditional && kt->traditional_comments; + keep_comments = traditional && kt->type == T_DEFINE; /* #import is defined only in Objective C, or when on the NeXT. */ if (kt->type == T_IMPORT && !(objc || lookup ((U_CHAR *) "__NeXT__", -1, -1))) @@ -3799,8 +3807,25 @@ handle_directive (ip, op) } break; + case '"': + /* "..." is special for #include. */ + if (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) { + while (bp < limit && *bp != '\n') { + if (*bp == '"') { + bp++; + break; + } + if (*bp == '\\' && bp[1] == '\n') { + ip->lineno++; + copy_directive = 1; + bp++; + } + bp++; + } + break; + } + /* Fall through. */ case '\'': - case '\"': bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_directive, &unterminated); /* Don't bother calling the directive if we already got an error message due to unterminated string. Skip everything and pretend @@ -3818,7 +3843,7 @@ handle_directive (ip, op) /* <...> is special for #include. */ case '<': - if (!kt->angle_brackets) + if (! IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) break; while (bp < limit && *bp != '>' && *bp != '\n') { if (*bp == '\\' && bp[1] == '\n') { @@ -3841,9 +3866,14 @@ handle_directive (ip, op) bp = ip->bufp; /* No need to copy the directive because of a comment at the end; just don't include the comment in the directive. */ - if (bp == limit || *bp == '\n') { - bp = obp; - goto endloop1; + if (!put_out_comments) { + U_CHAR *p; + for (p = bp; *p == ' ' || *p == '\t'; p++) + continue; + if (*p == '\n') { + bp = obp; + goto endloop1; + } } /* Don't remove the comments if -traditional. */ if (! keep_comments) @@ -3872,9 +3902,12 @@ handle_directive (ip, op) RESUME_P is the next interesting data after the directive. A comment may come between. */ - /* If a directive should be copied through, and -E was given, + /* If a directive should be copied through, and -C was given, pass it through before removing comments. */ - if (!no_output && kt->pass_thru && put_out_comments) { + if (!no_output && put_out_comments + && (kt->type == T_DEFINE ? dump_macros == dump_definitions + : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes + : kt->type == T_PRAGMA)) { int len; /* Output directive name. */ @@ -3923,7 +3956,7 @@ handle_directive (ip, op) /* <...> is special for #include. */ case '<': - if (!kt->angle_brackets) + if (! IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) break; while (xp < bp && c != '>') { c = *xp++; @@ -3958,13 +3991,7 @@ handle_directive (ip, op) = skip_quoted_string (xp - 1, bp, ip->lineno, NULL_PTR, NULL_PTR, NULL_PTR); while (xp != bp1) - if (*xp == '\\') { - if (*++xp != '\n') - *cp++ = '\\'; - else - xp++; - } else - *cp++ = *xp++; + *cp++ = *xp++; } break; @@ -3998,13 +4025,12 @@ handle_directive (ip, op) /* Some directives should be written out for cc1 to process, just as if they were not defined. And sometimes we're copying - definitions through. */ + directives through. */ if (!no_output && already_output == 0 - && (kt->pass_thru - || (kt->type == T_DEFINE - && (dump_macros == dump_names - || dump_macros == dump_definitions)))) { + && (kt->type == T_DEFINE ? (int) dump_names <= (int) dump_macros + : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes + : kt->type == T_PRAGMA)) { int len; /* Output directive name. */ @@ -4013,13 +4039,8 @@ handle_directive (ip, op) bcopy (kt->name, (char *) op->bufp, kt->length); op->bufp += kt->length; - if (kt->pass_thru || dump_macros == dump_definitions) { - /* Output arguments. */ - len = (cp - buf); - check_expand (op, len); - bcopy (buf, (char *) op->bufp, len); - op->bufp += len; - } else if (kt->type == T_DEFINE && dump_macros == dump_names) { + if (kt->type == T_DEFINE && dump_macros == dump_names) { + /* Output `#define name' only. */ U_CHAR *xp = buf; U_CHAR *yp; SKIP_WHITE_SPACE (xp); @@ -4028,16 +4049,21 @@ handle_directive (ip, op) len = (xp - yp); check_expand (op, len + 1); *op->bufp++ = ' '; - bcopy (yp, op->bufp, len); - op->bufp += len; + bcopy (yp, (char *) op->bufp, len); + } else { + /* Output entire directive. */ + len = (cp - buf); + check_expand (op, len); + bcopy (buf, (char *) op->bufp, len); } + op->bufp += len; } /* Don't we need a newline or #line? */ /* Call the appropriate directive handler. buf now points to either the appropriate place in the input buffer, or to the temp buffer if it was necessary to make one. cp points to the first char after the contents of the (possibly - copied) directive, in either case. */ + copied) directive, in either case. */ (*kt->func) (buf, cp, op, kt); check_expand (op, ip->length - (ip->bufp - ip->buf)); @@ -4055,7 +4081,7 @@ timestamp () { static struct tm *timebuf; if (!timebuf) { - time_t t = time ((time_t *)0); + time_t t = time ((time_t *) 0); timebuf = localtime (&t); } return timebuf; @@ -4102,16 +4128,14 @@ special_symbol (hp, op) case T_FILE: case T_BASE_FILE: { - char *string; - if (hp->type == T_FILE) - string = ip->nominal_fname; - else - string = instack[0].nominal_fname; + FILE_BUF *p = hp->type == T_FILE ? ip : &instack[0]; + char *string = p->nominal_fname; if (string) { - buf = (char *) alloca (3 + 4 * strlen (string)); - quote_string (buf, string); + size_t string_len = p->nominal_fname_len; + buf = (char *) alloca (3 + 4 * string_len); + quote_string (buf, string, string_len); } else buf = "\"\""; @@ -4164,6 +4188,12 @@ special_symbol (hp, op) case T_CONST: buf = hp->value.cpval; +#ifdef STDC_0_IN_SYSTEM_HEADERS + if (ip->system_header_p + && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0 + && !lookup ((U_CHAR *) "__STRICT_ANSI__", -1, -1)) + buf = "0"; +#endif if (pcp_inside_if && pcp_outfile) /* Output a precondition for this macro use */ fprintf (pcp_outfile, "#define %s %s\n", hp->name, buf); @@ -4198,11 +4228,13 @@ special_symbol (hp, op) if (!is_idstart[*ip->bufp]) goto oops; + if (ip->bufp[0] == 'L' && (ip->bufp[1] == '\'' || ip->bufp[1] == '"')) + goto oops; if ((hp = lookup (ip->bufp, -1, -1))) { 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. */ + /* Output a precondition for this macro use. */ fprintf (pcp_outfile, "#define %s\n", hp->name); buf = " 1 "; } @@ -4254,29 +4286,41 @@ do_include (buf, limit, op, keyword) FILE_BUF *op; struct directive *keyword; { - int importing = (keyword->type == T_IMPORT); + U_CHAR *importing = keyword->type == T_IMPORT ? (U_CHAR *) "" : (U_CHAR *) 0; int skip_dirs = (keyword->type == T_INCLUDE_NEXT); static int import_warning = 0; char *fname; /* Dynamically allocated fname buffer */ char *pcftry; char *pcfname; - U_CHAR *fbeg, *fend; /* Beginning and end of fname */ + char *fbeg, *fend; /* Beginning and end of fname */ + U_CHAR *fin; struct file_name_list *search_start = include; /* Chain of dirs to search */ - struct file_name_list dsp[1]; /* First in chain, if #include "..." */ + struct file_name_list *dsp; /* First in chain, if #include "..." */ struct file_name_list *searchptr = 0; size_t flen; - int f; /* file number */ + int f = -3; /* file number */ + struct include_file *inc = 0; int retried = 0; /* Have already tried macro expanding the include line*/ int angle_brackets = 0; /* 0 for "...", 1 for <...> */ +#ifdef VMS + int vaxc_include = 0; /* 1 for token without punctuation */ +#endif int pcf = -1; char *pcfbuf; char *pcfbuflimit; int pcfnum; - f= -1; /* JF we iz paranoid! */ + + if (pedantic && !instack[indepth].system_header_p) + { + if (importing) + pedwarn ("ANSI C does not allow `#import'"); + if (skip_dirs) + pedwarn ("ANSI C does not allow `#include_next'"); + } if (importing && warn_import && !inhibit_warnings && !instack[indepth].system_header_p && !import_warning) { @@ -4296,25 +4340,28 @@ do_include (buf, limit, op, keyword) get_filename: - fbeg = buf; - SKIP_WHITE_SPACE (fbeg); + fin = buf; + SKIP_WHITE_SPACE (fin); /* Discard trailing whitespace so we can easily see if we have parsed all the significant chars we were given. */ - while (limit != fbeg && is_hor_space[limit[-1]]) limit--; + while (limit != fin && is_hor_space[limit[-1]]) limit--; + fbeg = fend = (char *) alloca (limit - fin); - switch (*fbeg++) { + switch (*fin++) { case '\"': { FILE_BUF *fp; /* Copy the operand text, concatenating the strings. */ { - U_CHAR *fin = fbeg; - fbeg = (U_CHAR *) alloca (limit - fbeg + 1); - fend = fbeg; - while (fin != limit) { - while (fin != limit && *fin != '\"') - *fend++ = *fin++; - fin++; + for (;;) { + for (;;) { + if (fin == limit) + goto invalid_include_file_name; + *fend = *fin++; + if (*fend == '"') + break; + fend++; + } if (fin == limit) break; /* If not at the end, there had better be another string. */ @@ -4326,48 +4373,46 @@ get_filename: goto fail; } } - *fend = 0; /* We have "filename". Figure out directory this source - file is coming from and put it on the front of the list. */ + file is coming from and put it on the front of the list. */ - /* If -I- was specified, don't search current dir, only spec'd ones. */ + /* If -I- was specified, don't search current dir, only spec'd ones. */ if (ignore_srcdir) break; for (fp = &instack[indepth]; fp >= instack; fp--) { int n; - char *ep,*nam; + char *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, '/'); -#ifdef DIR_SEPARATOR - if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR); - else { - char *tmp = rindex (nam, DIR_SEPARATOR); - if (tmp != NULL && tmp > ep) ep = tmp; - } + dsp = ((struct file_name_list *) + alloca (sizeof (struct file_name_list) + + fp->nominal_fname_len)); + strcpy (dsp->fname, nam); + simplify_filename (dsp->fname); + nam = base_name (dsp->fname); + *nam = 0; +#ifdef VMS + /* for hack_vms_include_specification(), a local + dir specification must start with "./" on VMS. */ + if (nam == dsp->fname) + { + *nam++ = '.'; + *nam++ = '/'; + *nam = 0; + } #endif -#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'; + /* But for efficiency's sake, do not insert the dir + if it matches the search list's first dir. */ + dsp->next = search_start; + if (!search_start || strcmp (dsp->fname, search_start->fname)) { + search_start = dsp; + n = nam - dsp->fname; if (n + INCLUDE_LEN_FUDGE > max_include_len) max_include_len = n + INCLUDE_LEN_FUDGE; - } else { - dsp[0].fname = 0; /* Current directory */ } dsp[0].got_name_map = 0; break; @@ -4377,13 +4422,12 @@ get_filename: } case '<': - fend = fbeg; - while (fend != limit && *fend != '>') fend++; - if (*fend == '>' && fend + 1 == limit) { + while (fin != limit && *fin != '>') + *fend++ = *fin++; + if (*fin == '>' && fin + 1 == limit) { angle_brackets = 1; /* If -I-, start with the first -I dir after the -I-. */ - if (first_bracket_include) - search_start = first_bracket_include; + search_start = first_bracket_include; break; } goto fail; @@ -4396,31 +4440,35 @@ get_filename: * code from case '<' is repeated here) and generates a warning. * (Note: macro expansion of `xyz' takes precedence.) */ - if (retried && isalpha(*(--fbeg))) { - fend = fbeg; - while (fend != limit && (!isspace(*fend))) fend++; + /* Note: The argument of ISALPHA() can be evaluated twice, so do + the pre-decrement outside of the macro. */ + if (retried && (--fin, ISALPHA(*(U_CHAR *) (fin)))) { + while (fin != limit && (!ISSPACE(*fin))) + *fend++ = *fin++; warning ("VAX-C-style include specification found, use '#include ' !"); - if (fend == limit) { + vaxc_include = 1; + if (fin == limit) { angle_brackets = 1; /* If -I-, start with the first -I dir after the -I-. */ - if (first_bracket_include) - search_start = first_bracket_include; + search_start = first_bracket_include; break; } } #endif fail: - if (retried) { - error ("`#%s' expects \"FILENAME\" or ", keyword->name); - return 0; - } else { + if (! retried) { /* Expand buffer and then remove any newline markers. We can't just tell expand_to_temp_buffer to omit the markers, since it would put extra spaces in include file names. */ FILE_BUF trybuf; U_CHAR *src; + int errors_before_expansion = errors; trybuf = expand_to_temp_buffer (buf, limit, 1, 0); + if (errors != errors_before_expansion) { + free (trybuf.buf); + goto invalid_include_file_name; + } src = trybuf.buf; buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1); limit = buf; @@ -4444,9 +4492,13 @@ get_filename: } *limit = 0; free (trybuf.buf); - retried++; + retried = 1; goto get_filename; } + + invalid_include_file_name: + error ("`#%s' expects \"FILENAME\" or ", keyword->name); + return 0; } /* For #include_next, skip in the search path @@ -4463,7 +4515,8 @@ get_filename: } } - flen = fend - fbeg; + *fend = 0; + flen = simplify_filename (fbeg); if (flen == 0) { @@ -4473,121 +4526,132 @@ get_filename: /* Allocate this permanently, because it gets stored in the definitions of macros. */ - fname = xmalloc (max_include_len + flen + 4); - /* + 2 above for slash and terminating null. */ - /* + 2 added for '.h' on VMS (to support '#include filename') */ + fname = xmalloc (max_include_len + flen + 1); + /* + 1 above for terminating null. */ + + system_include_depth += angle_brackets; /* If specified file name is absolute, just open it. */ - if (*fbeg == '/' -#ifdef DIR_SEPARATOR - || *fbeg == DIR_SEPARATOR -#endif - ) { - strncpy (fname, (char *) fbeg, flen); - fname[flen] = 0; - if (redundant_include_p (fname)) - return 0; - if (importing) - f = lookup_import (fname, NULL_PTR); - else - f = open_include_file (fname, NULL_PTR); - if (f == -2) - return 0; /* Already included this file */ + if (absolute_filename (fbeg)) { + strcpy (fname, fbeg); + f = open_include_file (fname, NULL_PTR, importing, &inc); } else { + + struct bypass_dir { + struct bypass_dir *next; + char *fname; + struct file_name_list *searchptr; + } **bypass_slot = 0; + /* 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, skip_redundant_dir_prefix (searchptr->fname)); - if (fname[0] && fname[strlen (fname) - 1] != '/') - strcat (fname, "/"); - } else { - fname[0] = 0; + + if (searchptr == first_bracket_include) { + /* Go to bypass directory if we know we've seen this file before. */ + static struct bypass_dir *bypass_hashtab[INCLUDE_HASHSIZE]; + struct bypass_dir *p; + bypass_slot = &bypass_hashtab[hashf ((U_CHAR *) fbeg, flen, + INCLUDE_HASHSIZE)]; + for (p = *bypass_slot; p; p = p->next) + if (!strcmp (fbeg, p->fname)) { + searchptr = p->searchptr; + bypass_slot = 0; + break; + } } - strncat (fname, (char *) 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"); + if (searchptr->fname[0]) + { + strcpy (fname, searchptr->fname); + if (fname[strlen (fname) - 1] == ':') + { + char *slashp; + slashp = strchr (fbeg, '/'); + + /* start at root-dir of logical device if no path given. */ + if (slashp == 0) + strcat (fname, "[000000]"); + } + strcat (fname, fbeg); + + /* Fix up the filename */ + hack_vms_include_specification (fname, vaxc_include); } - } -#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 (fname)) - return 0; - if (importing) - f = lookup_import (fname, searchptr); else - f = open_include_file (fname, searchptr); - if (f == -2) - return 0; /* Already included this file */ -#ifdef EACCES - else if (f == -1 && errno == EACCES) - warning ("Header file %s exists, but is not readable", fname); -#endif - if (f >= 0) + { + /* This is a normal VMS filespec, so use it unchanged. */ + strcpy (fname, fbeg); + /* if it's '#include filename', add the missing .h */ + if (vaxc_include && index(fname,'.')==NULL) + strcat (fname, ".h"); + } +#else + strcpy (fname, searchptr->fname); + strcat (fname, fbeg); +#endif /* VMS */ + f = open_include_file (fname, searchptr, importing, &inc); + if (f != -1) { + if (bypass_slot && searchptr != first_bracket_include) { + /* This is the first time we found this include file, + and we found it after first_bracket_include. + Record its location so that we can bypass to here next time. */ + struct bypass_dir *p + = (struct bypass_dir *) xmalloc (sizeof (struct bypass_dir)); + p->next = *bypass_slot; + p->fname = fname + strlen (searchptr->fname); + p->searchptr = searchptr; + *bypass_slot = p; + } + break; + } +#ifdef VMS + /* Our VMS hacks can produce invalid filespecs, so don't worry + about errors other than EACCES. */ + if (errno == EACCES) break; +#else + if (errno != ENOENT && errno != ENOTDIR) + break; +#endif } } + if (f < 0) { - /* A file that was not found. */ - strncpy (fname, (char *) fbeg, flen); - fname[flen] = 0; + if (f == -2) { + /* The file was already included. */ + /* 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 (print_deps_missing_files - && print_deps > (angle_brackets || (system_include_depth > 0))) + } else if (print_deps_missing_files + && (system_include_depth != 0) < print_deps) { /* If it was requested as a system header file, then assume it belongs in the first place to look for such. */ if (angle_brackets) { - 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, skip_redundant_dir_prefix (searchptr->fname)); - if (p[0] && p[strlen (p) - 1] != '/') - strcat (p, "/"); - strcat (p, fname); - deps_output (p, ' '); - break; - } - } + if (search_start) { + char *p = (char *) alloca (strlen (search_start->fname) + + strlen (fbeg) + 1); + strcpy (p, search_start->fname); + strcat (p, fbeg); + deps_output (p, ' '); + } } else { /* Otherwise, omit the directory, as if the file existed in the directory with the source. */ - deps_output (fname, ' '); + deps_output (fbeg, ' '); } } /* If -M was specified, and this header file won't be added to the @@ -4595,57 +4659,16 @@ get_filename: 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 (print_deps - && (print_deps <= (angle_brackets || (system_include_depth > 0)))) - warning ("No include path in which to find %s", fname); - else if (search_start) - error_from_errno (fname); + else if (0 < print_deps && print_deps <= (system_include_depth != 0)) + warning ("No include path in which to find %s", fbeg); + else if (f != -3) + error_from_errno (fbeg); else - error ("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; + error ("No include path in which to find %s", fbeg); - for (ptr = dont_repeat_files; ptr; ptr = ptr->next) { - if (!strcmp (ptr->fname, fname)) { - close (f); - return 0; /* This file was once'd. */ - } - } - - for (ptr = all_include_files; ptr; ptr = ptr->next) { - if (!strcmp (ptr->fname, fname)) - break; /* This file was included before. */ - } - - 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 = all_include_files; - all_include_files = ptr; - ptr->fname = savestring (fname); - ptr->got_name_map = 0; - - /* For -M, add this file to the dependencies. */ - if (print_deps > (angle_brackets || (system_include_depth > 0))) - deps_output (fname, ' '); - } - - /* Handle -H option. */ - if (print_include_names) - fprintf (stderr, "%*s%s\n", indepth, "", fname); - - if (angle_brackets) - system_include_depth++; + } else { /* Actually process the file. */ - add_import (f, fname); /* Record file on "seen" list for #import. */ pcftry = (char *) alloca (strlen (fname) + 30); pcfbuf = 0; @@ -4653,10 +4676,6 @@ get_filename: if (!no_precomp) { - struct stat stat_f; - - fstat (f, &stat_f); - do { sprintf (pcftry, "%s%d", fname, pcfnum++); @@ -4665,12 +4684,12 @@ get_filename: { 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) + if (fstat (pcf, &s) != 0) + pfatal_with_name (pcftry); + if (! INO_T_EQ (inc->st.st_ino, s.st_ino) + || inc->st.st_dev != s.st_dev) { - pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit); + pcfbuf = check_precompiled (pcf, &s, fname, &pcfbuflimit); /* Don't need it any more. */ close (pcf); } @@ -4692,28 +4711,11 @@ get_filename: (U_CHAR *) fname, op); } else - finclude (f, fname, op, is_system_include (fname), searchptr); - - if (angle_brackets) - system_include_depth--; + finclude (f, inc, op, is_system_include (fname), searchptr); } - return 0; -} -/* 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. */ + system_include_depth -= angle_brackets; -static int -redundant_include_p (name) - char *name; -{ - struct file_name_list *l = all_include_files; - for (; l; l = l->next) - if (! strcmp (name, l->fname) - && l->control_macro - && lookup (l->control_macro, -1, -1)) - return 1; return 0; } @@ -4736,38 +4738,127 @@ is_system_include (filename) for (searchptr = first_system_include; searchptr; searchptr = searchptr->next) - if (searchptr->fname) { - register char *sys_dir = skip_redundant_dir_prefix (searchptr->fname); - register unsigned length = strlen (sys_dir); + if (! strncmp (searchptr->fname, filename, strlen (searchptr->fname))) + return searchptr->c_system_include_path + 1; + return 0; +} + +/* Yield the non-directory suffix of a file name. */ - if (! strncmp (sys_dir, filename, length) - && (filename[length] == '/' +static char * +base_name (fname) + char *fname; +{ + char *s = fname; + char *p; +#if defined (__MSDOS__) || defined (_WIN32) + if (ISALPHA (s[0]) && s[1] == ':') s += 2; +#endif +#ifdef 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. */ + if (s != fname) + return s; +#endif + if ((p = rindex (s, '/'))) s = p + 1; #ifdef DIR_SEPARATOR - || filename[length] == DIR_SEPARATOR + if ((p = rindex (s, DIR_SEPARATOR))) s = p + 1; +#endif + return s; +} + +/* Yield nonzero if FILENAME is absolute (i.e. not relative). */ + +static int +absolute_filename (filename) + char *filename; +{ +#if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN32__)) + if (ISALPHA (filename[0]) && filename[1] == ':') filename += 2; +#endif +#if defined (__CYGWIN32__) + /* At present, any path that begins with a drive spec is absolute. */ + if (ISALPHA (filename[0]) && filename[1] == ':') return 1; +#endif +#ifdef VMS + if (index (filename, ':') != 0) return 1; +#endif + if (filename[0] == '/') return 1; +#ifdef DIR_SEPARATOR + if (filename[0] == DIR_SEPARATOR) return 1; #endif - )) { - if (searchptr->c_system_include_path) - return 2; - else - return 1; - } - } return 0; } - -/* Skip leading "./" from a directory name. - This may yield the empty string, which represents the current directory. */ -static char * -skip_redundant_dir_prefix (dir) - char *dir; +/* Remove unnecessary characters from FILENAME in place, + to avoid unnecessary filename aliasing. + Return the length of the resulting string. + + Do only the simplifications allowed by Posix. + It is OK to miss simplifications on non-Posix hosts, + since this merely leads to suboptimal results. */ + +static size_t +simplify_filename (filename) + char *filename; { - while (dir[0] == '.' && dir[1] == '/') - for (dir += 2; *dir == '/'; dir++) - continue; - if (dir[0] == '.' && !dir[1]) - dir++; - return dir; + register char *from = filename; + register char *to = 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++ = '/'; + } + } + } + to0 = to; + + for (;;) { +#ifndef VMS + 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; + } + } + } + + /* Skip /s after a /. */ + while (*from == '/') + from++; + } } /* The file_name_map structure holds a mapping of file names for a @@ -4819,7 +4910,9 @@ read_filename_string (ch, f) return alloc; } -/* Read the file name map file for DIRNAME. */ +/* Read the file name map file for DIRNAME. + If DIRNAME is empty, read the map file for the working directory; + otherwise DIRNAME must end in '/'. */ static struct file_name_map * read_name_map (dirname) @@ -4838,9 +4931,6 @@ read_name_map (dirname) char *name; FILE *f; size_t dirlen; - int separator_needed; - - dirname = skip_redundant_dir_prefix (dirname); for (map_list_ptr = map_list; map_list_ptr; map_list_ptr = map_list_ptr->map_list_next) @@ -4853,11 +4943,9 @@ read_name_map (dirname) map_list_ptr->map_list_map = NULL; dirlen = strlen (dirname); - separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/'; - name = (char *) alloca (dirlen + strlen (FILE_NAME_MAP_FILE) + 2); + name = (char *) alloca (dirlen + strlen (FILE_NAME_MAP_FILE) + 1); strcpy (name, dirname); - name[dirlen] = '/'; - strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE); + strcat (name, FILE_NAME_MAP_FILE); f = fopen (name, "r"); if (!f) map_list_ptr->map_list_map = NULL; @@ -4869,6 +4957,7 @@ read_name_map (dirname) { char *from, *to; struct file_name_map *ptr; + size_t tolen; if (is_space[ch]) continue; @@ -4877,19 +4966,21 @@ read_name_map (dirname) ; to = read_filename_string (ch, f); + simplify_filename (from); + tolen = simplify_filename (to); + ptr = ((struct file_name_map *) xmalloc (sizeof (struct file_name_map))); ptr->map_from = from; /* Make the real filename absolute. */ - if (*to == '/') + if (absolute_filename (to)) ptr->map_to = to; else { - ptr->map_to = xmalloc (dirlen + strlen (to) + 2); + ptr->map_to = xmalloc (dirlen + tolen + 1); strcpy (ptr->map_to, dirname); - ptr->map_to[dirlen] = '/'; - strcpy (ptr->map_to + dirlen + separator_needed, to); + strcat (ptr->map_to, to); free (to); } @@ -4910,85 +5001,162 @@ read_name_map (dirname) } /* 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 + being tried from the include file search path. + IMPORTING is "" if we are importing, null otherwise. + 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. + Unless unsuccessful, put a descriptor of the included file into *PINC. + This function maps filenames on file systems based on information read by read_name_map. */ static int -open_include_file (filename, searchptr) +open_include_file (filename, searchptr, importing, pinc) char *filename; struct file_name_list *searchptr; -{ - register struct file_name_map *map; - register char *from; - char *p, *dir; + U_CHAR *importing; + struct include_file **pinc; +{ + char *fname = remap ? remap_include_file (filename, searchptr) : filename; + int fd = -2; + + /* Look up FNAME in include_hashtab. */ + struct include_file **phead = &include_hashtab[hashf ((U_CHAR *) fname, + strlen (fname), + INCLUDE_HASHSIZE)]; + struct include_file *inc, *head = *phead; + for (inc = head; inc; inc = inc->next) + if (!strcmp (fname, inc->fname)) + break; - if (searchptr && ! searchptr->got_name_map) - { - searchptr->name_map = read_name_map (searchptr->fname - ? searchptr->fname : "."); - searchptr->got_name_map = 1; - } + if (!inc + || ! inc->control_macro + || (inc->control_macro[0] && ! lookup (inc->control_macro, -1, -1))) { - /* 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) - { - if (! strcmp (map->map_from, from)) - { - /* Found a match. */ - return open (map->map_to, O_RDONLY, 0666); - } - } - } + fd = open (fname, O_RDONLY, 0); - /* Try to find a mapping file for the particular directory we are - looking in. Thus #include 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, '/'); -#ifdef DIR_SEPARATOR - if (! p) p = rindex (filename, DIR_SEPARATOR); - else { - char *tmp = rindex (filename, DIR_SEPARATOR); - if (tmp != NULL && tmp > p) p = tmp; - } + if (fd < 0) + { +#ifdef VMS + /* if #include fails, try again with hacked spec. */ + if (!hack_vms_include_specification (fname, 0)) + return fd; + fd = open (fname, O_RDONLY, 0); + if (fd < 0) #endif - 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); - } + return fd; + } + + if (!inc) { + /* FNAME was not in include_hashtab; insert a new entry. */ + inc = (struct include_file *) xmalloc (sizeof (struct include_file)); + inc->next = head; + inc->fname = fname; + inc->control_macro = 0; + inc->deps_output = 0; + if (fstat (fd, &inc->st) != 0) + pfatal_with_name (fname); + *phead = inc; + + /* Look for another file with the same inode and device. */ + if (lookup_ino_include (inc) + && inc->control_macro + && (!inc->control_macro[0] || lookup (inc->control_macro, -1, -1))) { + close (fd); + fd = -2; + } + } + + /* For -M, add this file to the dependencies. */ + if (! inc->deps_output && (system_include_depth != 0) < print_deps) { + inc->deps_output = 1; + deps_output (fname, ' '); + } + + /* Handle -H option. */ + if (print_include_names) + fprintf (stderr, "%*s%s\n", indepth, "", fname); + } + + if (importing) + inc->control_macro = importing; + + *pinc = inc; + return fd; +} + +/* Return the remapped name of the include file FILENAME. + SEARCHPTR is the directory being tried from the include file path. */ + +static char * +remap_include_file (filename, searchptr) + char *filename; + struct file_name_list *searchptr; +{ + register struct file_name_map *map; + register char *from; - if (p == filename) + if (searchptr) { - dir = "."; - from = filename; + if (! searchptr->got_name_map) + { + searchptr->name_map = read_name_map (searchptr->fname); + searchptr->got_name_map = 1; + } + + /* Check the mapping for the directory we are using. */ + from = filename + strlen (searchptr->fname); + for (map = searchptr->name_map; map; map = map->map_next) + if (! strcmp (map->map_from, from)) + return map->map_to; } - else + + from = base_name (filename); + + if (from != filename || !searchptr) { - dir = (char *) alloca (p - filename + 1); - bcopy (filename, dir, p - filename); - dir[p - filename] = '\0'; - from = p + 1; + /* Try to find a mapping file for the particular directory we are + looking in. Thus #include will look up sys/types.h + in /usr/include/header.gcc and look up types.h in + /usr/include/sys/header.gcc. */ + + char *dir = (char *) alloca (from - filename + 1); + bcopy (filename, dir, from - filename); + dir[from - filename] = '\0'; + + for (map = read_name_map (dir); map; map = map->map_next) + if (! strcmp (map->map_from, from)) + return map->map_to; + } + + return filename; +} + +/* Insert INC into the include file table, hashed by device and inode number. + If a file with different name but same dev+ino was already in the table, + return 1 and set INC's control macro to the already-known macro. */ + +static int +lookup_ino_include (inc) + struct include_file *inc; +{ + int hash = ((unsigned) (inc->st.st_dev + INO_T_HASH (inc->st.st_ino)) + % INCLUDE_HASHSIZE); + struct include_file *i = include_ino_hashtab[hash]; + inc->next_ino = i; + include_ino_hashtab[hash] = inc; + + for (; i; i = i->next_ino) + if (INO_T_EQ (inc->st.st_ino, i->st.st_ino) + && inc->st.st_dev == i->st.st_dev) { + inc->control_macro = i->control_macro; + return 1; } - for (map = read_name_map (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); + return 0; } -/* Process the contents of include file FNAME, already open on descriptor F, +/* Process file descriptor F, which corresponds to include file INC, 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' @@ -4997,58 +5165,55 @@ open_include_file (filename, searchptr) or 0 if the file name was absolute. */ static void -finclude (f, fname, op, system_header_p, dirptr) +finclude (f, inc, op, system_header_p, dirptr) int f; - char *fname; + struct include_file *inc; FILE_BUF *op; int system_header_p; struct file_name_list *dirptr; { - int st_mode; - long st_size; - long i; + char *fname = inc->fname; + int i; FILE_BUF *fp; /* For input stack frame */ int missing_newline = 0; CHECK_DEPTH (return;); - if (file_size_and_mode (f, &st_mode, &st_size) < 0) - { - perror_with_name (fname); - close (f); - return; - } - fp = &instack[indepth + 1]; bzero ((char *) fp, sizeof (FILE_BUF)); fp->nominal_fname = fp->fname = fname; + fp->nominal_fname_len = strlen (fname); + fp->inc = inc; fp->length = 0; fp->lineno = 1; fp->if_stack = if_stack; fp->system_header_p = system_header_p; fp->dir = dirptr; - if (S_ISREG (st_mode)) { - fp->buf = (U_CHAR *) xmalloc (st_size + 2); + if (S_ISREG (inc->st.st_mode)) { + size_t s = (size_t) inc->st.st_size; + if (s != inc->st.st_size || s + 2 < s) + memory_full (); + fp->buf = (U_CHAR *) xmalloc (s + 2); fp->bufp = fp->buf; - /* Read the file contents, knowing that st_size is an upper bound + /* Read the file contents, knowing that s is an upper bound on the number of bytes we can read. */ - fp->length = safe_read (f, (char *) fp->buf, st_size); + fp->length = safe_read (f, (char *) fp->buf, s); if (fp->length < 0) goto nope; } - else if (S_ISDIR (st_mode)) { + else if (S_ISDIR (inc->st.st_mode)) { error ("directory `%s' specified in #include", fname); close (f); return; } else { /* Cannot count its file size before reading. First read the entire file into heap and - copy them into buffer on stack. */ + copy them into buffer on stack. */ int bsize = 2000; + int st_size = 0; - st_size = 0; fp->buf = (U_CHAR *) xmalloc (bsize + 2); for (;;) { @@ -5107,158 +5272,53 @@ finclude (f, fname, op, system_header_p, dirptr) free (fp->buf); } -/* Record that inclusion of the file named FILE +/* Record that inclusion of the include file INC should be controlled by the macro named MACRO_NAME. This means that trying to include the file again will do something if that macro is defined. */ static void -record_control_macro (file, macro_name) - char *file; +record_control_macro (inc, macro_name) + struct include_file *inc; U_CHAR *macro_name; { - struct file_name_list *new; - - for (new = all_include_files; new; new = new->next) { - if (!strcmp (new->fname, file)) { - new->control_macro = macro_name; - return; - } - } - - /* If the file is not in all_include_files, something's wrong. */ - abort (); -} - -/* 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; -}; - -/* Hash table of files already included with #include or #import. */ - -static struct import_file *import_hash_table[IMPORT_HASH_SIZE]; - -/* 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 (filename, searchptr) - 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 = 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 (filename, searchptr); - if (fd < 0) - return fd; - fstat (fd, &sb); - for (h = 0; h < IMPORT_HASH_SIZE; h++) { - i = 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 */ -} - -/* Add the file FNAME, open on descriptor FD, to import_hash_table. */ - -static void -add_import (fd, fname) - int fd; - char *fname; -{ - 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 = 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 = import_hash_table[hashval]; - import_hash_table[hashval] = i; + if (!inc->control_macro || inc->control_macro[0]) + inc->control_macro = macro_name; } /* Load the specified precompiled header into core, and verify its preconditions. PCF indicates the file descriptor to read, which must - be a regular file. FNAME indicates the file name of the original - header. *LIMIT will be set to an address one past the end of the file. + be a regular file. *ST is its file status. + FNAME indicates the file name of the original header. + *LIMIT will be set to an address one past the end of the file. If the preconditions of the file are not satisfied, the buffer is freed and we return 0. If the preconditions are satisfied, return the address of the buffer following the preconditions. The buffer, in this case, should never be freed because various pieces of it will be referred to until all precompiled strings are output at the end of - the run. -*/ + the run. */ + static char * -check_precompiled (pcf, fname, limit) +check_precompiled (pcf, st, fname, limit) int pcf; - char *fname; + struct stat *st; + char *fname ATTRIBUTE_UNUSED; char **limit; { - int st_mode; - long st_size; int length = 0; char *buf; char *cp; if (pcp_outfile) return 0; - - if (file_size_and_mode (pcf, &st_mode, &st_size) < 0) - return 0; - if (S_ISREG (st_mode)) + if (S_ISREG (st->st_mode)) { - buf = xmalloc (st_size + 2); - length = safe_read (pcf, buf, st_size); + size_t s = (size_t) st->st_size; + if (s != st->st_size || s + 2 < s) + memory_full (); + buf = xmalloc (s + 2); + length = safe_read (pcf, buf, s); if (length < 0) goto nope; } @@ -5271,7 +5331,7 @@ check_precompiled (pcf, fname, limit) *limit = buf + length; - /* File is in core. Check the preconditions. */ + /* File is in core. Check the preconditions. */ if (!check_preconditions (buf)) goto nope; for (cp = buf; *cp; cp++) @@ -5293,6 +5353,7 @@ check_precompiled (pcf, fname, limit) precompiled header. These are a series of #define and #undef lines which must match the current contents of the hash table. */ + static int check_preconditions (prec) char *prec; @@ -5351,7 +5412,8 @@ check_preconditions (prec) /* Process the main body of a precompiled file. BUF points to the string section of the file, following the preconditions. LIMIT is one character past the end. NAME is the name of the file being read - in. OP is the main output buffer */ + in. OP is the main output buffer. */ + static void pcfinclude (buf, limit, name, op) U_CHAR *buf, *limit, *name; @@ -5368,7 +5430,7 @@ pcfinclude (buf, limit, name, op) nstrings = (nstrings << 8) | *cp++; nstrings = (nstrings << 8) | *cp++; - /* Looping over each string... */ + /* Looping over each string... */ while (nstrings--) { U_CHAR *string_start; U_CHAR *endofthiskey; @@ -5380,14 +5442,14 @@ pcfinclude (buf, limit, name, op) /* First skip to a longword boundary */ /* ??? Why a 4-byte boundary? On all machines? */ - /* NOTE: This works correctly even if HOST_WIDE_INT + /* NOTE: This works correctly even if size_t is narrower than a pointer. Do not try risky measures here to get another type to use! Do not include stddef.h--it will fail! */ - if ((HOST_WIDE_INT) cp & 3) - cp += 4 - ((HOST_WIDE_INT) cp & 3); + if ((size_t) cp & 3) + cp += 4 - ((size_t) cp & 3); - /* Now get the string. */ + /* Now get the string. */ str = (STRINGDEF *) (GENERIC_PTR) cp; string_start = cp += sizeof (STRINGDEF); @@ -5397,7 +5459,7 @@ pcfinclude (buf, limit, name, op) /* We need to macro expand the string here to ensure that the proper definition environment is in place. If it were only expanded when we find out it is needed, macros necessary for - its proper expansion might have had their definitions changed. */ + its proper expansion might have had their definitions changed. */ tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0); /* Lineno is already set in the precompiled file */ str->contents = tmpbuf.buf; @@ -5410,14 +5472,14 @@ pcfinclude (buf, limit, name, op) *stringlist_tailp = str; stringlist_tailp = &str->chain; - /* Next comes a fourbyte number indicating the number of keys */ - /* for this string. */ + /* Next comes a fourbyte number indicating the number of keys + for this string. */ nkeys = *cp++; nkeys = (nkeys << 8) | *cp++; nkeys = (nkeys << 8) | *cp++; nkeys = (nkeys << 8) | *cp++; - /* If this number is -1, then the string is mandatory. */ + /* If this number is -1, then the string is mandatory. */ if (nkeys == -1) str->writeflag = 1; else @@ -5430,11 +5492,11 @@ pcfinclude (buf, limit, name, op) cp += sizeof (KEYDEF); /* Find the end of the key. At the end of this for loop we - advance CP to the start of the next key using this variable. */ + advance CP to the start of the next key using this variable. */ endofthiskey = cp + strlen ((char *) cp); kp->str = str; - /* Expand the key, and enter it into the hash table. */ + /* Expand the key, and enter it into the hash table. */ tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0); tmpbuf.bufp = tmpbuf.buf; @@ -5461,12 +5523,13 @@ pcfinclude (buf, limit, name, op) } /* This output_line_directive serves to switch us back to the current input file in case some of these strings get output (which will - result in line directives for the header file being output). */ + result in line directives for the header file being output). */ output_line_directive (&instack[indepth], op, 0, enter_file); } -/* Called from rescan when it hits a key for strings. Mark them all */ - /* used and clean up. */ +/* Called from rescan when it hits a key for strings. Mark them all + used and clean up. */ + static void pcstring_used (hp) HASHNODE *hp; @@ -5478,8 +5541,9 @@ pcstring_used (hp) delete_macro (hp); } -/* Write the output, interspersing precompiled strings in their */ - /* appropriate places. */ +/* Write the output, interspersing precompiled strings in their + appropriate places. */ + static void write_output () { @@ -5489,10 +5553,10 @@ write_output () char *line_directive = xmalloc (line_directive_len); int len; - /* In each run through the loop, either cur_buf_loc == */ - /* next_string_loc, in which case we print a series of strings, or */ - /* it is less than next_string_loc, in which case we write some of */ - /* the buffer. */ + /* In each run through the loop, either cur_buf_loc == + next_string_loc, in which case we print a series of strings, or + it is less than next_string_loc, in which case we write some of + the buffer. */ cur_buf_loc = outbuf.buf; next_string = stringlist; @@ -5506,7 +5570,8 @@ write_output () line_directive_len *= 2); sprintf (line_directive, "\n# %d ", next_string->lineno); strcpy (quote_string (line_directive + strlen (line_directive), - (char *) next_string->filename), + (char *) next_string->filename, + strlen ((char *) next_string->filename)), "\n"); safe_write (fileno (stdout), line_directive, strlen (line_directive)); safe_write (fileno (stdout), @@ -5565,7 +5630,7 @@ pass_thru_directive (buf, limit, op, keyword) 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. */ + hash table. */ struct arglist { struct arglist *next; @@ -5576,7 +5641,8 @@ struct arglist { }; /* Create a DEFINITION node from a #define directive. Arguments are - as for do_define. */ + as for do_define. */ + static MACRODEF create_definition (buf, limit, op) U_CHAR *buf, *limit; @@ -5587,6 +5653,7 @@ create_definition (buf, limit, op) int sym_length; /* and how long it is */ int line = instack[indepth].lineno; char *file = instack[indepth].nominal_fname; + size_t file_len = instack[indepth].nominal_fname_len; int rest_args = 0; DEFINITION *defn; @@ -5605,7 +5672,7 @@ create_definition (buf, limit, op) /* 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. */ + care of that. */ if (*bp == '(') { struct arglist *arg_ptrs = NULL; @@ -5636,8 +5703,10 @@ create_definition (buf, limit, op) while (is_idchar[*bp]) { bp++; /* do we have a "special" rest-args extension here? */ - if (limit - bp > REST_EXTENSION_LENGTH && - bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) { + if (limit - bp > 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"); rest_args = 1; temp->rest_args = 1; break; @@ -5669,8 +5738,8 @@ create_definition (buf, limit, op) struct arglist *otemp; for (otemp = temp->next; otemp != NULL; otemp = otemp->next) - if (temp->length == otemp->length && - bcmp (temp->name, otemp->name, temp->length) == 0) { + if (temp->length == otemp->length + && bcmp (temp->name, otemp->name, temp->length) == 0) { error ("duplicate argument name `%.*s' in `#define'", temp->length, temp->name); goto nope; @@ -5680,7 +5749,7 @@ create_definition (buf, limit, op) ++bp; /* skip paren */ SKIP_WHITE_SPACE (bp); - /* now everything from bp before limit is the definition. */ + /* now everything from bp before limit is the definition. */ defn = collect_expansion (bp, limit, argno, arg_ptrs); defn->rest_args = rest_args; @@ -5709,7 +5778,7 @@ create_definition (buf, limit, op) if (is_hor_space[*bp]) { bp++; SKIP_WHITE_SPACE (bp); - } else { + } else if (sym_length) { switch (*bp) { case '!': case '"': case '#': case '%': case '&': case '\'': case ')': case '*': case '+': case ',': case '-': case '.': @@ -5727,13 +5796,14 @@ create_definition (buf, limit, op) } } } - /* Now everything from bp before limit is the definition. */ + /* Now everything from bp before limit is the definition. */ defn = collect_expansion (bp, limit, -1, NULL_PTR); defn->args.argnames = (U_CHAR *) ""; } defn->line = line; defn->file = file; + defn->file_len = file_len; /* OP is null if this is a predefinition */ defn->predefined = !op; @@ -5794,7 +5864,9 @@ do_define (buf, limit, op, keyword) pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam); if (hp->type == T_MACRO) - pedwarn_with_file_and_line (hp->value.defn->file, hp->value.defn->line, + pedwarn_with_file_and_line (hp->value.defn->file, + hp->value.defn->file_len, + hp->value.defn->line, "this is the location of the previous definition"); } /* Replace the old definition. */ @@ -5831,7 +5903,8 @@ check_macro_name (symname, usage) for (p = symname; is_idchar[*p]; p++) ; sym_length = p - symname; - if (sym_length == 0) + if (sym_length == 0 + || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"'))) error ("invalid %s name", usage); else if (!is_idstart[*symname] || (sym_length == 7 && ! bcmp (symname, "defined", 7))) @@ -5839,9 +5912,8 @@ check_macro_name (symname, usage) return sym_length; } -/* - * return zero if two DEFINITIONs are isomorphic - */ +/* Return zero if two DEFINITIONs are isomorphic. */ + static int compare_defs (d1, d2) DEFINITION *d1, *d2; @@ -5853,7 +5925,8 @@ compare_defs (d1, d2) if (d1->nargs != d2->nargs) return 1; - if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames)) + if (pedantic + && 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) { @@ -5950,7 +6023,7 @@ collect_expansion (buf, end, nargs, arglist) /* 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. */ + that something smarter should happen. */ if (end < buf) abort (); @@ -6058,7 +6131,8 @@ collect_expansion (buf, end, nargs, arglist) p++; SKIP_WHITE_SPACE (p); } - if (! is_idstart[*p] || nargs == 0) + if (! is_idstart[*p] || nargs == 0 + || (*p == 'L' && (p[1] == '\'' || p[1] == '"'))) error ("`#' operator is not followed by a macro argument name"); else stringify = p; @@ -6067,7 +6141,7 @@ collect_expansion (buf, end, nargs, arglist) } } else { /* In -traditional mode, recognize arguments inside strings and - and character constants, and ignore special properties of #. + character constants, and ignore special properties of #. Arguments inside strings are considered "stringified", but no extra quote marks are supplied. */ switch (c) { @@ -6097,9 +6171,12 @@ collect_expansion (buf, end, nargs, arglist) this must be -traditional. So replace the comment with nothing at all. */ exp_p--; - p += 1; - while (p < limit && !(p[-2] == '*' && p[-1] == '/')) - p++; + while (++p < limit) { + if (p[0] == '*' && p[1] == '/') { + p += 2; + break; + } + } #if 0 /* Mark this as a concatenation-point, as if it had been ##. */ concat = p; @@ -6118,7 +6195,8 @@ collect_expansion (buf, end, nargs, arglist) while (p != limit && is_idchar[*p]) p++; id_len = p - id_beg; - if (is_idstart[c]) { + if (is_idstart[c] + && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) { register struct arglist *arg; for (arg = arglist; arg != NULL; arg = arg->next) { @@ -6220,8 +6298,8 @@ collect_expansion (buf, end, nargs, arglist) static int do_assert (buf, limit, op, keyword) U_CHAR *buf, *limit; - FILE_BUF *op; - struct directive *keyword; + FILE_BUF *op ATTRIBUTE_UNUSED; + struct directive *keyword ATTRIBUTE_UNUSED; { U_CHAR *bp; /* temp ptr into input buffer */ U_CHAR *symname; /* remember where symbol name starts */ @@ -6244,7 +6322,7 @@ do_assert (buf, limit, op, keyword) /* Lossage will occur if identifiers or control tokens are broken across lines using backslash. This is not the right place to take - care of that. */ + care of that. */ if (*bp != '(') { error ("missing token-sequence in `#assert'"); @@ -6297,8 +6375,8 @@ do_assert (buf, limit, op, keyword) static int do_unassert (buf, limit, op, keyword) U_CHAR *buf, *limit; - FILE_BUF *op; - struct directive *keyword; + FILE_BUF *op ATTRIBUTE_UNUSED; + struct directive *keyword ATTRIBUTE_UNUSED; { U_CHAR *bp; /* temp ptr into input buffer */ U_CHAR *symname; /* remember where symbol name starts */ @@ -6323,7 +6401,7 @@ do_unassert (buf, limit, op, keyword) /* Lossage will occur if identifiers or control tokens are broken across lines using backslash. This is not the right place to take - care of that. */ + care of that. */ if (*bp == '(') { int error_flag = 0; @@ -6537,15 +6615,14 @@ free_token_list (tokens) } } -/* - * 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. - */ +/* 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. */ + static ASSERTION_HASHNODE * assertion_install (name, len, hash) U_CHAR *name; @@ -6576,16 +6653,15 @@ assertion_install (name, len, hash) 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. - */ +/* 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. */ + static ASSERTION_HASHNODE * assertion_lookup (name, len, hash) U_CHAR *name; @@ -6613,8 +6689,8 @@ delete_assertion (hp) if (hp->next != NULL) hp->next->prev = hp->prev; - /* make sure that the bucket chain header that - the deleted guy was on points to the right thing afterwards. */ + /* 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; @@ -6631,7 +6707,7 @@ static int do_line (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; - struct directive *keyword; + struct directive *keyword ATTRIBUTE_UNUSED; { register U_CHAR *bp; FILE_BUF *ip = &instack[indepth]; @@ -6646,7 +6722,7 @@ do_line (buf, limit, op, keyword) bp = tem.buf; SKIP_WHITE_SPACE (bp); - if (!isdigit (*bp)) { + if (!ISDIGIT (*bp)) { error ("invalid format `#line' directive"); return 0; } @@ -6661,7 +6737,7 @@ do_line (buf, limit, op, keyword) pedwarn ("line number out of range in `#line' directive"); /* skip over the line number. */ - while (isdigit (*bp)) + while (ISDIGIT (*bp)) bp++; #if 0 /* #line 10"foo.c" is supposed to be allowed. */ @@ -6693,7 +6769,7 @@ do_line (buf, limit, op, keyword) case '\\': { char *bpc = (char *) bp; - int c = parse_escape (&bpc); + HOST_WIDE_INT c = parse_escape (&bpc, (HOST_WIDE_INT) (U_CHAR) (-1)); bp = (U_CHAR *) bpc; if (c < 0) p--; @@ -6703,7 +6779,7 @@ do_line (buf, limit, op, keyword) break; case '\"': - p[-1] = 0; + *--p = 0; goto fname_done; } fname_done: @@ -6744,12 +6820,12 @@ do_line (buf, limit, op, keyword) } } - hash_bucket = - &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)]; + hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)]; for (hp = *hash_bucket; hp != NULL; hp = hp->next) if (hp->length == fname_length && bcmp (hp->value.cpval, fname, fname_length) == 0) { ip->nominal_fname = hp->value.cpval; + ip->nominal_fname_len = fname_length; break; } if (hp == 0) { @@ -6758,9 +6834,9 @@ do_line (buf, limit, op, keyword) 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); + ip->nominal_fname_len = hp->length = fname_length; + bcopy (fname, hp->value.cpval, fname_length + 1); } } else if (*bp) { error ("invalid format `#line' directive"); @@ -6773,11 +6849,9 @@ do_line (buf, limit, op, keyword) 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 un*x /lib/cpp, it is not an error to undef + something that has no definitions, so it isn't one here either. */ static int do_undef (buf, limit, op, keyword) @@ -6815,20 +6889,18 @@ do_undef (buf, limit, op, keyword) return 0; } -/* - * Report an error detected by the program we are processing. - * Use the text of the line in the error message. - * (We use error because it prints the filename & line#.) - */ +/* Report an error detected by the program we are processing. + Use the text of the line in the error message. + (We use error because it prints the filename & line#.) */ static int do_error (buf, limit, op, keyword) U_CHAR *buf, *limit; - FILE_BUF *op; - struct directive *keyword; + FILE_BUF *op ATTRIBUTE_UNUSED; + struct directive *keyword ATTRIBUTE_UNUSED; { int length = limit - buf; - U_CHAR *copy = (U_CHAR *) xmalloc (length + 1); + U_CHAR *copy = (U_CHAR *) alloca (length + 1); bcopy ((char *) buf, (char *) copy, length); copy[length] = 0; SKIP_WHITE_SPACE (copy); @@ -6836,24 +6908,28 @@ do_error (buf, limit, op, keyword) 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#.) - */ +/* 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 (buf, limit, op, keyword) U_CHAR *buf, *limit; - FILE_BUF *op; - struct directive *keyword; + FILE_BUF *op ATTRIBUTE_UNUSED; + struct directive *keyword ATTRIBUTE_UNUSED; { int length = limit - buf; - U_CHAR *copy = (U_CHAR *) xmalloc (length + 1); + U_CHAR *copy = (U_CHAR *) alloca (length + 1); bcopy ((char *) buf, (char *) copy, length); copy[length] = 0; SKIP_WHITE_SPACE (copy); - warning ("#warning %s", copy); + + if (pedantic && !instack[indepth].system_header_p) + pedwarn ("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. */ + pedwarn ("#warning %s", copy); return 0; } @@ -6864,34 +6940,21 @@ static void do_once () { int i; - FILE_BUF *ip = NULL; for (i = indepth; i >= 0; i--) - if (instack[i].fname != NULL) { - ip = &instack[i]; + if (instack[i].inc) { + record_control_macro (instack[i].inc, (U_CHAR *) ""); break; } - - if (ip != NULL) { - struct file_name_list *new; - - new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); - new->next = dont_repeat_files; - dont_repeat_files = new; - new->fname = savestring (ip->fname); - new->control_macro = 0; - new->got_name_map = 0; - new->c_system_include_path = 0; - } } -/* #ident has already been copied to the output file, so just ignore it. */ +/* Report program identification. */ static int do_ident (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; - struct directive *keyword; + struct directive *keyword ATTRIBUTE_UNUSED; { FILE_BUF trybuf; int len; @@ -6901,22 +6964,17 @@ do_ident (buf, limit, op, keyword) pedwarn ("ANSI C does not allow `#ident'"); trybuf = expand_to_temp_buffer (buf, limit, 0, 0); - buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1); - bcopy ((char *) trybuf.buf, (char *) buf, trybuf.bufp - trybuf.buf); - limit = buf + (trybuf.bufp - trybuf.buf); - len = (limit - buf); - free (trybuf.buf); - - /* Output directive name. */ - check_expand (op, 7); + buf = trybuf.buf; + len = trybuf.bufp - buf; + + /* Output expanded directive. */ + check_expand (op, 7 + len); bcopy ("#ident ", (char *) op->bufp, 7); op->bufp += 7; - - /* Output the expanded argument line. */ - check_expand (op, len); bcopy ((char *) buf, (char *) op->bufp, len); op->bufp += len; + free (buf); return 0; } @@ -6925,9 +6983,9 @@ do_ident (buf, limit, op, keyword) static int do_pragma (buf, limit, op, keyword) - U_CHAR *buf, *limit; - FILE_BUF *op; - struct directive *keyword; + U_CHAR *buf, *limit ATTRIBUTE_UNUSED; + FILE_BUF *op ATTRIBUTE_UNUSED; + struct directive *keyword ATTRIBUTE_UNUSED; { SKIP_WHITE_SPACE (buf); if (!strncmp ((char *) buf, "once", 4)) { @@ -6941,25 +6999,27 @@ do_pragma (buf, limit, op, keyword) if (!strncmp ((char *) 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 h; + U_CHAR *p = buf + 14, *fname; SKIP_WHITE_SPACE (p); - if (*p == '\n' || *p != '\"') + if (*p != '\"') return 0; fname = p + 1; if ((p = (U_CHAR *) index ((char *) fname, '\"'))) *p = '\0'; - for (ptr = 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 && !strcmp ((char *) inc_fname, (char *) fname)) - warning ("`#pragma implementation' for `%s' appears after file is included", - fname); + for (h = 0; h < INCLUDE_HASHSIZE; h++) { + struct include_file *inc; + for (inc = include_hashtab[h]; inc; inc = inc->next) { + if (!strcmp (base_name (inc->fname), (char *) fname)) { + warning ("`#pragma implementation' for \"%s\" appears after its #include",fname); + return 0; + } + } } } - return 0; } @@ -6967,10 +7027,8 @@ do_pragma (buf, limit, op, keyword) /* 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. */ -/* - * the behavior of the #pragma directive is implementation defined. - * this implementation defines it as follows. - */ +/* The behavior of the #pragma directive is implementation defined. + this implementation defines it as follows. */ static int do_pragma () @@ -6996,9 +7054,9 @@ nope: static int do_sccs (buf, limit, op, keyword) - U_CHAR *buf, *limit; - FILE_BUF *op; - struct directive *keyword; + U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED; + FILE_BUF *op ATTRIBUTE_UNUSED; + struct directive *keyword ATTRIBUTE_UNUSED; { if (pedantic) pedwarn ("ANSI C does not allow `#sccs'"); @@ -7007,24 +7065,22 @@ do_sccs (buf, limit, op, keyword) #endif /* defined (SCCS_DIRECTIVE) */ -/* - * handle #if directive by - * 1) inserting special `defined' keyword into the hash table - * that gets turned into 0 or 1 by special_symbol (thus, - * if the luser has a symbol called `defined' already, it won't - * work inside the #if directive) - * 2) rescan the input into a temporary output buffer - * 3) pass the output buffer to the yacc parser and collect a value - * 4) clean up the mess left from steps 1 and 2. - * 5) call conditional_skip to skip til the next #endif (etc.), - * or not, depending on the value from step 3. - */ +/* Handle #if directive by + 1) inserting special `defined' keyword into the hash table + that gets turned into 0 or 1 by special_symbol (thus, + if the luser has a symbol called `defined' already, it won't + work inside the #if directive) + 2) rescan the input into a temporary output buffer + 3) pass the output buffer to the yacc parser and collect a value + 4) clean up the mess left from steps 1 and 2. + 5) call conditional_skip to skip til the next #endif (etc.), + or not, depending on the value from step 3. */ static int do_if (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; - struct directive *keyword; + struct directive *keyword ATTRIBUTE_UNUSED; { HOST_WIDE_INT value; FILE_BUF *ip = &instack[indepth]; @@ -7034,16 +7090,14 @@ do_if (buf, limit, op, keyword) return 0; } -/* - * handle a #elif directive by not changing if_stack either. - * see the comment above do_else. - */ +/* Handle a #elif directive by not changing if_stack either. + see the comment above do_else. */ static int do_elif (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; - struct directive *keyword; + struct directive *keyword ATTRIBUTE_UNUSED; { HOST_WIDE_INT value; FILE_BUF *ip = &instack[indepth]; @@ -7055,9 +7109,12 @@ do_elif (buf, limit, op, keyword) if (if_stack->type != T_IF && if_stack->type != T_ELIF) { error ("`#elif' after `#else'"); fprintf (stderr, " (matches line %d", if_stack->lineno); - if (if_stack->fname != NULL && ip->fname != NULL && - strcmp (if_stack->fname, ip->nominal_fname) != 0) - fprintf (stderr, ", file %s", if_stack->fname); + if (! (if_stack->fname_len == ip->nominal_fname_len + && !bcmp (if_stack->fname, ip->nominal_fname, + if_stack->fname_len))) { + fprintf (stderr, ", file "); + eprint_string (if_stack->fname, if_stack->fname_len); + } fprintf (stderr, ")\n"); } if_stack->type = T_ELIF; @@ -7077,10 +7134,9 @@ do_elif (buf, limit, op, keyword) return 0; } -/* - * evaluate a #if expression in BUF, of length LENGTH, - * then parse the result as a C expression and return the value as an int. - */ +/* 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 eval_if_expression (buf, length) U_CHAR *buf; @@ -7097,18 +7153,18 @@ eval_if_expression (buf, length) pcp_inside_if = 0; delete_macro (save_defined); /* clean up special symbol */ - value = parse_c_expression ((char *) temp_obuf.buf); + temp_obuf.buf[temp_obuf.length] = '\n'; + value = parse_c_expression ((char *) temp_obuf.buf, + warn_undef && !instack[indepth].system_header_p); free (temp_obuf.buf); return value; } -/* - * routine to handle ifdef/ifndef. Try to look up the symbol, - * then do or don't skip to the #endif/#else/#elif depending - * on what directive is actually being processed. - */ +/* routine to handle ifdef/ifndef. Try to look up the symbol, then do + or don't skip to the #endif/#else/#elif depending on what directive + is actually being processed. */ static int do_xifdef (buf, limit, op, keyword) @@ -7165,18 +7221,20 @@ do_xifdef (buf, limit, op, keyword) } else { HASHNODE *hp; - if (pedantic && buf[0] >= '0' && buf[0] <= '9') - pedwarn ("`#%s' argument starts with a digit", keyword->name); - else if (end != limit && !traditional) - pedwarn ("garbage at end of `#%s' argument", keyword->name); + if (! traditional) { + if (ISDIGIT (buf[0])) + pedwarn ("`#%s' argument starts with a digit", keyword->name); + else if (end != limit) + pedwarn ("garbage at end of `#%s' argument", keyword->name); + } hp = lookup (buf, end-buf, -1); if (pcp_outfile) { /* Output a precondition for this macro. */ - if (hp && - (hp->type == T_CONST - || (hp->type == T_MACRO && hp->value.defn->predefined))) + if (hp + && (hp->type == T_CONST + || (hp->type == T_MACRO && hp->value.defn->predefined))) fprintf (pcp_outfile, "#define %s\n", hp->name); else { U_CHAR *cp = buf; @@ -7216,6 +7274,7 @@ conditional_skip (ip, skip, type, control_macro, op) temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); temp->fname = ip->nominal_fname; + temp->fname_len = ip->nominal_fname_len; temp->lineno = ip->lineno; temp->next = if_stack; temp->control_macro = control_macro; @@ -7232,11 +7291,10 @@ conditional_skip (ip, skip, type, control_macro, op) } } -/* - * 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. - */ +/* 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 (ip, any, op) FILE_BUF *ip; @@ -7253,6 +7311,7 @@ skip_if_group (ip, any, op) /* Save info about where the group starts. */ U_CHAR *beg_of_group = bp; int beg_lineno = ip->lineno; + int skipping_include_directive = 0; if (output_conditionals && op != 0) { char *ptr = "#failed\n"; @@ -7281,22 +7340,49 @@ skip_if_group (ip, any, op) bp = skip_to_end_of_comment (ip, &ip->lineno, 0); } break; + case '<': + if (skipping_include_directive) { + while (bp < endb && *bp != '>' && *bp != '\n') { + if (*bp == '\\' && bp[1] == '\n') { + ip->lineno++; + bp++; + } + bp++; + } + } + break; case '\"': + if (skipping_include_directive) { + while (bp < endb && *bp != '\n') { + if (*bp == '"') { + bp++; + break; + } + if (*bp == '\\' && bp[1] == '\n') { + ip->lineno++; + bp++; + } + bp++; + } + break; + } + /* Fall through. */ case '\'': bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, NULL_PTR, NULL_PTR); break; case '\\': - /* Char after backslash loses its special meaning. */ - if (bp < endb) { - if (*bp == '\n') - ++ip->lineno; /* But do update the line-count. */ + /* Char after backslash loses its special meaning in some cases. */ + if (*bp == '\n') { + ++ip->lineno; + bp++; + } else if (traditional && bp < endb) bp++; - } break; case '\n': ++ip->lineno; beg_of_line = bp; + skipping_include_directive = 0; break; case '%': if (beg_of_line == 0 || traditional) @@ -7357,23 +7443,37 @@ skip_if_group (ip, any, op) bp++; else if (*bp == '\\' && bp[1] == '\n') bp += 2; - else if (*bp == '/' && bp[1] == '*') { - bp += 2; - while (!(*bp == '*' && bp[1] == '/')) { - if (*bp == '\n') - ip->lineno++; - bp++; - } - bp += 2; - } else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { - bp += 2; - while (bp[-1] == '\\' || *bp != '\n') { - if (*bp == '\n') - ip->lineno++; - bp++; - } - } - else break; + else if (*bp == '/') { + if (bp[1] == '\\' && bp[2] == '\n') + newline_fix (bp + 1); + if (bp[1] == '*') { + for (bp += 2; ; bp++) { + if (*bp == '\n') + ip->lineno++; + else if (*bp == '*') { + if (bp[-1] == '/' && warn_comments) + warning ("`/*' within comment"); + if (bp[1] == '\\' && bp[2] == '\n') + newline_fix (bp + 1); + if (bp[1] == '/') + break; + } + } + 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++; + } + } + } else + break; + } else + break; } cp = bp; @@ -7449,12 +7549,13 @@ skip_if_group (ip, any, op) if_stack = temp; temp->lineno = ip->lineno; temp->fname = ip->nominal_fname; + temp->fname_len = ip->nominal_fname_len; temp->type = kt->type; break; case T_ELSE: case T_ENDIF: if (pedantic && if_stack != save_if_stack) - validate_else (bp); + validate_else (bp, endb); case T_ELIF: if (if_stack == instack[indepth].if_stack) { error ("`#%s' not within a conditional", kt->name); @@ -7475,7 +7576,13 @@ skip_if_group (ip, any, op) free (temp); break; - default: + case T_INCLUDE: + case T_INCLUDE_NEXT: + case T_IMPORT: + skipping_include_directive = 1; + break; + + default: break; } break; @@ -7514,18 +7621,16 @@ skip_if_group (ip, any, op) } } -/* - * handle a #else directive. Do this by just continuing processing - * without changing if_stack ; this is so that the error message - * for missing #endif's etc. will point to the original #if. It - * is possible that something different would be better. - */ +/* Handle a #else directive. Do this by just continuing processing + without changing if_stack ; this is so that the error message + for missing #endif's etc. will point to the original #if. It + is possible that something different would be better. */ static int do_else (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; - struct directive *keyword; + struct directive *keyword ATTRIBUTE_UNUSED; { FILE_BUF *ip = &instack[indepth]; @@ -7546,8 +7651,12 @@ do_else (buf, limit, op, keyword) if (if_stack->type != T_IF && if_stack->type != T_ELIF) { error ("`#else' after `#else'"); fprintf (stderr, " (matches line %d", if_stack->lineno); - if (strcmp (if_stack->fname, ip->nominal_fname) != 0) - fprintf (stderr, ", file %s", if_stack->fname); + if (! (if_stack->fname_len == ip->nominal_fname_len + && !bcmp (if_stack->fname, ip->nominal_fname, + if_stack->fname_len))) { + fprintf (stderr, ", file "); + eprint_string (if_stack->fname, if_stack->fname_len); + } fprintf (stderr, ")\n"); } if_stack->type = T_ELSE; @@ -7562,15 +7671,13 @@ do_else (buf, limit, op, keyword) return 0; } -/* - * unstack after #endif directive - */ +/* Unstack after #endif directive. */ static int do_endif (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; - struct directive *keyword; + struct directive *keyword ATTRIBUTE_UNUSED; { if (pedantic) { SKIP_WHITE_SPACE (buf); @@ -7615,7 +7722,7 @@ do_endif (buf, limit, op, keyword) if (indepth != 0 && ! (indepth == 1 && no_record_file) && ! (no_record_file && no_output)) - record_control_macro (ip->fname, temp->control_macro); + record_control_macro (ip->inc, temp->control_macro); fail: ; } free (temp); @@ -7626,43 +7733,45 @@ do_endif (buf, limit, op, keyword) /* When an #else or #endif is found while skipping failed conditional, if -pedantic was specified, this is called to warn about text after - the directive name. P points to the first char after the directive name. */ + the directive name. P points to the first char after the directive + name. */ static void -validate_else (p) +validate_else (p, limit) register U_CHAR *p; + register U_CHAR *limit; { /* Advance P over whitespace and comments. */ while (1) { - if (*p == '\\' && p[1] == '\n') + while (*p == '\\' && p[1] == '\n') p += 2; if (is_hor_space[*p]) p++; else if (*p == '/') { - if (p[1] == '\\' && p[2] == '\n') - newline_fix (p + 1); - if (p[1] == '*') { + while (p[1] == '\\' && p[2] == '\n') p += 2; + if (p[1] == '*') { /* Don't bother warning about unterminated comments since that will happen later. Just be sure to exit. */ - while (*p) { - if (p[1] == '\\' && p[2] == '\n') - newline_fix (p + 1); - if (*p == '*' && p[1] == '/') { - p += 2; - break; + for (p += 2; ; p++) { + if (p == limit) + return; + if (*p == '*') { + while (p[1] == '\\' && p[2] == '\n') + p += 2; + if (p[1] == '/') { + p += 2; + break; + } } - p++; } } - else if (cplusplus_comments && p[1] == '/') { - p += 2; - while (*p && (*p != '\n' || p[-1] == '\\')) - p++; - } + else if (cplusplus_comments && p[1] == '/') + return; + else break; } else break; } - if (*p && *p != '\n') + if (*p != '\n') pedwarn ("text following `#else' or `#endif' violates ANSI standard"); } @@ -7673,9 +7782,10 @@ validate_else (p) counter is not sufficient to deal with newlines in the string. If NOWARN is nonzero, don't warn about slash-star inside a comment. - This feature is useful when processing a comment that is going to be - processed or was processed at another point in the preprocessor, - to avoid a duplicate warning. Likewise for unterminated comment errors. */ + This feature is useful when processing a comment that is going to + be processed or was processed at another point in the preprocessor, + to avoid a duplicate warning. Likewise for unterminated comment + errors. */ static U_CHAR * skip_to_end_of_comment (ip, line_counter, nowarn) @@ -7685,54 +7795,38 @@ skip_to_end_of_comment (ip, line_counter, nowarn) { register U_CHAR *limit = ip->buf + ip->length; register U_CHAR *bp = ip->bufp; - FILE_BUF *op = &outbuf; /* JF */ - int output = put_out_comments && !line_counter; + FILE_BUF *op = put_out_comments && !line_counter ? &outbuf : (FILE_BUF *) 0; int start_line = line_counter ? *line_counter : 0; /* JF this line_counter stuff is a crock to make sure the comment is only put out once, no matter how many times the comment is skipped. It almost works */ - if (output) { + if (op) { *op->bufp++ = '/'; - *op->bufp++ = '*'; + *op->bufp++ = bp[-1]; } if (cplusplus_comments && bp[-1] == '/') { - if (output) { - while (bp < limit) { - *op->bufp++ = *bp; - if (*bp == '\n' && bp[-1] != '\\') + for (; bp < limit; bp++) { + if (*bp == '\n') { + if (bp[-1] != '\\') break; - if (*bp == '\n') { + if (!nowarn && warn_comments) + warning ("multiline `//' comment"); + if (line_counter) ++*line_counter; + if (op) ++op->lineno; - } - bp++; - } - op->bufp[-1] = '*'; - *op->bufp++ = '/'; - *op->bufp++ = '\n'; - } else { - while (bp < limit) { - if (bp[-1] != '\\' && *bp == '\n') { - break; - } else { - if (*bp == '\n' && line_counter) - ++*line_counter; - bp++; - } } + if (op) + *op->bufp++ = *bp; } ip->bufp = bp; return bp; } while (bp < limit) { - if (output) + if (op) *op->bufp++ = *bp; switch (*bp++) { - case '/': - if (warn_comments && !nowarn && bp < limit && *bp == '*') - warning ("`/*' within comment"); - break; case '\n': /* If this is the end of the file, we have an unterminated comment. Don't swallow the newline. We are guaranteed that there will be a @@ -7745,14 +7839,16 @@ skip_to_end_of_comment (ip, line_counter, nowarn) } if (line_counter != NULL) ++*line_counter; - if (output) + if (op) ++op->lineno; break; case '*': + if (bp[-2] == '/' && !nowarn && warn_comments) + warning ("`/*' within comment"); if (*bp == '\\' && bp[1] == '\n') newline_fix (bp); if (*bp == '/') { - if (output) + if (op) *op->bufp++ = '/'; ip->bufp = ++bp; return bp; @@ -7767,22 +7863,21 @@ skip_to_end_of_comment (ip, line_counter, nowarn) return bp; } -/* - * Skip over a quoted string. BP points to the opening quote. - * Returns a pointer after the closing quote. Don't go past LIMIT. - * START_LINE is the line number of the starting point (but it need - * not be valid if the starting point is inside a macro expansion). - * - * The input stack state is not changed. - * - * If COUNT_NEWLINES is nonzero, it points to an int to increment - * for each newline passed. - * - * If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it - * if we pass a backslash-newline. - * - * If EOFP is nonzero, set *EOFP to 1 if the string is unterminated. - */ +/* Skip over a quoted string. BP points to the opening quote. + Returns a pointer after the closing quote. Don't go past LIMIT. + START_LINE is the line number of the starting point (but it need + not be valid if the starting point is inside a macro expansion). + + The input stack state is not changed. + + If COUNT_NEWLINES is nonzero, it points to an int to increment + for each newline passed. + + If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it + if we pass a backslash-newline. + + If EOFP is nonzero, set *EOFP to 1 if the string is unterminated. */ + static U_CHAR * skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp) register U_CHAR *bp; @@ -7815,21 +7910,22 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, ++*count_newlines; bp += 2; } - if (*bp == '\n' && count_newlines) { + if (*bp == '\n') { if (backslash_newlines_p) *backslash_newlines_p = 1; - ++*count_newlines; + if (count_newlines) + ++*count_newlines; } bp++; } else if (c == '\n') { if (traditional) { /* Unterminated strings and character constants are 'valid'. */ - bp--; /* Don't consume the newline. */ + bp--; /* Don't consume the newline. */ if (eofp) *eofp = 1; break; } - if (pedantic || match == '\'') { + if (match == '\'') { error_with_line (line_for_error (start_line), "unterminated string or character constant"); bp--; @@ -7840,8 +7936,12 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, /* If not traditional, then allow newlines inside strings. */ if (count_newlines) ++*count_newlines; - if (multiline_string_line == 0) + if (multiline_string_line == 0) { + if (pedantic) + pedwarn_with_line (line_for_error (start_line), + "string constant runs past end of line"); multiline_string_line = start_line; + } } else if (c == match) break; } @@ -7849,19 +7949,23 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, } /* Place into DST a quoted string representing the string SRC. + SRCLEN is the length of SRC; SRC may contain null bytes. Return the address of DST's terminating null. */ + static char * -quote_string (dst, src) +quote_string (dst, src, srclen) char *dst, *src; + size_t srclen; { U_CHAR c; + char *srclim = src + srclen; *dst++ = '\"'; - for (;;) + while (src != srclim) switch ((c = *src++)) { default: - if (isprint (c)) + if (ISPRINT (c)) *dst++ = c; else { @@ -7875,12 +7979,11 @@ quote_string (dst, src) *dst++ = '\\'; *dst++ = c; break; - - case '\0': - *dst++ = '\"'; - *dst = '\0'; - return dst; } + + *dst++ = '\"'; + *dst = '\0'; + return dst; } /* Skip across a group of balanced parens, starting from IP->bufp. @@ -7934,13 +8037,11 @@ skip_paren_group (ip) return p; } -/* - * write out a #line directive, 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. - */ +/* Write out a #line directive, 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_directive (ip, op, conditional, file_change) @@ -7974,17 +8075,17 @@ output_line_directive (ip, op, conditional, file_change) } } - /* 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') { + /* Output a positive line number if possible. */ + while (ip->lineno <= 0 && ip->bufp - ip->buf < ip->length + && *ip->bufp == '\n') { ip->lineno++; ip->bufp++; } - line_directive_buf = (char *) alloca (4 * strlen (ip->nominal_fname) + 100); + line_directive_buf = (char *) alloca (4 * ip->nominal_fname_len + 100); sprintf (line_directive_buf, "# %d ", ip->lineno); line_end = quote_string (line_directive_buf + strlen (line_directive_buf), - ip->nominal_fname); + ip->nominal_fname, ip->nominal_fname_len); if (file_change != same_file) { *line_end++ = ' '; *line_end++ = file_change == enter_file ? '1' : '2'; @@ -8096,7 +8197,7 @@ macroexpand (hp, op) if (rest_args) continue; if (i < nargs || (nargs == 0 && i == 0)) { - /* if we are working on last arg which absorbs rest of args... */ + /* If we are working on last arg which absorbs rest of args... */ if (i == nargs - 1 && defn->rest_args) rest_args = 1; parse_error = macarg (&args[i], rest_args); @@ -8249,29 +8350,30 @@ macroexpand (hp, op) for (; i < arglen; i++) { c = arg->raw[i]; - /* Special markers Newline Space - generate nothing for a stringified argument. */ - if (c == '\n' && arg->raw[i+1] != '\n') { - i++; - continue; - } + if (! in_string) { + /* Special markers Newline Space + generate nothing for a stringified argument. */ + if (c == '\n' && arg->raw[i+1] != '\n') { + i++; + continue; + } - /* Internal sequences of whitespace are replaced by one space - except within an string or char token. */ - if (! in_string - && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) { - while (1) { - /* Note that Newline Space does occur within whitespace - sequences; consider it part of the sequence. */ - if (c == '\n' && is_space[arg->raw[i+1]]) - i += 2; - else if (c != '\n' && is_space[c]) - i++; - else break; - c = arg->raw[i]; + /* Internal sequences of whitespace are replaced by one space + except within an string or char token. */ + if (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c]) { + while (1) { + /* Note that Newline Space does occur within whitespace + sequences; consider it part of the sequence. */ + if (c == '\n' && is_space[arg->raw[i+1]]) + i += 2; + else if (c != '\n' && is_space[c]) + i++; + else break; + c = arg->raw[i]; + } + i--; + c = ' '; } - i--; - c = ' '; } if (escaped) @@ -8289,12 +8391,10 @@ macroexpand (hp, op) /* Escape these chars */ if (c == '\"' || (in_string && c == '\\')) xbuf[totlen++] = '\\'; - if (isprint (c)) - xbuf[totlen++] = c; - else { - sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c); - totlen += 4; - } + /* We used to output e.g. \008 for control characters here, + but this doesn't conform to the C Standard. + Just output the characters as-is. */ + xbuf[totlen++] = c; } if (!traditional) xbuf[totlen++] = '\"'; /* insert ending quote */ @@ -8374,8 +8474,8 @@ macroexpand (hp, op) abort (); } - /* if there is anything left of the definition - after handling the arg list, copy that in too. */ + /* 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 */ @@ -8410,6 +8510,8 @@ macroexpand (hp, op) ip2->fname = 0; ip2->nominal_fname = 0; + ip2->nominal_fname_len = 0; + ip2->inc = 0; /* This may not be exactly correct, but will give much better error messages for nested macro calls than using a line number of zero. */ ip2->lineno = start_line; @@ -8430,11 +8532,9 @@ macroexpand (hp, op) } } -/* - * Parse a macro argument and store the info on it into *ARGPTR. - * REST_ARGS is passed to macarg1 to make it absorb the rest of the args. - * Return nonzero to indicate a syntax error. - */ +/* Parse a macro argument and store the info on it into *ARGPTR. + REST_ARGS is passed to macarg1 to make it absorb the rest of the args. + Return nonzero to indicate a syntax error. */ static char * macarg (argptr, rest_args) @@ -8449,7 +8549,7 @@ macarg (argptr, rest_args) /* Try to parse as much of the argument as exists at this input stack level. */ - U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, + U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren, &newlines, &comments, rest_args); /* If we find the end of the argument at this level, @@ -8487,7 +8587,7 @@ macarg (argptr, rest_args) ip = &instack[--indepth]; newlines = 0; comments = 0; - bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren, + bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren, &newlines, &comments, rest_args); final_start = bufsize; bufsize += bp - ip->bufp; @@ -8550,8 +8650,6 @@ macarg (argptr, rest_args) #endif if (c == '\"' || c == '\\') /* escape these chars */ totlen++; - else if (!isprint (c)) - totlen += 3; } argptr->stringified_length = totlen; } @@ -8559,6 +8657,7 @@ macarg (argptr, rest_args) } /* Scan text from START (inclusive) up to LIMIT (exclusive), + taken from the expansion of MACRO, counting parens in *DEPTHPTR, and return if reach LIMIT or before a `)' that would make *DEPTHPTR negative @@ -8572,9 +8671,10 @@ macarg (argptr, rest_args) Set *COMMENTS to 1 if a comment is seen. */ static U_CHAR * -macarg1 (start, limit, depthptr, newlines, comments, rest_args) +macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args) U_CHAR *start; register U_CHAR *limit; + struct hashnode *macro; int *depthptr, *newlines, *comments; int rest_args; { @@ -8591,43 +8691,44 @@ macarg1 (start, limit, depthptr, newlines, comments, rest_args) break; case '\\': /* Traditionally, backslash makes following char not special. */ - if (bp + 1 < limit && traditional) - { - bp++; - /* But count source lines anyway. */ - if (*bp == '\n') - ++*newlines; - } + if (traditional && bp + 1 < limit && bp[1] != '\n') + bp++; break; case '\n': ++*newlines; break; case '/': + if (macro) + break; if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); - if (cplusplus_comments && bp[1] == '/') { + if (bp[1] == '*') { *comments = 1; - bp += 2; - while (bp < limit && (*bp != '\n' || bp[-1] == '\\')) { - if (*bp == '\n') ++*newlines; - bp++; + for (bp += 2; bp < limit; bp++) { + if (*bp == '\n') + ++*newlines; + else if (*bp == '*') { + if (bp[-1] == '/' && warn_comments) + warning ("`/*' within comment"); + if (bp[1] == '\\' && bp[2] == '\n') + newline_fix (bp + 1); + if (bp[1] == '/') { + bp++; + break; + } + } + } + } 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"); + } } - /* Now count the newline that we are about to skip. */ - ++*newlines; - break; - } - if (bp[1] != '*' || bp + 1 >= limit) - break; - *comments = 1; - bp += 2; - while (bp + 1 < limit) { - if (bp[0] == '*' - && bp[1] == '\\' && bp[2] == '\n') - newline_fix (bp + 1); - if (bp[0] == '*' && bp[1] == '/') - break; - if (*bp == '\n') ++*newlines; - bp++; } break; case '\'': @@ -8639,8 +8740,11 @@ macarg1 (start, limit, depthptr, newlines, comments, rest_args) bp++; if (*bp == '\n') ++*newlines; - while (*bp == '\\' && bp[1] == '\n') { - bp += 2; + if (!macro) { + while (*bp == '\\' && bp[1] == '\n') { + bp += 2; + ++*newlines; + } } } else if (*bp == '\n') { ++*newlines; @@ -8736,16 +8840,16 @@ discard_comments (start, length, newlines) obp--; else obp[-1] = ' '; - ibp++; - while (ibp + 1 < limit) { - if (ibp[0] == '*' - && ibp[1] == '\\' && ibp[2] == '\n') - newline_fix (ibp + 1); - if (ibp[0] == '*' && ibp[1] == '/') - break; - ibp++; + while (++ibp < limit) { + if (ibp[0] == '*') { + if (ibp[1] == '\\' && ibp[2] == '\n') + newline_fix (ibp + 1); + if (ibp[1] == '/') { + ibp += 2; + break; + } + } } - ibp += 2; break; case '\'': @@ -8761,10 +8865,16 @@ discard_comments (start, length, newlines) break; if (c == '\n' && quotec == '\'') break; - if (c == '\\' && ibp < limit) { - while (*ibp == '\\' && ibp[1] == '\n') - ibp += 2; - *obp++ = *ibp++; + if (c == '\\') { + if (ibp < limit && *ibp == '\n') { + ibp++; + obp--; + } else { + while (*ibp == '\\' && ibp[1] == '\n') + ibp += 2; + if (ibp < limit) + *obp++ = *ibp++; + } } } } @@ -8815,7 +8925,7 @@ change_newlines (start, length) int quotec = c; while (ibp < limit) { *obp++ = c = *ibp++; - if (c == quotec) + if (c == quotec && ibp[-2] != '\\') break; if (c == '\n' && quotec == '\'') break; @@ -8828,11 +8938,10 @@ change_newlines (start, length) return obp - start; } -/* - * my_strerror - return the descriptive text associated with an `errno' code. - */ +/* my_strerror - return the descriptive text associated with an + `errno' code. */ -char * +static char * my_strerror (errnum) int errnum; { @@ -8861,17 +8970,22 @@ my_strerror (errnum) return result; } -/* - * error - print error message and increment count of errors. - */ +/* error - print error message and increment count of errors. */ void -error (PRINTF_ALIST (msg)) - PRINTF_DCL (msg) +error VPROTO ((char * msg, ...)) { +#ifndef __STDC__ + char * msg; +#endif va_list args; VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + verror (msg, args); va_end (args); } @@ -8892,8 +9006,10 @@ verror (msg, args) break; } - if (ip != NULL) - fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); + if (ip != NULL) { + eprint_string (ip->nominal_fname, ip->nominal_fname_len); + fprintf (stderr, ":%d: ", ip->lineno); + } vfprintf (stderr, msg, args); fprintf (stderr, "\n"); errors++; @@ -8905,6 +9021,7 @@ static void error_from_errno (name) char *name; { + int e = errno; int i; FILE_BUF *ip = NULL; @@ -8916,10 +9033,12 @@ error_from_errno (name) break; } - if (ip != NULL) - fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); + if (ip != NULL) { + eprint_string (ip->nominal_fname, ip->nominal_fname_len); + fprintf (stderr, ":%d: ", ip->lineno); + } - fprintf (stderr, "%s: %s\n", name, my_strerror (errno)); + fprintf (stderr, "%s: %s\n", name, my_strerror (e)); errors++; } @@ -8927,12 +9046,19 @@ error_from_errno (name) /* Print error message but don't count it. */ void -warning (PRINTF_ALIST (msg)) - PRINTF_DCL (msg) +warning VPROTO ((char * msg, ...)) { +#ifndef __STDC__ + char * msg; +#endif va_list args; VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + vwarning (msg, args); va_end (args); } @@ -8959,25 +9085,31 @@ vwarning (msg, args) break; } - if (ip != NULL) - fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); + if (ip != NULL) { + eprint_string (ip->nominal_fname, ip->nominal_fname_len); + fprintf (stderr, ":%d: ", ip->lineno); + } fprintf (stderr, "warning: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); } static void -#if defined (__STDC__) && defined (HAVE_VPRINTF) -error_with_line (int line, PRINTF_ALIST (msg)) -#else -error_with_line (line, PRINTF_ALIST (msg)) - int line; - PRINTF_DCL (msg) -#endif +error_with_line VPROTO ((int line, char * msg, ...)) { +#ifndef __STDC__ + int line; + char * msg; +#endif va_list args; VA_START (args, msg); + +#ifndef __STDC__ + line = va_arg (args, int); + msg = va_arg (args, char *); +#endif + verror_with_line (line, msg, args); va_end (args); } @@ -8999,25 +9131,31 @@ verror_with_line (line, msg, args) break; } - if (ip != NULL) - fprintf (stderr, "%s:%d: ", ip->nominal_fname, line); + if (ip != NULL) { + eprint_string (ip->nominal_fname, ip->nominal_fname_len); + fprintf (stderr, ":%d: ", line); + } vfprintf (stderr, msg, args); fprintf (stderr, "\n"); errors++; } static void -#if defined (__STDC__) && defined (HAVE_VPRINTF) -warning_with_line (int line, PRINTF_ALIST (msg)) -#else -warning_with_line (line, PRINTF_ALIST (msg)) - int line; - PRINTF_DCL (msg) -#endif +warning_with_line VPROTO ((int line, char * msg, ...)) { +#ifndef __STDC__ + int line; + char * msg; +#endif va_list args; VA_START (args, msg); + +#ifndef __STDC__ + line = va_arg (args, int); + msg = va_arg (args, char *); +#endif + vwarning_with_line (line, msg, args); va_end (args); } @@ -9045,22 +9183,31 @@ vwarning_with_line (line, msg, args) break; } - if (ip != NULL) - fprintf (stderr, line ? "%s:%d: " : "%s: ", ip->nominal_fname, line); + if (ip != NULL) { + eprint_string (ip->nominal_fname, ip->nominal_fname_len); + fprintf (stderr, line ? ":%d: " : ": ", line); + } fprintf (stderr, "warning: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); } -/* print an error message and maybe count it. */ +/* Print an error message and maybe count it. */ void -pedwarn (PRINTF_ALIST (msg)) - PRINTF_DCL (msg) +pedwarn VPROTO ((char * msg, ...)) { +#ifndef __STDC__ + char * msg; +#endif va_list args; VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + if (pedantic_errors) verror (msg, args); else @@ -9069,17 +9216,21 @@ pedwarn (PRINTF_ALIST (msg)) } void -#if defined (__STDC__) && defined (HAVE_VPRINTF) -pedwarn_with_line (int line, PRINTF_ALIST (msg)) -#else -pedwarn_with_line (line, PRINTF_ALIST (msg)) - int line; - PRINTF_DCL (msg) -#endif +pedwarn_with_line VPROTO ((int line, char * msg, ...)) { +#ifndef __STDC__ + int line; + char * msg; +#endif va_list args; VA_START (args, msg); + +#ifndef __STDC__ + line = va_arg (args, int); + msg = va_arg (args, char *); +#endif + if (pedantic_errors) verror_with_line (line, msg, args); else @@ -9091,26 +9242,36 @@ pedwarn_with_line (line, PRINTF_ALIST (msg)) giving specified file name and line number, not current. */ static void -#if defined (__STDC__) && defined (HAVE_VPRINTF) -pedwarn_with_file_and_line (char *file, int line, PRINTF_ALIST (msg)) -#else -pedwarn_with_file_and_line (file, line, PRINTF_ALIST (msg)) - char *file; - int line; - PRINTF_DCL (msg) +pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line, + char * msg, ...)) +{ +#ifndef __STDC__ + char *file; + size_t file_len; + int line; + char * msg; #endif -{ va_list args; if (!pedantic_errors && inhibit_warnings) return; - if (file != NULL) - fprintf (stderr, "%s:%d: ", file, line); + if (file) { + eprint_string (file, file_len); + fprintf (stderr, ":%d: ", 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); va_end (args); fprintf (stderr, "\n"); @@ -9152,7 +9313,9 @@ print_containing_files () fprintf (stderr, ",\n "); } - fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno); + fprintf (stderr, " from "); + eprint_string (ip->nominal_fname, ip->nominal_fname_len); + fprintf (stderr, ":%d", ip->lineno); } if (! first) fprintf (stderr, ":\n"); @@ -9200,6 +9363,7 @@ line_for_error (line) /* You might think void was cleaner for the return type, but that would get type mismatch in check_expand in strict ANSI. */ + static int grow_outbuf (obuf, needed) register FILE_BUF *obuf; @@ -9241,8 +9405,9 @@ grow_outbuf (obuf, needed) * Otherwise, compute the length by scanning the entire name. * * If HASH is >= 0, it is the precomputed hash code. - * Otherwise, compute the hash code. + * Otherwise, compute the hash code. */ + static HASHNODE * install (name, len, type, value, hash) U_CHAR *name; @@ -9287,7 +9452,7 @@ install (name, len, type, value, hash) } /* - * find the most recent hash node for name name (ending with first + * 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. @@ -9296,6 +9461,7 @@ install (name, len, type, value, hash) * If HASH is >= 0, it is the precomputed hash code. * Otherwise, compute the hash code. */ + HASHNODE * lookup (name, len, hash) U_CHAR *name; @@ -9346,8 +9512,8 @@ delete_macro (hp) if (hp->next != NULL) hp->next->prev = hp->prev; - /* make sure that the bucket chain header that - the deleted guy was on points to the right thing afterwards. */ + /* 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; @@ -9370,6 +9536,7 @@ delete_macro (hp) * return hash function on name. must be compatible with the one * computed a step at a time, elsewhere */ + static int hashf (name, len, hashsize) register U_CHAR *name; @@ -9386,6 +9553,7 @@ hashf (name, len, hashsize) /* Dump the definition of a single macro HP to OF. */ + static void dump_single_macro (hp, of) register HASHNODE *hp; @@ -9567,8 +9735,8 @@ initialize_char_syntax () is_idchar[i] = 1; is_idchar['_'] = 1; is_idstart['_'] = 1; - is_idchar['$'] = dollars_in_ident; - is_idstart['$'] = dollars_in_ident; + is_idchar['$'] = 1; + is_idstart['$'] = 1; /* horizontal space table */ is_hor_space[' '] = 1; @@ -9625,6 +9793,7 @@ initialize_builtins (inp, outp) /* 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); */ + install ((U_CHAR *) "__HAVE_BUILTIN_SETJMP__", -1, T_CONST, "1", -1); if (debug_output) { @@ -9747,10 +9916,7 @@ make_definition (str, op) if (unterminated) return; while (p != p1) - if (*p == '\\' && p[1] == '\n') - p += 2; - else - *q++ = *p++; + *q++ = *p++; } else if (*p == '\\' && p[1] == '\n') p += 2; /* Change newline chars into newline-markers. */ @@ -9768,6 +9934,7 @@ make_definition (str, op) ip = &instack[++indepth]; ip->nominal_fname = ip->fname = "*Initialization*"; + ip->nominal_fname_len = strlen (ip->nominal_fname); ip->buf = ip->bufp = buf; ip->length = strlen ((char *) buf); @@ -9797,6 +9964,7 @@ make_undef (str, op) ip = &instack[++indepth]; ip->nominal_fname = ip->fname = "*undef*"; + ip->nominal_fname_len = strlen (ip->nominal_fname); ip->buf = ip->bufp = (U_CHAR *) str; ip->length = strlen (str); @@ -9853,6 +10021,7 @@ make_assertion (option, str) ip = &instack[++indepth]; ip->nominal_fname = ip->fname = "*Initialization*"; + ip->nominal_fname_len = strlen (ip->nominal_fname); ip->buf = ip->bufp = buf; ip->length = strlen ((char *) buf); @@ -9865,12 +10034,116 @@ make_assertion (option, str) for (kt = directive_table; kt->type != T_ASSERT; kt++) ; - /* pass NULL as output ptr to do_define since we KNOW it never - does any output.... */ + /* Pass NULL as output ptr to do_define since we KNOW it never does + any output.... */ do_assert (buf, buf + strlen ((char *) buf) , NULL_PTR, kt); --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 + simplified concatenation of PREFIX and NAME, + with a trailing / added if needed. + But return 0 if the include prefix should be ignored, + e.g. because it is a duplicate of PREV_FILE_NAME. */ + +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; +{ + if (name == 0) + fatal ("Directory name missing after command line option"); + + if (*name == 0) + /* Ignore the empty string. */ + return 0; + + prefix = update_path (prefix, component); + name = update_path (name, component); + + { + struct file_name_list *dir + = ((struct file_name_list *) + xmalloc (sizeof (struct file_name_list) + + strlen (prefix) + strlen (name) + 2)); + size_t len; + strcpy (dir->fname, prefix); + strcat (dir->fname, name); + len = simplify_filename (dir->fname); + + /* Convert directory name to a prefix. */ + if (len && dir->fname[len - 1] != DIR_SEPARATOR) { + if (len == 1 && dir->fname[len - 1] == '.') + len = 0; + else +#ifdef VMS + /* must be '/', hack_vms_include_specification triggers on it. */ + dir->fname[len++] = '/'; +#else + dir->fname[len++] = DIR_SEPARATOR; +#endif + dir->fname[len] = 0; + } + + /* Ignore a directory whose name matches the previous one. */ + if (prev_file_name && !strcmp (prev_file_name->fname, dir->fname)) { + /* But treat `-Idir -I- -Idir' as `-I- -Idir'. */ + if (!first_bracket_include) + first_bracket_include = prev_file_name; + free (dir); + return 0; + } + +#ifndef VMS + /* VMS can't stat dir prefixes, so skip these optimizations in VMS. */ + + /* Add a trailing "." if there is a filename. This increases the number + of systems that can stat directories. We remove it below. */ + if (len != 0) + { + dir->fname[len] = '.'; + dir->fname[len + 1] = 0; + } + + /* Ignore a nonexistent directory. */ + if (stat (len ? dir->fname : ".", &dir->st) != 0) { + if (errno != ENOENT && errno != ENOTDIR) + error_from_errno (dir->fname); + free (dir); + return 0; + } + + if (len != 0) + dir->fname[len] = 0; + + /* Ignore a directory whose identity matches the previous one. */ + if (prev_file_name + && INO_T_EQ (prev_file_name->st.st_ino, dir->st.st_ino) + && prev_file_name->st.st_dev == dir->st.st_dev) { + /* But treat `-Idir -I- -Idir' as `-I- -Idir'. */ + if (!first_bracket_include) + first_bracket_include = prev_file_name; + free (dir); + return 0; + } +#endif /* ! VMS */ + + dir->next = 0; + dir->c_system_include_path = 0; + dir->got_name_map = 0; + + return dir; + } +} + /* 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. */ @@ -9904,6 +10177,67 @@ append_include_chain (first, last) last_include = last; } +/* Place into DST a representation of the file named SRC that is suitable + for `make'. Do not null-terminate DST. Return its length. */ +static int +quote_string_for_make (dst, src) + char *dst; + char *src; +{ + char *p = src; + int i = 0; + for (;;) + { + char c = *p++; + switch (c) + { + case '\0': + case ' ': + case '\t': + { + /* GNU make uses a weird quoting scheme for white space. + A space or tab preceded by 2N+1 backslashes represents + N backslashes followed by space; a space or tab + 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; + for (q = p - 1; src < q && q[-1] == '\\'; q--) + { + if (dst) + dst[i] = '\\'; + i++; + } + } + if (!c) + return i; + if (dst) + dst[i] = '\\'; + i++; + goto ordinary_char; + + case '$': + if (dst) + dst[i] = c; + i++; + /* Fall through. This can mishandle things like "$(" but + there's no easy fix. */ + default: + ordinary_char: + /* This can mishandle characters in the string "\0\n%*?[\\~"; + exactly which chars are mishandled depends on the `make' version. + We know of no portable solution for this; + even GNU make 3.76.1 doesn't solve the problem entirely. + (Also, '\0' is mishandled due to our calling conventions.) */ + if (dst) + dst[i] = c; + i++; + break; + } + } +} + + /* Add output to `deps_buffer' for the -M switch. STRING points to the text to be output. SPACER is ':' for targets, ' ' for dependencies. */ @@ -9913,7 +10247,7 @@ deps_output (string, spacer) char *string; int spacer; { - int size = strlen (string); + int size = quote_string_for_make ((char *) 0, string); if (size == 0) return; @@ -9930,15 +10264,15 @@ deps_output (string, spacer) spacer = 0; } - if (deps_size + size + 8 > deps_allocated_size) { - deps_allocated_size = (deps_size + size + 50) * 2; + if (deps_size + 2 * size + 8 > deps_allocated_size) { + deps_allocated_size = (deps_size + 2 * size + 50) * 2; deps_buffer = xrealloc (deps_buffer, deps_allocated_size); } if (spacer == ' ') { deps_buffer[deps_size++] = ' '; deps_column++; } - bcopy (string, &deps_buffer[deps_size], size); + quote_string_for_make (&deps_buffer[deps_size], string); deps_size += size; deps_column += size; if (spacer == ':') { @@ -9949,13 +10283,20 @@ deps_output (string, spacer) } static void -fatal (PRINTF_ALIST (msg)) - PRINTF_DCL (msg) +fatal VPROTO ((char * msg, ...)) { +#ifndef __STDC__ + char * msg; +#endif va_list args; fprintf (stderr, "%s: ", progname); VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + vfprintf (stderr, msg, args); va_end (args); fprintf (stderr, "\n"); @@ -9975,8 +10316,7 @@ static void perror_with_name (name) char *name; { - fprintf (stderr, "%s: ", progname); - fprintf (stderr, "%s: %s\n", name, my_strerror (errno)); + fprintf (stderr, "%s: %s: %s\n", progname, name, my_strerror (errno)); errors++; } @@ -9997,7 +10337,7 @@ pfatal_with_name (name) static void pipe_closed (signo) /* If this is missing, some compilers complain. */ - int signo; + int signo ATTRIBUTE_UNUSED; { fatal ("output pipe has been closed"); } @@ -10052,68 +10392,86 @@ savestring (input) return output; } -/* Get the file-mode and data size of the file open on FD - and store them in *MODE_POINTER and *SIZE_POINTER. */ +#ifdef VMS -static int -file_size_and_mode (fd, mode_pointer, size_pointer) - int fd; - int *mode_pointer; - long int *size_pointer; -{ - struct stat sbuf; +/* Under VMS we need to fix up the "include" specification filename. - if (fstat (fd, &sbuf) < 0) return (-1); - if (mode_pointer) *mode_pointer = sbuf.st_mode; - if (size_pointer) *size_pointer = sbuf.st_size; - return 0; -} - -#ifdef VMS + Rules for possible conversions -/* Under VMS we need to fix up the "include" specification - filename so that everything following the 1st slash is - changed into its correct VMS file specification. */ + fullname tried paths -static void -hack_vms_include_specification (fname) - char *fname; + 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. + + return 1 if name was changed, 0 else. */ + +static int +hack_vms_include_specification (fullname, vaxc_include) + char *fullname; + int vaxc_include; { - register char *cp, *cp1, *cp2; - int f, check_filename_before_returning, no_prefix_seen; + register char *basename, *unixname, *local_ptr, *first_slash; + int f, check_filename_before_returning, must_revert; char Local[512]; check_filename_before_returning = 0; - no_prefix_seen = 0; - - /* Ignore leading "./"s */ - while (fname[0] == '.' && fname[1] == '/') { - strcpy (fname, fname+2); - no_prefix_seen = 1; /* mark this for later */ - } - /* Look for the boundary between the VMS and UNIX filespecs */ - cp = rindex (fname, ']'); /* Look for end of dirspec. */ - if (cp == 0) cp = rindex (fname, '>'); /* ... Ditto */ - if (cp == 0) cp = rindex (fname, ':'); /* Look for end of devspec. */ - if (cp) { - cp++; - } else { - cp = index (fname, '/'); /* Look for the "/" */ - } + 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); /* * Check if we have a vax-c style '#include filename' * and add the missing .h */ - if (cp == 0) { - if (index(fname,'.') == 0) - strcat(fname, ".h"); - } else { - if (index(cp,'.') == 0) - strcat(cp, ".h"); - } - cp2 = Local; /* initialize */ + if (vaxc_include && !index (basename,'.')) + strcat (basename, ".h"); + + 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 @@ -10124,171 +10482,201 @@ hack_vms_include_specification (fname) 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). */ + 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++; - /* See if we found that 1st slash */ - if (cp == 0) return; /* Nothing to do!!! */ - if (*cp != '/') return; /* Nothing to do!!! */ - /* Point to the UNIX filename part (which needs to be fixed!) */ - cp1 = cp+1; /* If the directory spec is not rooted, we can just copy - the UNIX filename part and we are done */ - if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) { - if (cp[-2] != '.') { - /* - * The VMS part ends in a `]', and the preceding character is not a `.'. - * 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. */ - cp -= 1; /* Strip "]" */ - cp1--; /* 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 cp1, so that it points to a '/'. This inhibits the - * generation of the 000000 root directory spec (which does not belong here - * in this case). - */ - cp -= 2; /* Strip ".]" */ - cp1--; }; /* backspace */ - } else { + the UNIX filename part and we are done. */ - /* 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 (cp[-1] != ':') *cp2++ = ':'; /* dev not in spec. take first dir */ - *cp2++ = '['; /* Open the directory specification */ - } + 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 */ + specified already. - /* If there are no other slashes then the filename will be + If there are no other slashes then the filename will be in the "root" directory. Otherwise, we need to add - directory specifications. */ - if (index (cp1, '/') == 0) { - /* Just add "000000]" as the directory string */ - strcpy (cp2, "000000]"); - cp2 += strlen (cp2); - 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 (cp1, '/') != 0) { - /* If this token is "." we can ignore it */ - if ((cp1[0] == '.') && (cp1[1] == '/')) { - cp1 += 2; - continue; - } - /* Add a subdirectory spec. Do not duplicate "." */ - if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<') - *cp2++ = '.'; - /* If this is ".." then the spec becomes "-" */ - if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) { - /* Add "-" and skip the ".." */ - *cp2++ = '-'; - cp1 += 3; - continue; - } - /* Copy the subdirectory */ - while (*cp1 != '/') *cp2++= *cp1++; - cp1++; /* Skip the "/" */ + 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++ = ']'; } - /* Close the directory specification */ - if (cp2[-1] == '.') /* no trailing periods */ - cp2--; - *cp2++ = ']'; - } - /* Now add the filename */ - while (*cp1) *cp2++ = *cp1++; - *cp2 = 0; - /* Now append it to the original VMS spec. */ - strcpy (cp, Local); + + /* 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 && no_prefix_seen) { - f = open (fname, O_RDONLY, 0666); - if (f >= 0) { - /* The file name is OK as it is, so return it as is. */ - close (f); - return; - } - /* The filename did not work. Try to remove the [000000] from the name, - and return it. */ - cp = index (fname, '['); - cp2 = index (fname, ']') + 1; - strcpy (cp, cp2); /* this gets rid of it */ - } - return; -} -#endif /* VMS */ - -#ifdef VMS + 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; + } -/* These are the read/write replacement routines for - VAX-11 "C". They make read/write behave enough - like their UNIX counterparts that CCCP will work */ + /* 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 */ -static int -read (fd, buf, size) - int fd; - char *buf; - int size; -{ -#undef read /* Get back the REAL read routine */ - register int i; - register int total = 0; - - /* Read until the buffer is exhausted */ - while (size > 0) { - /* Limit each read to 32KB */ - i = (size > (32*1024)) ? (32*1024) : size; - i = read (fd, buf, i); - if (i <= 0) { - if (i == 0) return (total); - return (i); } - /* Account for this read */ - total += i; - buf += i; - size -= i; - } - return (total); -} -static int -write (fd, buf, size) - int fd; - char *buf; - int size; -{ -#undef write /* Get back the REAL write routine */ - int i; - int j; - - /* Limit individual writes to 32Kb */ - i = size; - while (i > 0) { - j = (i > (32*1024)) ? (32*1024) : i; - if (write (fd, buf, j) < 0) return (-1); - /* Account for the data written */ - buf += j; - i -= j; - } - return (size); + return 1; } +#endif /* VMS */ + +#ifdef VMS /* The following wrapper functions supply additional arguments to the VMS I/O routines to optimize performance with file handling. The arguments @@ -10296,27 +10684,27 @@ write (fd, buf, size) "mbc=16" - Set multi-block count to 16 (use a 8192 byte buffer). "deq=64" - When extending the file, extend it in chunks of 32Kbytes. "fop=tef"- Truncate unused portions of file when closing file. - "shr=nil"- Disallow file sharing while file is open. - */ + "shr=nil"- Disallow file sharing while file is open. */ static FILE * -freopen (fname, type, oldfile) +VMS_freopen (fname, type, oldfile) char *fname; char *type; FILE *oldfile; { -#undef freopen /* Get back the REAL fopen routine */ +#undef freopen /* Get back the real freopen routine. */ if (strcmp (type, "w") == 0) - return freopen (fname, type, oldfile, "mbc=16", "deq=64", "fop=tef", "shr=nil"); + return freopen (fname, type, oldfile, + "mbc=16", "deq=64", "fop=tef", "shr=nil"); return freopen (fname, type, oldfile, "mbc=16"); } static FILE * -fopen (fname, type) +VMS_fopen (fname, type) char *fname; char *type; { -#undef fopen /* Get back the REAL fopen routine */ +#undef fopen /* Get back the real fopen routine. */ /* The gcc-vms-1.42 distribution's header files prototype fopen with two fixed arguments, which matches ANSI's specification but not VAXCRTL's pre-ANSI implementation. This hack circumvents the mismatch problem. */ @@ -10330,40 +10718,20 @@ fopen (fname, type) } static int -open (fname, flags, prot) +VMS_open (fname, flags, prot) char *fname; int flags; int prot; { -#undef open /* Get back the REAL open routine */ +#undef open /* Get back the real open routine. */ return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef"); } - -/* Avoid run-time library bug, where copying M out of N+M characters with - N >= 65535 results in VAXCRTL's strncat falling into an infinite loop. - gcc-cpp exercises this particular bug. [Fixed in V5.5-2's VAXCRTL.] */ - -static char * -strncat (dst, src, cnt) - char *dst; - const char *src; - unsigned cnt; -{ - register char *d = dst, *s = (char *) src; - register int n = cnt; /* convert to _signed_ type */ - - while (*d) d++; /* advance to end */ - while (--n >= 0) - if (!(*d++ = *s++)) break; - if (n < 0) *d = '\0'; - return dst; -} /* more VMS hackery */ #include #include -extern unsigned long sys$parse(), sys$search(); +extern unsigned long SYS$PARSE(), SYS$SEARCH(); /* Work around another library bug. If a file is located via a searchlist, and if the device it's on is not the same device as the one specified @@ -10377,7 +10745,7 @@ extern unsigned long sys$parse(), sys$search(); bad enough, but then compounding the problem by reporting the reason for failure as "normal successful completion." */ -#undef fstat /* get back to library version */ +#undef fstat /* Get back to the library version. */ static int VMS_fstat (fd, statbuf) @@ -10410,8 +10778,8 @@ VMS_stat (name, statbuf) { struct FAB fab; struct NAM nam; - char exp_nam[NAM$C_MAXRSS+1], /* expanded name buffer for sys$parse */ - res_nam[NAM$C_MAXRSS+1]; /* resultant name buffer for sys$search */ + char exp_nam[NAM$C_MAXRSS+1], /* expanded name buffer for SYS$PARSE */ + res_nam[NAM$C_MAXRSS+1]; /* resultant name buffer for SYS$SEARCH */ fab = cc$rms_fab; fab.fab$l_fna = (char *) name; @@ -10421,9 +10789,9 @@ VMS_stat (name, statbuf) nam.nam$l_esa = exp_nam, nam.nam$b_ess = sizeof exp_nam - 1; nam.nam$l_rsa = res_nam, nam.nam$b_rss = sizeof res_nam - 1; nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL; - if (sys$parse (&fab) & 1) + if (SYS$PARSE (&fab) & 1) { - if (sys$search (&fab) & 1) + if (SYS$SEARCH (&fab) & 1) { res_nam[nam.nam$b_rsl] = '\0'; result = stat (res_nam, statbuf); @@ -10431,7 +10799,7 @@ VMS_stat (name, statbuf) /* Clean up searchlist context cached by the system. */ nam.nam$b_nop = NAM$M_SYNCHK; fab.fab$l_fna = 0, fab.fab$b_fns = 0; - (void) sys$parse (&fab); + (void) SYS$PARSE (&fab); } } diff --git a/contrib/gcc/cexp.y b/contrib/gcc/cexp.y index d83de80..6280aed 100644 --- a/contrib/gcc/cexp.y +++ b/contrib/gcc/cexp.y @@ -1,5 +1,5 @@ /* Parse C expressions for CCCP. - Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation. + Copyright (C) 1987, 1992, 94 - 97, 1998 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,15 +26,25 @@ Boston, MA 02111-1307, USA. %{ #include "config.h" +#ifdef __STDC__ +# include +#else +# include +#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 /* #define YYDEBUG 1 */ #ifdef MULTIBYTE_CHARS -#include #include #endif -#include +#include "gansidecl.h" typedef unsigned char U_CHAR; @@ -46,42 +56,48 @@ struct arglist { int argno; }; -/* Define a generic NULL if one hasn't already been defined. */ - -#ifndef NULL -#define NULL 0 +/* 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 +# 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 GENERIC_PTR -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#define GENERIC_PTR void * -#else -#define GENERIC_PTR char * -#endif +#ifndef unsigned_HOST_WIDE_INT +#define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT #endif -/* Find the largest host integer type and set its size and type. */ +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif #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 +#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT)) #endif -#endif +HOST_WIDE_INT parse_c_expression PROTO((char *, int)); -#ifndef NULL_PTR -#define NULL_PTR ((GENERIC_PTR)0) +static int yylex PROTO((void)); +static void yyerror PROTO((char *)) __attribute__ ((noreturn)); +static HOST_WIDE_INT expression_value; +#ifdef TEST_EXP_READER +static int expression_signedp; #endif -int yylex (); -void yyerror (); -HOST_WIDE_INT expression_value; - static jmp_buf parse_return_error; /* Nonzero means count most punctuation as part of a name. */ @@ -91,10 +107,11 @@ static int keyword_parsing = 0; This is a count, since unevaluated expressions can nest. */ static int skip_evaluation; -/* some external tables of character types */ -extern unsigned char is_idstart[], is_idchar[], is_hor_space[]; +/* Nonzero means warn if undefined identifiers are evaluated. */ +static int warn_undef; -extern char *xmalloc (); +/* some external tables of character types */ +extern unsigned char is_idstart[], is_idchar[], is_space[]; /* Flag for -pedantic. */ extern int pedantic; @@ -102,6 +119,9 @@ extern int pedantic; /* Flag for -traditional. */ extern int traditional; +/* Flag for -lang-c89. */ +extern int c89; + #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT #endif @@ -134,17 +154,46 @@ extern int traditional; #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE #endif -/* 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 (); -static long left_shift (); -static long right_shift (); +#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_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ + ? ~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE) \ + : ~ (HOST_WIDE_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. + Suppose SIGNEDP is negative if the result is signed, zero if unsigned. + Then this yields nonzero if overflow occurred during the addition. + Overflow occurs if A and B have the same sign, but A and SUM differ in sign, + and SIGNEDP is negative. + Use `^' to test whether signs differ, and `< 0' to isolate the sign. */ +#define overflow_sum_sign(a, b, sum, signedp) \ + ((~((a) ^ (b)) & ((a) ^ (sum)) & (signedp)) < 0) + +struct constant; + +GENERIC_PTR xmalloc PROTO((size_t)); +HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_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 *, ...)); + +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 void integer_overflow PROTO((void)); + +/* `signedp' values */ +#define SIGNED (~0) +#define UNSIGNED 0 %} %union { - struct constant {long value; int unsignedp;} integer; + struct constant {HOST_WIDE_INT value; int signedp;} integer; struct name {U_CHAR *address; int length;} name; struct arglist *keywords; } @@ -174,7 +223,12 @@ static long right_shift (); %% start : exp1 - { expression_value = $1.value; } + { + expression_value = $1.value; +#ifdef TEST_EXP_READER + expression_signedp = $1.signedp; +#endif + } ; /* Expressions, including the comma operator. */ @@ -188,45 +242,46 @@ exp1 : exp /* Expressions, not including the comma operator. */ exp : '-' exp %prec UNARY { $$.value = - $2.value; - if (($$.value & $2.value) < 0 && ! $2.unsignedp) - integer_overflow (); - $$.unsignedp = $2.unsignedp; } + $$.signedp = $2.signedp; + if (($$.value & $2.value & $$.signedp) < 0) + integer_overflow (); } | '!' exp %prec UNARY { $$.value = ! $2.value; - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | '+' exp %prec UNARY { $$ = $2; } | '~' exp %prec UNARY { $$.value = ~ $2.value; - $$.unsignedp = $2.unsignedp; } + $$.signedp = $2.signedp; } | '#' NAME { $$.value = check_assertion ($2.address, $2.length, 0, NULL_PTR); - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | '#' NAME { keyword_parsing = 1; } '(' keywords ')' { $$.value = check_assertion ($2.address, $2.length, 1, $5); keyword_parsing = 0; - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | '(' exp1 ')' { $$ = $2; } ; /* Binary operators in order of decreasing precedence. */ exp : exp '*' exp - { $$.unsignedp = $1.unsignedp || $3.unsignedp; - if ($$.unsignedp) - $$.value = (unsigned long) $1.value * $3.value; - else + { $$.signedp = $1.signedp & $3.signedp; + if ($$.signedp) { $$.value = $1.value * $3.value; if ($1.value && ($$.value / $1.value != $3.value || ($$.value & $1.value & $3.value) < 0)) integer_overflow (); - } } + } + else + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + * $3.value); } | exp '/' exp { if ($3.value == 0) { @@ -234,15 +289,16 @@ exp : exp '*' exp error ("division by zero in #if"); $3.value = 1; } - $$.unsignedp = $1.unsignedp || $3.unsignedp; - if ($$.unsignedp) - $$.value = (unsigned long) $1.value / $3.value; - else + $$.signedp = $1.signedp & $3.signedp; + if ($$.signedp) { $$.value = $1.value / $3.value; if (($$.value & $1.value & $3.value) < 0) integer_overflow (); - } } + } + else + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + / $3.value); } | exp '%' exp { if ($3.value == 0) { @@ -250,88 +306,91 @@ exp : exp '*' exp error ("division by zero in #if"); $3.value = 1; } - $$.unsignedp = $1.unsignedp || $3.unsignedp; - if ($$.unsignedp) - $$.value = (unsigned long) $1.value % $3.value; + $$.signedp = $1.signedp & $3.signedp; + if ($$.signedp) + $$.value = $1.value % $3.value; else - $$.value = $1.value % $3.value; } + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + % $3.value); } | exp '+' exp { $$.value = $1.value + $3.value; - $$.unsignedp = $1.unsignedp || $3.unsignedp; - if (! $$.unsignedp - && ! possible_sum_sign ($1.value, $3.value, - $$.value)) + $$.signedp = $1.signedp & $3.signedp; + if (overflow_sum_sign ($1.value, $3.value, + $$.value, $$.signedp)) integer_overflow (); } | exp '-' exp { $$.value = $1.value - $3.value; - $$.unsignedp = $1.unsignedp || $3.unsignedp; - if (! $$.unsignedp - && ! possible_sum_sign ($$.value, $3.value, - $1.value)) + $$.signedp = $1.signedp & $3.signedp; + if (overflow_sum_sign ($$.value, $3.value, + $1.value, $$.signedp)) integer_overflow (); } | exp LSH exp - { $$.unsignedp = $1.unsignedp; - if ($3.value < 0 && ! $3.unsignedp) + { $$.signedp = $1.signedp; + if (($3.value & $3.signedp) < 0) $$.value = right_shift (&$1, -$3.value); else $$.value = left_shift (&$1, $3.value); } | exp RSH exp - { $$.unsignedp = $1.unsignedp; - if ($3.value < 0 && ! $3.unsignedp) + { $$.signedp = $1.signedp; + if (($3.value & $3.signedp) < 0) $$.value = left_shift (&$1, -$3.value); else $$.value = right_shift (&$1, $3.value); } | exp EQUAL exp { $$.value = ($1.value == $3.value); - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | exp NOTEQUAL exp { $$.value = ($1.value != $3.value); - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | exp LEQ exp - { $$.unsignedp = 0; - if ($1.unsignedp || $3.unsignedp) - $$.value = (unsigned long) $1.value <= $3.value; + { $$.signedp = SIGNED; + if ($1.signedp & $3.signedp) + $$.value = $1.value <= $3.value; else - $$.value = $1.value <= $3.value; } + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + <= $3.value); } | exp GEQ exp - { $$.unsignedp = 0; - if ($1.unsignedp || $3.unsignedp) - $$.value = (unsigned long) $1.value >= $3.value; + { $$.signedp = SIGNED; + if ($1.signedp & $3.signedp) + $$.value = $1.value >= $3.value; else - $$.value = $1.value >= $3.value; } + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + >= $3.value); } | exp '<' exp - { $$.unsignedp = 0; - if ($1.unsignedp || $3.unsignedp) - $$.value = (unsigned long) $1.value < $3.value; + { $$.signedp = SIGNED; + if ($1.signedp & $3.signedp) + $$.value = $1.value < $3.value; else - $$.value = $1.value < $3.value; } + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + < $3.value); } | exp '>' exp - { $$.unsignedp = 0; - if ($1.unsignedp || $3.unsignedp) - $$.value = (unsigned long) $1.value > $3.value; + { $$.signedp = SIGNED; + if ($1.signedp & $3.signedp) + $$.value = $1.value > $3.value; else - $$.value = $1.value > $3.value; } + $$.value = ((unsigned_HOST_WIDE_INT) $1.value + > $3.value); } | exp '&' exp { $$.value = $1.value & $3.value; - $$.unsignedp = $1.unsignedp || $3.unsignedp; } + $$.signedp = $1.signedp & $3.signedp; } | exp '^' exp { $$.value = $1.value ^ $3.value; - $$.unsignedp = $1.unsignedp || $3.unsignedp; } + $$.signedp = $1.signedp & $3.signedp; } | exp '|' exp { $$.value = $1.value | $3.value; - $$.unsignedp = $1.unsignedp || $3.unsignedp; } + $$.signedp = $1.signedp & $3.signedp; } | exp AND { skip_evaluation += !$1.value; } exp { skip_evaluation -= !$1.value; $$.value = ($1.value && $4.value); - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | exp OR { skip_evaluation += !!$1.value; } exp { skip_evaluation -= !!$1.value; $$.value = ($1.value || $4.value); - $$.unsignedp = 0; } + $$.signedp = SIGNED; } | exp '?' { skip_evaluation += !$1.value; } exp ':' @@ -339,14 +398,17 @@ exp : exp '*' exp exp { skip_evaluation -= !!$1.value; $$.value = $1.value ? $4.value : $7.value; - $$.unsignedp = $4.unsignedp || $7.unsignedp; } + $$.signedp = $4.signedp & $7.signedp; } | INT { $$ = yylval.integer; } | CHAR { $$ = yylval.integer; } | NAME - { $$.value = 0; - $$.unsignedp = 0; } + { if (warn_undef && !skip_evaluation) + warning ("`%.*s' is not defined", + $1.length, $1.address); + $$.value = 0; + $$.signedp = SIGNED; } ; keywords : @@ -383,37 +445,31 @@ static char *lexptr; /* maybe needs to actually deal with floating point numbers */ -int +static int parse_number (olen) int olen; { register char *p = lexptr; register int c; - register unsigned long n = 0, nd, ULONG_MAX_over_base; + register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base; register int base = 10; register int len = olen; register int overflow = 0; register int digit, largest_digit = 0; int spec_long = 0; - for (c = 0; c < len; c++) - if (p[c] == '.') { - /* It's a float since it contains a point. */ - yyerror ("floating point numbers not allowed in #if expressions"); - return ERROR; - } - - yylval.integer.unsignedp = 0; + yylval.integer.signedp = SIGNED; - if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) { - p += 2; - base = 16; - len -= 2; - } - else if (*p == '0') + if (*p == '0') { base = 8; + if (len >= 3 && (p[1] == 'x' || p[1] == 'X')) { + p += 2; + base = 16; + len -= 2; + } + } - ULONG_MAX_over_base = (unsigned long) -1 / base; + max_over_base = (unsigned_HOST_WIDE_INT) -1 / base; for (; len > 0; len--) { c = *p++; @@ -429,18 +485,26 @@ parse_number (olen) while (1) { if (c == 'l' || c == 'L') { - if (spec_long) - yyerror ("two `l's in integer constant"); - spec_long = 1; + if (!pedantic < spec_long) + yyerror ("too many `l's in integer constant"); + spec_long++; } else if (c == 'u' || c == 'U') { - if (yylval.integer.unsignedp) + if (! yylval.integer.signedp) yyerror ("two `u's in integer constant"); - yylval.integer.unsignedp = 1; + yylval.integer.signedp = UNSIGNED; } - else - break; + 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'", + (int) (p - lexptr - 1), lexptr); + yyerror (buf); + } + } if (--len == 0) break; @@ -452,27 +516,22 @@ parse_number (olen) if (largest_digit < digit) largest_digit = digit; nd = n * base + digit; - overflow |= ULONG_MAX_over_base < n | nd < n; + overflow |= (max_over_base < n) | (nd < n); n = nd; } - if (len != 0) { - yyerror ("Invalid number in #if expression"); - return ERROR; - } - if (base <= largest_digit) - warning ("integer constant contains digits beyond the radix"); + pedwarn ("integer constant contains digits beyond the radix"); if (overflow) - warning ("integer constant out of range"); + pedwarn ("integer constant out of range"); /* If too big to be signed, consider it unsigned. */ - if ((long) n < 0 && ! yylval.integer.unsignedp) + if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0) { if (base == 10) warning ("integer constant is so large that it is unsigned"); - yylval.integer.unsignedp = 1; + yylval.integer.signedp = UNSIGNED; } lexptr = p; @@ -501,7 +560,7 @@ static struct token tokentab2[] = { /* Read one token, getting characters through lexptr. */ -int +static int yylex () { register int c; @@ -509,6 +568,7 @@ yylex () register unsigned char *tokstart; register struct token *toktab; int wide_flag; + HOST_WIDE_INT mask; retry: @@ -529,13 +589,12 @@ yylex () } switch (c) { - case 0: + case '\n': return 0; case ' ': case '\t': case '\r': - case '\n': lexptr++; goto retry; @@ -545,18 +604,21 @@ yylex () { lexptr++; wide_flag = 1; + mask = MAX_WCHAR_TYPE_MASK; goto char_constant; } if (lexptr[1] == '"') { lexptr++; wide_flag = 1; + mask = MAX_WCHAR_TYPE_MASK; goto string_constant; } break; case '\'': wide_flag = 0; + mask = MAX_CHAR_TYPE_MASK; char_constant: lexptr++; if (keyword_parsing) { @@ -564,7 +626,7 @@ yylex () while (1) { c = *lexptr++; if (c == '\\') - c = parse_escape (&lexptr); + c = parse_escape (&lexptr, mask); else if (c == '\'') break; } @@ -577,8 +639,8 @@ yylex () handles multicharacter constants and wide characters. It is mostly copied from c-lex.c. */ { - register int result = 0; - register num_chars = 0; + register HOST_WIDE_INT result = 0; + register int num_chars = 0; unsigned width = MAX_CHAR_TYPE_SIZE; int max_chars; char *token_buffer; @@ -606,19 +668,16 @@ yylex () if (c == '\\') { - c = parse_escape (&lexptr); - if (width < HOST_BITS_PER_INT - && (unsigned) c >= (1 << width)) - pedwarn ("escape sequence out of range for character"); + c = parse_escape (&lexptr, mask); } num_chars++; /* Merge character into result; ignore excess chars. */ - if (num_chars < max_chars + 1) + if (num_chars <= max_chars) { - if (width < HOST_BITS_PER_INT) - result = (result << width) | (c & ((1 << width) - 1)); + if (width < HOST_BITS_PER_WIDE_INT) + result = (result << width) | c; else result = c; token_buffer[num_chars - 1] = c; @@ -644,13 +703,16 @@ yylex () { int num_bits = num_chars * width; - if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1) + if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__", + sizeof ("__CHAR_UNSIGNED__") - 1, -1) || ((result >> (num_bits - 1)) & 1) == 0) yylval.integer.value - = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); + = result & (~ (unsigned_HOST_WIDE_INT) 0 + >> (HOST_BITS_PER_WIDE_INT - num_bits)); else yylval.integer.value - = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); + = result | ~(~ (unsigned_HOST_WIDE_INT) 0 + >> (HOST_BITS_PER_WIDE_INT - num_bits)); } else { @@ -667,7 +729,7 @@ yylex () if (mbtowc (& wc, token_buffer, num_chars) == num_chars) result = wc; else - warning ("Ignoring invalid multibyte character"); + pedwarn ("Ignoring invalid multibyte character"); } #endif yylval.integer.value = result; @@ -675,7 +737,7 @@ yylex () } /* This is always a signed type. */ - yylval.integer.unsignedp = 0; + yylval.integer.signedp = SIGNED; return CHAR; @@ -712,6 +774,7 @@ yylex () return c; case '"': + mask = MAX_CHAR_TYPE_MASK; string_constant: if (keyword_parsing) { char *start_ptr = lexptr; @@ -719,7 +782,7 @@ yylex () while (1) { c = *lexptr++; if (c == '\\') - c = parse_escape (&lexptr); + c = parse_escape (&lexptr, mask); else if (c == '"') break; } @@ -733,10 +796,16 @@ yylex () if (c >= '0' && c <= '9' && !keyword_parsing) { /* It's a number */ - for (namelen = 0; - c = tokstart[namelen], is_idchar[c] || c == '.'; - namelen++) - ; + for (namelen = 1; ; namelen++) { + int d = tokstart[namelen]; + if (! ((is_idchar[d] || d == '.') + || ((d == '-' || d == '+') + && (c == 'e' || c == 'E' + || ((c == 'p' || c == 'P') && ! c89)) + && ! traditional))) + break; + c = d; + } return parse_number (namelen); } @@ -744,7 +813,7 @@ yylex () if (keyword_parsing) { for (namelen = 0;; namelen++) { - if (is_hor_space[tokstart[namelen]]) + if (is_space[tokstart[namelen]]) break; if (tokstart[namelen] == '(' || tokstart[namelen] == ')') break; @@ -773,6 +842,9 @@ yylex () is updated past the characters we use. The value of the escape sequence is returned. + RESULT_MASK is used to mask out the result; + an error is reported if bits are lost thereby. + A negative value means the sequence \ newline was seen, which is supposed to be equivalent to nothing at all. @@ -782,9 +854,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. */ -int -parse_escape (string_ptr) +HOST_WIDE_INT +parse_escape (string_ptr, result_mask) char **string_ptr; + HOST_WIDE_INT result_mask; { register int c = *(*string_ptr)++; switch (c) @@ -823,7 +896,7 @@ parse_escape (string_ptr) case '6': case '7': { - register int i = c - '0'; + register HOST_WIDE_INT i = c - '0'; register int count = 0; while (++count < 3) { @@ -836,16 +909,17 @@ parse_escape (string_ptr) break; } } - if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) + if (i != (i & result_mask)) { - i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; - warning ("octal character constant does not fit in a byte"); + i &= result_mask; + pedwarn ("octal escape sequence out of range"); } return i; } case 'x': { - register unsigned i = 0, overflow = 0, digits_found = 0, digit; + register unsigned_HOST_WIDE_INT i = 0, overflow = 0; + register int digits_found = 0, digit; for (;;) { c = *(*string_ptr)++; @@ -866,10 +940,10 @@ parse_escape (string_ptr) } if (!digits_found) yyerror ("\\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; - warning ("hex character constant does not fit in a byte"); + i &= result_mask; + pedwarn ("hex escape sequence out of range"); } return i; } @@ -878,11 +952,11 @@ parse_escape (string_ptr) } } -void +static void yyerror (s) char *s; { - error (s); + error ("%s", s); skip_evaluation = 0; longjmp (parse_return_error, 1); } @@ -894,52 +968,50 @@ integer_overflow () pedwarn ("integer overflow in preprocessor expression"); } -static long +static HOST_WIDE_INT left_shift (a, b) struct constant *a; - unsigned long b; + unsigned_HOST_WIDE_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_LONG) + if (b >= HOST_BITS_PER_WIDE_INT) return 0; - else if (a->unsignedp) - return (unsigned long) a->value << b; else - return a->value << b; + return (unsigned_HOST_WIDE_INT) a->value << b; } -static long +static HOST_WIDE_INT right_shift (a, b) struct constant *a; - unsigned long b; + unsigned_HOST_WIDE_INT b; { - if (b >= HOST_BITS_PER_LONG) - return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1); - else if (a->unsignedp) - return (unsigned long) a->value >> b; - else + if (b >= HOST_BITS_PER_WIDE_INT) + return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0; + else if (a->signedp) return a->value >> b; + else + return (unsigned_HOST_WIDE_INT) a->value >> b; } /* This page contains the entry point to this file. */ /* Parse STRING as an expression, and complain if this fails - to use up all of the contents of STRING. */ -/* We do not support C comments. They should be removed before + to use up all of the contents of STRING. + STRING may contain '\0' bytes; it is terminated by the first '\n' + outside a string constant, so that we can diagnose '\0' properly. + If WARN_UNDEFINED is nonzero, warn if undefined identifiers are evaluated. + We do not support C comments. They should be removed before this function is called. */ HOST_WIDE_INT -parse_c_expression (string) +parse_c_expression (string, warn_undefined) char *string; + int warn_undefined; { lexptr = string; - - if (lexptr == 0 || *lexptr == 0) { - error ("empty #if expression"); - return 0; /* don't include the #if group */ - } + warn_undef = warn_undefined; /* if there is some sort of scanning error, just return 0 and assume the parsing routine has printed an error message somewhere. @@ -947,55 +1019,92 @@ parse_c_expression (string) if (setjmp (parse_return_error)) return 0; - if (yyparse ()) - return 0; /* actually this is never reached - the way things stand. */ - if (*lexptr) + if (yyparse () != 0) + abort (); + + if (*lexptr != '\n') error ("Junk after end of expression."); return expression_value; /* set by yyparse () */ } #ifdef TEST_EXP_READER + +#if YYDEBUG extern int yydebug; +#endif + +int pedantic; +int traditional; + +int main PROTO((int, char **)); +static void initialize_random_junk PROTO((void)); +static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT)); /* Main program for testing purposes. */ int -main () +main (argc, argv) + int argc; + char **argv; { int n, c; char buf[1024]; + unsigned_HOST_WIDE_INT u; -/* - yydebug = 1; -*/ + pedantic = 1 < argc; + traditional = 2 < argc; +#if YYDEBUG + yydebug = 3 < argc; +#endif initialize_random_junk (); for (;;) { printf ("enter expression: "); n = 0; - while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF) + while ((buf[n] = c = getchar ()) != '\n' && c != EOF) n++; - if (buf[n] == EOF) + if (c == EOF) break; - buf[n] = '\0'; - printf ("parser returned %ld\n", parse_c_expression (buf)); + parse_c_expression (buf, 1); + printf ("parser returned "); + u = (unsigned_HOST_WIDE_INT) expression_value; + if (expression_value < 0 && expression_signedp) { + u = -u; + printf ("-"); + } + if (u == 0) + printf ("0"); + else + print_unsigned_host_wide_int (u); + if (! expression_signedp) + printf("u"); + printf ("\n"); } return 0; } +static void +print_unsigned_host_wide_int (u) + unsigned_HOST_WIDE_INT u; +{ + if (u) { + print_unsigned_host_wide_int (u / 10); + putchar ('0' + (int) (u % 10)); + } +} + /* table to tell if char can be part of a C identifier. */ unsigned char is_idchar[256]; /* table to tell if char can be first char of a c identifier. */ unsigned char is_idstart[256]; -/* table to tell if c is horizontal space. isspace () thinks that - newline is space; this is not a good idea for this program. */ -char is_hor_space[256]; +/* table to tell if c is horizontal or vertical space. */ +unsigned char is_space[256]; /* * initialize random junk in the hash table and maybe other places */ +static void initialize_random_junk () { register int i; @@ -1016,32 +1125,100 @@ initialize_random_junk () ++is_idchar[i]; ++is_idchar['_']; ++is_idstart['_']; -#if DOLLARS_IN_IDENTIFIERS ++is_idchar['$']; ++is_idstart['$']; + + ++is_space[' ']; + ++is_space['\t']; + ++is_space['\v']; + ++is_space['\f']; + ++is_space['\n']; + ++is_space['\r']; +} + +void +error VPROTO ((char * msg, ...)) +{ +#ifndef __STDC__ + char * msg; #endif + va_list args; - /* horizontal space table */ - ++is_hor_space[' ']; - ++is_hor_space['\t']; + VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + + fprintf (stderr, "error: "); + vfprintf (stderr, msg, args); + fprintf (stderr, "\n"); + va_end (args); } -error (msg) +void +pedwarn VPROTO ((char * msg, ...)) { - printf ("error: %s\n", msg); +#ifndef __STDC__ + char * msg; +#endif + va_list args; + + VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + + fprintf (stderr, "pedwarn: "); + vfprintf (stderr, msg, args); + fprintf (stderr, "\n"); + va_end (args); } -warning (msg) +void +warning VPROTO ((char * msg, ...)) { - printf ("warning: %s\n", msg); +#ifndef __STDC__ + char * msg; +#endif + va_list args; + + VA_START (args, msg); + +#ifndef __STDC__ + msg = va_arg (args, char *); +#endif + + fprintf (stderr, "warning: "); + vfprintf (stderr, msg, args); + fprintf (stderr, "\n"); + va_end (args); +} + +int +check_assertion (name, sym_length, tokens_specified, tokens) + U_CHAR *name; + int sym_length; + int tokens_specified; + struct arglist *tokens; +{ + return 0; } struct hashnode * lookup (name, len, hash) - char *name; + U_CHAR *name; int len; int hash; { return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1); } + +GENERIC_PTR +xmalloc (size) + size_t size; +{ + return (GENERIC_PTR) malloc (size); +} #endif diff --git a/contrib/gcc/choose-temp.c b/contrib/gcc/choose-temp.c new file mode 100644 index 0000000..4629336 --- /dev/null +++ b/contrib/gcc/choose-temp.c @@ -0,0 +1,211 @@ +/* Utility to pick a temporary filename prefix. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty 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. + +Libiberty 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 libiberty; see the file COPYING.LIB. If not, +write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file exports two functions: choose_temp_base and make_temp_file. */ + +/* This file lives in at least two places: libiberty and gcc. + Don't change one without the other. */ + +#if defined (IN_GCC) || defined (HAVE_CONFIG_H) +#include "config.h" +#endif + +#ifdef IN_GCC +#include "system.h" +#else + +/* If we are in gcc, system.h has handled everything. When not in + gcc, if we have a config.h we assume that HAVE_SYS_FILE_H tells us + whether to include sys/file.h. However, libiberty does not have a + config.h, and instead arranges to define NO_SYS_FILE_H on the + command line when there is no sys/file.h. */ + +#if defined (HAVE_CONFIG_H) ? defined (HAVE_SYS_FILE_H) : ! defined (NO_SYS_FILE_H) +#include +#include /* May get R_OK, etc. on some systems. */ +#endif + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#endif + +#include /* May get P_tmpdir. */ +#endif /* IN_GCC */ + +#ifdef IN_GCC +#include "gansidecl.h" +extern char *xmalloc (); +#else +#include "ansidecl.h" +#include "libiberty.h" +#if defined (__MSDOS__) || defined (_WIN32) +#define DIR_SEPARATOR '\\' +#endif +#endif + +#ifndef DIR_SEPARATOR +#define DIR_SEPARATOR '/' +#endif + +/* On MSDOS, write temp files in current dir + because there's no place else we can expect to use. */ +/* ??? Although the current directory is tried as a last resort, + this is left in so that on MSDOS it is preferred to /tmp on the + off chance that someone requires this, since that was the previous + behaviour. */ +#ifdef __MSDOS__ +#ifndef P_tmpdir +#define P_tmpdir "." +#endif +#endif + +/* Name of temporary file. + mktemp requires 6 trailing X's. */ +#define TEMP_FILE "ccXXXXXX" + +/* Subroutine of choose_temp_base. + If BASE is non-NULL, return it. + Otherwise it checks if DIR is a usable directory. + If success, DIR is returned. + Otherwise NULL is returned. */ + +static char * +try (dir, base) + char *dir, *base; +{ + if (base != 0) + return base; + if (dir != 0 + && access (dir, R_OK | W_OK | X_OK) == 0) + return dir; + return 0; +} + +/* Return a prefix for temporary file names or NULL if unable to find one. + The current directory is chosen if all else fails so the program is + exited if a temporary directory can't be found (mktemp fails). + The buffer for the result is obtained with xmalloc. + + This function is provided for backwards compatability only. It use + is not recommended. */ + +char * +choose_temp_base () +{ + char *base = 0; + char *temp_filename; + int len; + static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 }; + static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 }; + + base = try (getenv ("TMPDIR"), base); + base = try (getenv ("TMP"), base); + base = try (getenv ("TEMP"), base); + +#ifdef P_tmpdir + base = try (P_tmpdir, base); +#endif + + /* Try /usr/tmp, then /tmp. */ + base = try (usrtmp, base); + base = try (tmp, base); + + /* If all else fails, use the current directory! */ + if (base == 0) + base = "."; + + len = strlen (base); + temp_filename = xmalloc (len + 1 /*DIR_SEPARATOR*/ + + strlen (TEMP_FILE) + 1); + strcpy (temp_filename, base); + + if (len != 0 + && temp_filename[len-1] != '/' + && temp_filename[len-1] != DIR_SEPARATOR) + temp_filename[len++] = DIR_SEPARATOR; + strcpy (temp_filename + len, TEMP_FILE); + + mktemp (temp_filename); + if (strlen (temp_filename) == 0) + abort (); + return temp_filename; +} +/* Return a temporary file name (as a string) or NULL if unable to create + one. */ + +char * +make_temp_file (suffix) + char *suffix; +{ + char *base = 0; + char *temp_filename; + int base_len, suffix_len; + int fd; + static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 }; + static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 }; + + base = try (getenv ("TMPDIR"), base); + base = try (getenv ("TMP"), base); + base = try (getenv ("TEMP"), base); + +#ifdef P_tmpdir + base = try (P_tmpdir, base); +#endif + + /* Try /usr/tmp, then /tmp. */ + base = try (usrtmp, base); + base = try (tmp, base); + + /* If all else fails, use the current directory! */ + if (base == 0) + base = "."; + + base_len = strlen (base); + + if (suffix) + suffix_len = strlen (suffix); + else + suffix_len = 0; + + temp_filename = xmalloc (base_len + 1 /*DIR_SEPARATOR*/ + + strlen (TEMP_FILE) + + suffix_len + 1); + strcpy (temp_filename, base); + + if (base_len != 0 + && temp_filename[base_len-1] != '/' + && temp_filename[base_len-1] != DIR_SEPARATOR) + temp_filename[base_len++] = DIR_SEPARATOR; + strcpy (temp_filename + base_len, TEMP_FILE); + + if (suffix) + strcat (temp_filename, suffix); + + fd = mkstemps (temp_filename, suffix_len); + /* If mkstemps failed, then something bad is happening. Maybe we should + issue a message about a possible security attack in progress? */ + if (fd == -1) + abort (); + /* Similarly if we can not close the file. */ + if (close (fd)) + abort (); + return temp_filename; +} diff --git a/contrib/gcc/collect2.c b/contrib/gcc/collect2.c index 30fb49d..4fcbe73 100644 --- a/contrib/gcc/collect2.c +++ b/contrib/gcc/collect2.c @@ -1,8 +1,6 @@ -/* Collect static initialization info into data structures - that can be traversed by C++ initialization and finalization - routines. - - Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +/* 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. 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). @@ -25,67 +23,30 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Build tables of static constructors and destructors and run ld. */ +/* Build tables of static constructors and destructors and run ld. */ #include "config.h" -#include -#include -#include -#include +#include "system.h" #include -#include #include -#ifdef NO_WAIT_H -#include -#endif #define COLLECT #include "demangle.h" #include "obstack.h" - -#ifndef errno -extern int errno; -#endif - -#ifndef HAVE_STRERROR -#if defined(bsd4_4) -extern const char *const sys_errlist[]; -#else -extern char *sys_errlist[]; -#endif -extern int sys_nerr; -#else -char *strerror(); +#include "gansidecl.h" +#ifdef __CYGWIN32__ +#include #endif /* Obstack allocation and deallocation routines. */ #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free -#if !defined (__STDC__) && !defined (const) -#define const -#endif - #ifdef USG #define vfork fork #endif -/* Add prototype support. */ -#ifndef PROTO -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#define PROTO(ARGS) ARGS -#else -#define PROTO(ARGS) () -#endif -#endif - -#ifndef R_OK -#define R_OK 4 -#define W_OK 2 -#define X_OK 1 -#endif - #ifndef WIFSIGNALED #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f) #endif @@ -99,18 +60,12 @@ char *strerror(); #define WEXITSTATUS(S) (((S) & 0xff00) >> 8) #endif -/* On MSDOS, write temp files in current dir - because there's no place else we can expect to use. */ -#ifdef __MSDOS__ -#ifndef P_tmpdir -#define P_tmpdir "./" -#endif -#endif +extern char *make_temp_file PROTO ((char *)); /* On certain systems, we have code that works by scanning the object file directly. But this code uses system-specific header files and library functions, so turn it off in a cross-compiler. Likewise, the names of - the utilities aren't correct for a cross-compiler; we have to hope that + the utilities are not correct for a cross-compiler; we have to hope that cross-versions are in the proper directories. */ #ifdef CROSS_COMPILE @@ -123,10 +78,10 @@ char *strerror(); #undef REAL_STRIP_FILE_NAME #endif -/* If we can't use a special method, use the ordinary one: +/* If we cannot use a special method, use the ordinary one: run nm to find what symbols are present. In a cross-compiler, this means you need a cross nm, - but that isn't quite as unpleasant as special headers. */ + but that is not quite as unpleasant as special headers. */ #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE) #define OBJECT_FORMAT_NONE @@ -158,10 +113,6 @@ char *strerror(); #define MY_ISCOFF(X) ISCOFF (X) #endif -#ifdef XCOFF_DEBUGGING_INFO -#define XCOFF_SCAN_LIBS -#endif - #endif /* OBJECT_FORMAT_COFF */ #ifdef OBJECT_FORMAT_ROSE @@ -200,7 +151,7 @@ char *strerror(); #define SYMBOL__MAIN __main #endif -#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES || defined(XCOFF_SCAN_LIBS) +#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES #define SCAN_LIBRARIES #endif @@ -210,7 +161,7 @@ int do_collecting = 1; int do_collecting = 0; #endif -/* Linked lists of constructor and destructor names. */ +/* Linked lists of constructor and destructor names. */ struct id { @@ -236,7 +187,7 @@ enum pass { }; #ifndef NO_SYS_SIGLIST -#ifndef DONT_DECLARE_SYS_SIGLIST +#ifndef SYS_SIGLIST_DECLARED extern char *sys_siglist[]; #endif #endif @@ -245,27 +196,39 @@ extern char *version_string; int vflag; /* true if -v */ static int rflag; /* true if -r */ static int strip_flag; /* true if -s */ +#ifdef COLLECT_EXPORT_LIST +static int export_flag; /* true if -bE */ +static int aix64_flag; /* true if -b64 */ +#endif int debug; /* true if -debug */ static int shared_obj; /* true if -shared */ -static int temp_filename_length; /* Length of temp_filename */ -static char *temp_filename; /* Base of temp filenames */ -static char *c_file; /* .c for constructor/destructor list. */ -static char *o_file; /* .o for constructor/destructor list. */ -static char *export_file; /* .x for AIX export list. */ +static char *c_file; /* .c for constructor/destructor list. */ +static char *o_file; /* .o for constructor/destructor list. */ +#ifdef COLLECT_EXPORT_LIST +static char *export_file; /* .x for AIX export list. */ +static char *import_file; /* .p for AIX import list. */ +#endif char *ldout; /* File for ld errors. */ static char *output_file; /* Output file for ld. */ static char *nm_file_name; /* pathname of nm */ +#ifdef LDD_SUFFIX static char *ldd_file_name; /* pathname of ldd (or equivalent) */ +#endif static char *strip_file_name; /* pathname of strip */ char *c_file_name; /* pathname of gcc */ static char *initname, *fininame; /* names of init and fini funcs */ static struct head constructors; /* list of constructors found */ static struct head destructors; /* list of destructors found */ +#ifdef COLLECT_EXPORT_LIST static struct head exports; /* list of exported symbols */ +static struct head imports; /* list of imported symbols */ +static struct head undefined; /* list of undefined symbols */ +#endif +static struct head frame_tables; /* list of frame unwind info tables */ struct obstack temporary_obstack; struct obstack permanent_obstack; @@ -274,17 +237,20 @@ char * temporary_firstobj; /* Defined in the automatically-generated underscore.c. */ extern int prepends_underscore; -extern char *getenv (); extern char *mktemp (); extern FILE *fdopen (); +#ifndef GET_ENVIRONMENT +#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME) +#endif + /* Structure to hold all the directories in which to search for files to execute. */ struct prefix_list { - char *prefix; /* String to prepend to the path. */ - struct prefix_list *next; /* Next in linked list. */ + char *prefix; /* String to prepend to the path. */ + struct prefix_list *next; /* Next in linked list. */ }; struct path_prefix @@ -294,13 +260,19 @@ struct path_prefix char *name; /* Name of this list (used in config stuff) */ }; -void collect_exit PROTO((int)); -void collect_execute PROTO((char *, char **, char *)); -void dump_file PROTO((char *)); +#ifdef COLLECT_EXPORT_LIST +/* Lists to keep libraries to be scanned for global constructors/destructors. */ +static struct head libs; /* list of libraries */ +static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */ +static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */ +static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs, + &libpath_lib_dirs, NULL}; +static char *libexts[3] = {"a", "so", NULL}; /* possible library extentions */ +#endif + +static char *my_strerror PROTO((int)); static void handler PROTO((int)); static int is_ctor_dtor PROTO((char *)); -static void choose_temp_base PROTO((void)); -static int is_in_prefix_list PROTO((struct path_prefix *, char *, int)); static char *find_a_file PROTO((struct path_prefix *, char *)); static void add_prefix PROTO((struct path_prefix *, char *)); static void prefix_from_env PROTO((char *, struct path_prefix *)); @@ -310,18 +282,30 @@ static void fork_execute PROTO((char *, char **)); static void maybe_unlink PROTO((char *)); static void add_to_list PROTO((struct head *, char *)); static void write_list PROTO((FILE *, char *, struct id *)); +#ifdef COLLECT_EXPORT_LIST +static void dump_list PROTO((FILE *, char *, struct id *)); +#endif +#if 0 +static void dump_prefix_list PROTO((FILE *, char *, struct prefix_list *)); +#endif static void write_list_with_asm PROTO((FILE *, char *, struct id *)); static void write_c_file PROTO((FILE *, char *)); -static void write_export_file PROTO((FILE *)); static void scan_prog_file PROTO((char *, enum pass)); +#ifdef SCAN_LIBRARIES static void scan_libraries PROTO((char *)); +#endif +#ifdef COLLECT_EXPORT_LIST +static int is_in_list PROTO((char *, struct id *)); +static void write_export_file PROTO((FILE *)); +static void write_import_file PROTO((FILE *)); +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 (); -extern char *index (); -extern char *rindex (); -extern void free (); #ifdef NO_DUP2 int @@ -345,7 +329,7 @@ dup2 (oldfd, newfd) } #endif -char * +static char * my_strerror (e) int e; { @@ -379,9 +363,14 @@ collect_exit (status) if (o_file != 0 && o_file[0]) maybe_unlink (o_file); +#ifdef COLLECT_EXPORT_LIST if (export_file != 0 && export_file[0]) maybe_unlink (export_file); + if (import_file != 0 && import_file[0]) + maybe_unlink (import_file); +#endif + if (ldout != 0 && ldout[0]) { dump_file (ldout); @@ -395,7 +384,7 @@ collect_exit (status) } -/* Die when sys call fails. */ +/* Die when sys call fails. */ void fatal_perror (string, arg1, arg2, arg3) @@ -406,10 +395,10 @@ fatal_perror (string, arg1, arg2, arg3) fprintf (stderr, "collect2: "); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, ": %s\n", my_strerror (e)); - collect_exit (1); + collect_exit (FATAL_EXIT_CODE); } -/* Just die. */ +/* Just die. */ void fatal (string, arg1, arg2, arg3) @@ -418,7 +407,7 @@ fatal (string, arg1, arg2, arg3) fprintf (stderr, "collect2: "); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, "\n"); - collect_exit (1); + collect_exit (FATAL_EXIT_CODE); } /* Write error message. */ @@ -455,6 +444,14 @@ handler (signo) if (ldout != 0 && ldout[0]) maybe_unlink (ldout); +#ifdef COLLECT_EXPORT_LIST + if (export_file != 0 && export_file[0]) + maybe_unlink (export_file); + + if (import_file != 0 && import_file[0]) + maybe_unlink (import_file); +#endif + signal (signo, SIG_DFL); kill (getpid (), signo); } @@ -469,7 +466,7 @@ xcalloc (size1, size2) return ptr; fatal ("out of memory"); - return (char *)0; + return (char *) 0; } char * @@ -481,7 +478,7 @@ xmalloc (size) return ptr; fatal ("out of memory"); - return (char *)0; + return (char *) 0; } char * @@ -514,6 +511,39 @@ savestring (input, size) output[size] = 0; return output; } + +/* Parse a reasonable subset of shell quoting syntax. */ + +static char * +extract_string (pp) + char **pp; +{ + char *p = *pp; + int backquote = 0; + int inside = 0; + + for (;;) + { + char c = *p; + if (c == '\0') + break; + ++p; + if (backquote) + obstack_1grow (&temporary_obstack, c); + else if (! inside && c == ' ') + break; + else if (! inside && c == '\\') + backquote = 1; + else if (c == '\'') + inside = !inside; + else + obstack_1grow (&temporary_obstack, c); + } + + obstack_1grow (&temporary_obstack, '\0'); + *pp = p; + return obstack_finish (&temporary_obstack); +} void dump_file (name) @@ -528,7 +558,7 @@ dump_file (name) { int c; while (c = getc (stream), - c != EOF && (isalnum (c) || c == '_' || c == '$' || c == '.')) + c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.')) obstack_1grow (&temporary_obstack, c); if (obstack_object_size (&temporary_obstack) > 0) { @@ -570,6 +600,7 @@ dump_file (name) break; putc (c, stderr); } + fclose (stream); } /* Decide whether the given symbol is: @@ -590,17 +621,20 @@ is_ctor_dtor (s) #ifdef NO_DOT_IN_LABEL { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 }, { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 }, + { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 }, #else { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 }, { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 }, + { "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 }, #endif #else { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 }, { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 }, + { "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 }, #endif { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 }, { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 }, -#ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions. +#ifdef CFRONT_LOSSAGE /* Do not collect cfront initialization functions. cfront has its own linker procedure to collect them; if collect2 gets them too, they get collected twice when the cfront procedure is run and the compiler used @@ -628,42 +662,6 @@ is_ctor_dtor (s) } return 0; } - - -/* Compute a string to use as the base of all temporary file names. - It is substituted for %g. */ - -static void -choose_temp_base () -{ - char *base = getenv ("TMPDIR"); - int len; - - if (base == (char *)0) - { -#ifdef P_tmpdir - if (access (P_tmpdir, R_OK | W_OK) == 0) - base = P_tmpdir; -#endif - if (base == (char *)0) - { - if (access ("/usr/tmp", R_OK | W_OK) == 0) - base = "/usr/tmp/"; - else - base = "/tmp/"; - } - } - - len = strlen (base); - temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1); - strcpy (temp_filename, base); - if (len > 0 && temp_filename[len-1] != '/') - temp_filename[len++] = '/'; - strcpy (temp_filename + len, "ccXXXXXX"); - - mktemp (temp_filename); - temp_filename_length = strlen (temp_filename); -} /* Routine to add variables to the environment. */ @@ -730,52 +728,10 @@ static struct path_prefix cpath, path; static char *target_machine = TARGET_MACHINE; #endif -/* Names under which we were executed. Never return one of those files in our - searches. */ - -static struct path_prefix our_file_names; - -/* Determine if STRING is in PPREFIX. - - This utility is currently only used to look up file names. Prefix lists - record directory names. This matters to us because the latter has a - trailing slash, so I've added a flag to handle both. */ - -static int -is_in_prefix_list (pprefix, string, filep) - struct path_prefix *pprefix; - char *string; - int filep; -{ - struct prefix_list *pl; - - if (filep) - { - int len = strlen (string); - - for (pl = pprefix->plist; pl; pl = pl->next) - { - if (strncmp (pl->prefix, string, len) == 0 - && strcmp (pl->prefix + len, "/") == 0) - return 1; - } - } - else - { - for (pl = pprefix->plist; pl; pl = pl->next) - { - if (strcmp (pl->prefix, string) == 0) - return 1; - } - } - - return 0; -} - /* Search for NAME using prefix list PPREFIX. We only look for executable files. - Return 0 if not found, otherwise return its name, allocated with malloc. */ + Return 0 if not found, otherwise return its name, allocated with malloc. */ static char * find_a_file (pprefix, name) @@ -786,6 +742,9 @@ find_a_file (pprefix, name) struct prefix_list *pl; int len = pprefix->max_len + strlen (name) + 1; + if (debug) + fprintf (stderr, "Looking for '%s'\n", name); + #ifdef EXECUTABLE_SUFFIX len += strlen (EXECUTABLE_SUFFIX); #endif @@ -794,35 +753,48 @@ find_a_file (pprefix, name) /* Determine the filename to execute (special case for absolute paths). */ - if (*name == '/') + if (*name == '/' +#ifdef DIR_SEPARATOR + || (DIR_SEPARATOR == '\\' && name[1] == ':' + && (name[2] == DIR_SEPARATOR || name[2] == '/')) +#endif + ) { if (access (name, X_OK) == 0) { strcpy (temp, name); + + if (debug) + fprintf (stderr, " - found: absolute path\n"); + return temp; } + + if (debug) + fprintf (stderr, " - failed to locate using absolute path\n"); } else for (pl = pprefix->plist; pl; pl = pl->next) { strcpy (temp, pl->prefix); strcat (temp, name); - if (! is_in_prefix_list (&our_file_names, temp, 1) - /* This is a kludge, but there seems no way around it. */ - && strcmp (temp, "./ld") != 0 - && access (temp, X_OK) == 0) + + if (access (temp, X_OK) == 0) return temp; #ifdef EXECUTABLE_SUFFIX /* Some systems have a suffix for executable files. So try appending that. */ strcat (temp, EXECUTABLE_SUFFIX); - if (! is_in_prefix_list (&our_file_names, temp, 1) - && access (temp, X_OK) == 0) + + if (access (temp, X_OK) == 0) return temp; #endif } + if (debug && pprefix->plist == NULL) + fprintf (stderr, " - failed: no entries in prefix list\n"); + free (temp); return 0; } @@ -870,7 +842,8 @@ prefix_from_env (env, pprefix) char *env; struct path_prefix *pprefix; { - char *p = getenv (env); + char *p; + GET_ENVIRONMENT (p, env); if (p) prefix_from_string (p, pprefix); @@ -884,6 +857,9 @@ prefix_from_string (p, pprefix) char *startp, *endp; char *nstore = (char *) xmalloc (strlen (p) + 3); + if (debug) + fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); + startp = endp = p; while (1) { @@ -902,6 +878,9 @@ prefix_from_string (p, pprefix) else nstore[endp-startp] = 0; + if (debug) + fprintf (stderr, " - add prefix: %s\n", nstore); + add_prefix (pprefix, nstore); if (*endp == 0) break; @@ -912,7 +891,7 @@ prefix_from_string (p, pprefix) } } -/* Main program. */ +/* Main program. */ int main (argc, argv) @@ -922,7 +901,6 @@ main (argc, argv) char *ld_suffix = "ld"; char *full_ld_suffix = ld_suffix; char *real_ld_suffix = "real-ld"; - char *full_real_ld_suffix = real_ld_suffix; char *collect_ld_suffix = "collect-ld"; char *nm_suffix = "nm"; char *full_nm_suffix = nm_suffix; @@ -937,10 +915,12 @@ main (argc, argv) char *gstrip_suffix = "gstrip"; char *full_gstrip_suffix = gstrip_suffix; char *arg; - FILE *outf, *exportf; + FILE *outf; +#ifdef COLLECT_EXPORT_LIST + FILE *exportf; + FILE *importf; +#endif char *ld_file_name; - char *collect_name; - char *collect_names; char *p; char **c_argv; char **c_ptr; @@ -951,75 +931,44 @@ main (argc, argv) char **object_lst = (char **) xcalloc (sizeof (char *), argc); char **object = object_lst; int first_file; - int num_c_args = argc+7; + int num_c_args = argc+9; #ifdef DEBUG debug = 1; - vflag = 1; #endif + /* Parse command line early for instances of -debug. This allows + the debug flag to be set before functions like find_a_file() + are called. */ + { + int i; + + for (i = 1; argv[i] != NULL; i ++) + if (! strcmp (argv[i], "-debug")) + debug = 1; + vflag = debug; + } + +#ifndef DEFAULT_A_OUT_NAME output_file = "a.out"; +#else + output_file = DEFAULT_A_OUT_NAME; +#endif obstack_begin (&temporary_obstack, 0); obstack_begin (&permanent_obstack, 0); temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); - current_demangling_style = gnu_demangling; - - /* We must check that we do not call ourselves in an infinite - recursion loop. We append the name used for us to the COLLECT_NAMES - environment variable. - - In practice, collect will rarely invoke itself. This can happen now - that we are no longer called gld. A perfect example is when running - gcc in a build directory that has been installed. When looking for - ld's, we'll find our installed version and believe that's the real ld. */ - - /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the - previous version of collect (the one that used COLLECT_NAME and only - handled two levels of recursion). If we don't we may mutually recurse - forever. This can happen (I think) when bootstrapping the old version - and a new one is installed (rare, but we should handle it). - ??? Hopefully references to COLLECT_NAME can be removed at some point. */ - - collect_name = (char *) getenv ("COLLECT_NAME"); - collect_names = (char *) getenv ("COLLECT_NAMES"); - - p = (char *) xmalloc (strlen ("COLLECT_NAMES=") - + (collect_name ? strlen (collect_name) + 1 : 0) - + (collect_names ? strlen (collect_names) + 1 : 0) - + strlen (argv[0]) + 1); - strcpy (p, "COLLECT_NAMES="); - if (collect_name != 0) - sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR); - if (collect_names != 0) - sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR); - strcat (p, argv[0]); - putenv (p); - - prefix_from_env ("COLLECT_NAMES", &our_file_names); - - /* Set environment variable COLLECT_NAME to our name so the previous version - of collect won't find us. If it does we'll mutually recurse forever. - This can happen when bootstrapping the new version and an old version is - installed. - ??? Hopefully this bit of code can be removed at some point. */ - - p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1); - sprintf (p, "COLLECT_NAME=%s", argv[0]); - putenv (p); - - p = (char *) getenv ("COLLECT_GCC_OPTIONS"); - if (p) - while (*p) - { - char *q = p; - while (*q && *q != ' ') q++; - if (*p == '-' && p[1] == 'm') - num_c_args++; - if (*q) q++; - p = q; - } + current_demangling_style = gnu_demangling; + p = getenv ("COLLECT_GCC_OPTIONS"); + while (p && *p) + { + char *q = extract_string (&p); + if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) + num_c_args++; + } + obstack_free (&temporary_obstack, temporary_firstobj); + ++num_c_args; c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args); @@ -1054,7 +1003,7 @@ main (argc, argv) #ifdef CROSS_COMPILE /* If we look for a program in the compiler directories, we just use the short name, since these directories are already system-specific. - But it we look for a took in the system directories, we need to + But it we look for a program in the system directories, we need to qualify the program name with the target machine. */ full_ld_suffix @@ -1063,12 +1012,6 @@ main (argc, argv) strcat (full_ld_suffix, "-"); strcat (full_ld_suffix, ld_suffix); - full_real_ld_suffix - = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1); - strcpy (full_real_ld_suffix, target_machine); - strcat (full_real_ld_suffix, "-"); - strcat (full_real_ld_suffix, real_ld_suffix); - #if 0 full_gld_suffix = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1); @@ -1131,18 +1074,6 @@ main (argc, argv) if (ld_file_name == 0) ld_file_name = find_a_file (&path, full_ld_suffix); - /* If we've invoked ourselves, try again with LD_FILE_NAME. */ - - if (collect_names != 0) - { - if (ld_file_name != 0) - { - argv[0] = ld_file_name; - execvp (argv[0], argv); - } - fatal ("cannot find `ld'"); - } - #ifdef REAL_NM_FILE_NAME nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); if (nm_file_name == 0) @@ -1198,21 +1129,47 @@ main (argc, argv) *ld1++ = *ld2++ = ld_file_name; - /* Make temp file names. */ - choose_temp_base (); - c_file = xcalloc (temp_filename_length + sizeof (".c"), 1); - o_file = xcalloc (temp_filename_length + sizeof (".o"), 1); - export_file = xmalloc (temp_filename_length + sizeof (".x")); - ldout = xmalloc (temp_filename_length + sizeof (".ld")); - sprintf (ldout, "%s.ld", temp_filename); - sprintf (c_file, "%s.c", temp_filename); - sprintf (o_file, "%s.o", temp_filename); - sprintf (export_file, "%s.x", temp_filename); + /* Make temp file names. */ + c_file = make_temp_file (".c"); + o_file = make_temp_file (".o"); +#ifdef COLLECT_EXPORT_LIST + export_file = make_temp_file (".x"); + import_file = make_temp_file (".p"); +#endif + ldout = make_temp_file (".ld"); *c_ptr++ = c_file_name; + *c_ptr++ = "-x"; + *c_ptr++ = "c"; *c_ptr++ = "-c"; *c_ptr++ = "-o"; *c_ptr++ = o_file; +#ifdef COLLECT_EXPORT_LIST + /* Generate a list of directories from LIBPATH. */ + prefix_from_env ("LIBPATH", &libpath_lib_dirs); + /* Add to this list also two standard directories where + AIX loader always searches for libraries. */ + add_prefix (&libpath_lib_dirs, "/lib"); + add_prefix (&libpath_lib_dirs, "/usr/lib"); +#endif + + /* Get any options that the upper GCC wants to pass to the sub-GCC. + + AIX support needs to know if -shared has been specified before + parsing commandline arguments. */ + + p = getenv ("COLLECT_GCC_OPTIONS"); + while (p && *p) + { + char *q = extract_string (&p); + if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) + *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); + if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0) + shared_obj = 1; + } + obstack_free (&temporary_obstack, temporary_firstobj); + *c_ptr++ = "-fno-exceptions"; + /* !!! When GCC calls collect2, it does not know whether it is calling collect2 or ld. So collect2 cannot meaningfully understand any options @@ -1220,11 +1177,11 @@ main (argc, argv) If you propose to make GCC pass some other option, just imagine what will happen if ld is really ld!!! */ - /* Parse arguments. Remember output file spec, pass the rest to ld. */ + /* Parse arguments. Remember output file spec, pass the rest to ld. */ /* After the first file, put in the c++ rt0. */ first_file = 1; - while ((arg = *++argv) != (char *)0) + while ((arg = *++argv) != (char *) 0) { *ld1++ = *ld2++ = arg; @@ -1232,11 +1189,21 @@ main (argc, argv) { switch (arg[1]) { +#ifdef COLLECT_EXPORT_LIST + /* We want to disable automatic exports on AIX when user + explicitly puts an export list in command line */ + case 'b': + if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) + export_flag = 1; + if (arg[2] == '6' && arg[3] == '4') + aix64_flag = 1; + break; +#endif + case 'd': if (!strcmp (arg, "-debug")) { - debug = 1; - vflag = 1; + /* Already parsed. */ ld1--; ld2--; } @@ -1251,7 +1218,31 @@ main (argc, argv) *ld2++ = o_file; *ld2++ = arg; } +#ifdef COLLECT_EXPORT_LIST + { + /* Resolving full library name. */ + char *s = resolve_lib_name (arg+2); + + /* If we will use an import list for this library, + we should exclude it from ld args. */ + if (use_import_list (s)) + { + ld1--; + ld2--; + } + + /* Saving a full library name. */ + add_to_list (&libs, s); + } +#endif + break; + +#ifdef COLLECT_EXPORT_LIST + /* Saving directories where to search for libraries. */ + case 'L': + add_prefix (&cmdline_lib_dirs, arg+2); break; +#endif case 'o': if (arg[2] == '\0') @@ -1269,7 +1260,7 @@ main (argc, argv) if (arg[2] == '\0' && do_collecting) { /* We must strip after the nm run, otherwise C++ linking - won't work. Thus we strip in the second ld run, or + will not work. Thus we strip in the second ld run, or else with strip if there is no second ld run. */ strip_flag = 1; ld1--; @@ -1282,8 +1273,9 @@ main (argc, argv) break; } } - else if ((p = rindex (arg, '.')) != (char *)0 - && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0)) + else if ((p = rindex (arg, '.')) != (char *) 0 + && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0 + || strcmp (p, ".so") == 0)) { if (first_file) { @@ -1300,47 +1292,71 @@ main (argc, argv) } if (p[1] == 'o') *object++ = arg; +#ifdef COLLECT_EXPORT_LIST + /* libraries can be specified directly, i.e. without -l flag. */ + else + { + /* If we will use an import list for this library, + we should exclude it from ld args. */ + if (use_import_list (arg)) + { + ld1--; + ld2--; + } + + /* Saving a full library name. */ + add_to_list (&libs, arg); + } +#endif } } - /* Get any options that the upper GCC wants to pass to the sub-GCC. */ - p = (char *) getenv ("COLLECT_GCC_OPTIONS"); - if (p) - while (*p) - { - char *q = p; - while (*q && *q != ' ') q++; - if (*p == '-' && (p[1] == 'm' || p[1] == 'f')) - *c_ptr++ = savestring (p, q - p); - if (strncmp (p, "-shared", sizeof ("shared") - 1) == 0) - shared_obj = 1; - - if (*q) q++; - p = q; - } - #ifdef COLLECT_EXPORT_LIST + /* This is added only for debugging purposes. */ + if (debug) + { + fprintf (stderr, "List of libraries:\n"); + dump_list (stderr, "\t", libs.first); + } + /* The AIX linker will discard static constructors in object files if nothing else in the file is referenced, so look at them first. */ - while (object_lst < object) - scan_prog_file (*object_lst++, PASS_OBJ); - { - char *buf = alloca (strlen (export_file) + 5); - sprintf (buf, "-bE:%s", export_file); - *ld1++ = buf; - *ld2++ = buf; + char **export_object_lst = object_lst; + while (export_object_lst < object) + scan_prog_file (*export_object_lst++, PASS_OBJ); + } + { + struct id *list = libs.first; + for (; list; list = list->next) + scan_prog_file (list->name, PASS_FIRST); + } + { + char *buf1 = alloca (strlen (export_file) + 5); + char *buf2 = alloca (strlen (import_file) + 5); + sprintf (buf1, "-bE:%s", export_file); + sprintf (buf2, "-bI:%s", import_file); + *ld1++ = buf1; + *ld2++ = buf1; + *ld1++ = buf2; + *ld2++ = buf2; exportf = fopen (export_file, "w"); - if (exportf == (FILE *)0) + if (exportf == (FILE *) 0) fatal_perror ("%s", export_file); write_export_file (exportf); if (fclose (exportf)) fatal_perror ("closing %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); } #endif *c_ptr++ = c_file; - *object = *c_ptr = *ld1 = (char *)0; + *object = *c_ptr = *ld1 = (char *) 0; if (vflag) { @@ -1371,10 +1387,6 @@ main (argc, argv) fprintf (stderr, "o_file = %s\n", (o_file ? o_file : "not found")); - ptr = getenv ("COLLECT_NAMES"); - if (ptr) - fprintf (stderr, "COLLECT_NAMES = %s\n", ptr); - ptr = getenv ("COLLECT_GCC_OPTIONS"); if (ptr) fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr); @@ -1394,23 +1406,42 @@ main (argc, argv) fprintf (stderr, "\n"); } - /* Load the program, searching all libraries. */ + /* Load the program, searching all libraries and attempting to provide + undefined symbols from repository information. */ - collect_execute ("ld", ld1_argv, ldout); - do_wait ("ld"); - dump_file (ldout); - unlink (ldout); + /* On AIX we do this later. */ +#ifndef COLLECT_EXPORT_LIST + do_tlink (ld1_argv, object_lst); +#endif - /* If -r or they'll be run via some other method, don't build the - constructor or destructor list, just return now. */ - if (rflag || ! do_collecting) - return 0; + /* If -r or they will be run via some other method, do not build the + constructor or destructor list, just return now. */ + if (rflag +#ifndef COLLECT_EXPORT_LIST + || ! do_collecting +#endif + ) + { +#ifdef COLLECT_EXPORT_LIST + /* But make sure we delete the export file we may have created. */ + if (export_file != 0 && export_file[0]) + maybe_unlink (export_file); + if (import_file != 0 && import_file[0]) + maybe_unlink (import_file); +#endif + maybe_unlink (c_file); + maybe_unlink (o_file); + return 0; + } /* Examine the namelist with nm and search it for static constructors and destructors to call. - Write the constructor and destructor tables to a .s file and reload. */ + Write the constructor and destructor tables to a .s file and reload. */ + /* On AIX we already done scanning for global constructors/destructors. */ +#ifndef COLLECT_EXPORT_LIST scan_prog_file (output_file, PASS_FIRST); +#endif #ifdef SCAN_LIBRARIES scan_libraries (output_file); @@ -1423,14 +1454,19 @@ main (argc, argv) } if (constructors.number == 0 && destructors.number == 0 -#ifdef LDD_SUFFIX + && frame_tables.number == 0 +#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST) /* If we will be running these functions ourselves, we want to emit - stubs into the shared library so that we don't have to relink + stubs into the shared library so that we do not have to relink dependent programs when we add static objects. */ && ! shared_obj #endif ) { +#ifdef COLLECT_EXPORT_LIST + /* Doing tlink without additional code generation */ + do_tlink (ld1_argv, object_lst); +#endif /* Strip now if it was requested on the command line. */ if (strip_flag) { @@ -1443,13 +1479,16 @@ main (argc, argv) #ifdef COLLECT_EXPORT_LIST maybe_unlink (export_file); + maybe_unlink (import_file); #endif + maybe_unlink (c_file); + maybe_unlink (o_file); return 0; } maybe_unlink(output_file); outf = fopen (c_file, "w"); - if (outf == (FILE *)0) + if (outf == (FILE *) 0) fatal_perror ("%s", c_file); write_c_file (outf, c_file); @@ -1464,7 +1503,7 @@ main (argc, argv) *ld2++ = LD_FINI_SWITCH; *ld2++ = fininame; #endif - *ld2 = (char*)0; + *ld2 = (char*) 0; #ifdef COLLECT_EXPORT_LIST if (shared_obj) @@ -1474,7 +1513,7 @@ main (argc, argv) add_to_list (&exports, "_GLOBAL__DI"); add_to_list (&exports, "_GLOBAL__DD"); exportf = fopen (export_file, "w"); - if (exportf == (FILE *)0) + if (exportf == (FILE *) 0) fatal_perror ("%s", export_file); write_export_file (exportf); if (fclose (exportf)) @@ -1496,23 +1535,34 @@ main (argc, argv) } /* Assemble the constructor and destructor tables. - Link the tables in with the rest of the program. */ + Link the tables in with the rest of the program. */ fork_execute ("gcc", c_argv); +#ifdef COLLECT_EXPORT_LIST + /* On AIX we must call tlink because of possible templates resolution */ + do_tlink (ld2_argv, object_lst); +#else + /* Otherwise, simply call ld because tlink is already done */ fork_execute ("ld", ld2_argv); /* Let scan_prog_file do any final mods (OSF/rose needs this for constructors/destructors in shared libraries. */ scan_prog_file (output_file, PASS_SECOND); +#endif maybe_unlink (c_file); maybe_unlink (o_file); + +#ifdef COLLECT_EXPORT_LIST maybe_unlink (export_file); + maybe_unlink (import_file); +#endif + return 0; } -/* Wait for a process to finish, and exit if a non-zero status is found. */ +/* Wait for a process to finish, and exit if a non-zero status is found. */ int collect_wait (prog) @@ -1539,7 +1589,7 @@ collect_wait (prog) (status & 0200) ? ", core dumped" : ""); #endif - collect_exit (127); + collect_exit (FATAL_EXIT_CODE); } if (WIFEXITED (status)) @@ -1581,7 +1631,7 @@ collect_execute (prog, argv, redir) else fprintf (stderr, "[cannot find %s]", prog); - for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++) + for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) fprintf (stderr, " %s", str); fprintf (stderr, "\n"); @@ -1590,12 +1640,13 @@ collect_execute (prog, argv, redir) fflush (stdout); fflush (stderr); - /* If we can't find a program we need, complain error. Do this here - since we might not end up needing something that we couldn't find. */ + /* If we cannot find a program we need, complain error. Do this here + since we might not end up needing something that we could not find. */ if (argv[0] == 0) fatal ("cannot find `%s'", prog); +#ifndef __CYGWIN32__ pid = vfork (); if (pid == -1) { @@ -1612,14 +1663,19 @@ collect_execute (prog, argv, redir) { unlink (redir); if (freopen (redir, "a", stdout) == NULL) - fatal_perror ("redirecting stdout"); + fatal_perror ("redirecting stdout: %s", redir); if (freopen (redir, "a", stderr) == NULL) - fatal_perror ("redirecting stderr"); + fatal_perror ("redirecting stderr: %s", redir); } execvp (argv[0], argv); fatal_perror ("executing %s", prog); } +#else + pid = _spawnvp (_P_NOWAIT, argv[0], argv); + if (pid == -1) + fatal ("spawnvp failed"); +#endif } static void @@ -1694,6 +1750,53 @@ write_list (stream, prefix, list) } } +#ifdef COLLECT_EXPORT_LIST +/* This function is really used only on AIX, but may be useful. */ +static int +is_in_list (prefix, list) + char *prefix; + struct id *list; +{ + while (list) + { + if (!strcmp (prefix, list->name)) return 1; + list = list->next; + } + return 0; +} +#endif + +/* Added for debugging purpose. */ +#ifdef COLLECT_EXPORT_LIST +static void +dump_list (stream, prefix, list) + FILE *stream; + char *prefix; + struct id *list; +{ + while (list) + { + fprintf (stream, "%s%s,\n", prefix, list->name); + list = list->next; + } +} +#endif + +#if 0 +static void +dump_prefix_list (stream, prefix, list) + FILE *stream; + char *prefix; + struct prefix_list *list; +{ + while (list) + { + fprintf (stream, "%s%s,\n", prefix, list->prefix); + list = list->next; + } +} +#endif + static void write_list_with_asm (stream, prefix, list) FILE *stream; @@ -1717,6 +1820,7 @@ write_c_file_stat (stream, name) char *name; { char *prefix, *p, *q; + int frames = (frame_tables.number > 0); /* Figure out name of output_file, stripping off .so version. */ p = rindex (output_file, '/'); @@ -1749,7 +1853,7 @@ 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 (*q)) *q = '_'; if (debug) fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n", @@ -1770,15 +1874,49 @@ write_c_file_stat (stream, name) fprintf (stream, "static int count;\n"); fprintf (stream, "typedef void entry_pt();\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); + + if (frames) + { + write_list_with_asm (stream, "extern void *", frame_tables.first); + + fprintf (stream, "\tstatic void *frame_table[] = {\n"); + write_list (stream, "\t\t&", frame_tables.first); + fprintf (stream, "\t0\n};\n"); + + /* This must match what's in frame.h. */ + fprintf (stream, "struct object {\n"); + fprintf (stream, " void *pc_begin;\n"); + fprintf (stream, " void *pc_end;\n"); + fprintf (stream, " void *fde_begin;\n"); + fprintf (stream, " void *fde_array;\n"); + fprintf (stream, " __SIZE_TYPE__ count;\n"); + fprintf (stream, " struct object *next;\n"); + fprintf (stream, "};\n"); + + fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); + fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); + + fprintf (stream, "static void reg_frame () {\n"); + fprintf (stream, "\tstatic struct object ob;\n"); + fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); + fprintf (stream, "\t}\n"); + + fprintf (stream, "static void dereg_frame () {\n"); + fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); + fprintf (stream, "\t}\n"); + } + fprintf (stream, "void %s() {\n", initname); - if (constructors.number > 0) + if (constructors.number > 0 || frames) { fprintf (stream, "\tstatic entry_pt *ctors[] = {\n"); write_list (stream, "\t\t", constructors.first); + if (frames) + fprintf (stream, "\treg_frame,\n"); fprintf (stream, "\t};\n"); fprintf (stream, "\tentry_pt **p;\n"); fprintf (stream, "\tif (count++ != 0) return;\n"); - fprintf (stream, "\tp = ctors + %d;\n", constructors.number); + fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames); fprintf (stream, "\twhile (p > ctors) (*--p)();\n"); } else @@ -1786,16 +1924,18 @@ write_c_file_stat (stream, name) fprintf (stream, "}\n"); write_list_with_asm (stream, "extern entry_pt ", destructors.first); fprintf (stream, "void %s() {\n", fininame); - if (destructors.number > 0) + if (destructors.number > 0 || frames) { fprintf (stream, "\tstatic entry_pt *dtors[] = {\n"); write_list (stream, "\t\t", destructors.first); + if (frames) + fprintf (stream, "\tdereg_frame,\n"); fprintf (stream, "\t};\n"); fprintf (stream, "\tentry_pt **p;\n"); fprintf (stream, "\tif (--count != 0) return;\n"); fprintf (stream, "\tp = dtors;\n"); fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n", - destructors.number); + destructors.number + frames); } fprintf (stream, "}\n"); @@ -1806,8 +1946,9 @@ write_c_file_stat (stream, name) } } -/* Write the constructor/destructor tables. */ +/* Write the constructor/destructor tables. */ +#ifndef LD_INIT_SWITCH static void write_c_file_glob (stream, name) FILE *stream; @@ -1815,39 +1956,80 @@ write_c_file_glob (stream, name) { /* Write the tables as C code */ + int frames = (frame_tables.number > 0); + fprintf (stream, "typedef void entry_pt();\n\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); - + + if (frames) + { + write_list_with_asm (stream, "extern void *", frame_tables.first); + + fprintf (stream, "\tstatic void *frame_table[] = {\n"); + write_list (stream, "\t\t&", frame_tables.first); + fprintf (stream, "\t0\n};\n"); + + /* This must match what's in frame.h. */ + fprintf (stream, "struct object {\n"); + fprintf (stream, " void *pc_begin;\n"); + fprintf (stream, " void *pc_end;\n"); + fprintf (stream, " void *fde_begin;\n"); + fprintf (stream, " void *fde_array;\n"); + fprintf (stream, " __SIZE_TYPE__ count;\n"); + fprintf (stream, " struct object *next;\n"); + fprintf (stream, "};\n"); + + fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); + fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); + + fprintf (stream, "static void reg_frame () {\n"); + fprintf (stream, "\tstatic struct object ob;\n"); + fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); + fprintf (stream, "\t}\n"); + + fprintf (stream, "static void dereg_frame () {\n"); + fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); + fprintf (stream, "\t}\n"); + } + fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); - fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number); + fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames); write_list (stream, "\t", constructors.first); + if (frames) + fprintf (stream, "\treg_frame,\n"); fprintf (stream, "\t0\n};\n\n"); write_list_with_asm (stream, "extern entry_pt ", destructors.first); fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n"); - fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number); + fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames); write_list (stream, "\t", destructors.first); + if (frames) + fprintf (stream, "\tdereg_frame,\n"); fprintf (stream, "\t0\n};\n\n"); fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN); fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN); } +#endif /* ! LD_INIT_SWITCH */ static void write_c_file (stream, name) FILE *stream; char *name; { + fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); #ifndef LD_INIT_SWITCH if (! shared_obj) write_c_file_glob (stream, name); else #endif write_c_file_stat (stream, name); + fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n"); } +#ifdef COLLECT_EXPORT_LIST static void write_export_file (stream) FILE *stream; @@ -1856,6 +2038,17 @@ write_export_file (stream) for (; list; list = list->next) fprintf (stream, "%s\n", list->name); } + +static void +write_import_file (stream) + FILE *stream; +{ + struct id *list = imports.first; + fprintf (stream, "%s\n", "#! ."); + for (; list; list = list->next) + fprintf (stream, "%s\n", list->name); +} +#endif #ifdef OBJECT_FORMAT_NONE @@ -1885,7 +2078,7 @@ scan_prog_file (prog_name, which_pass) if (which_pass == PASS_SECOND) return; - /* If we don't have an `nm', complain. */ + /* If we do not have an `nm', complain. */ if (nm_file_name == 0) fatal ("cannot find `nm'"); @@ -1894,13 +2087,13 @@ scan_prog_file (prog_name, which_pass) nm_argv[argc++] = NM_FLAGS; nm_argv[argc++] = prog_name; - nm_argv[argc++] = (char *)0; + nm_argv[argc++] = (char *) 0; if (pipe (pipe_fd) < 0) fatal_perror ("pipe"); inf = fdopen (pipe_fd[0], "r"); - if (inf == (FILE *)0) + if (inf == (FILE *) 0) fatal_perror ("fdopen"); /* Trace if needed. */ @@ -1909,7 +2102,7 @@ scan_prog_file (prog_name, which_pass) char **p_argv; char *str; - for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++) + for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) fprintf (stderr, " %s", str); fprintf (stderr, "\n"); @@ -1958,13 +2151,13 @@ scan_prog_file (prog_name, which_pass) fprintf (stderr, "\nnm output with constructors/destructors.\n"); /* Read each line of nm output. */ - while (fgets (buf, sizeof buf, inf) != (char *)0) + while (fgets (buf, sizeof buf, inf) != (char *) 0) { int ch, ch2; char *name, *end; /* If it contains a constructor or destructor name, add the name - to the appropriate list. */ + to the appropriate list. */ for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) if (ch == ' ' && p[1] == 'U' && p[2] == ' ') @@ -1975,8 +2168,8 @@ scan_prog_file (prog_name, which_pass) name = p; /* Find the end of the symbol name. - Don't include `|', because Encore nm can tack that on the end. */ - for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|'; + Do not include `|', because Encore nm can tack that on the end. */ + for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|'; end++) continue; @@ -2010,6 +2203,10 @@ scan_prog_file (prog_name, which_pass) #endif break; + case 5: + if (which_pass != PASS_LIB) + add_to_list (&frame_tables, name); + default: /* not a constructor or destructor */ continue; } @@ -2043,7 +2240,7 @@ scan_prog_file (prog_name, which_pass) #include #include #include -#include +#include #include /* pointers to the object file */ @@ -2095,7 +2292,7 @@ libselect (d) We must verify that the extension is numeric, because Sun saves the original versions of patched libraries with a .FCS extension. Files with - invalid extensions must go last in the sort, so that they won't be used. */ + invalid extensions must go last in the sort, so that they will not be used. */ static int libcompare (d1, d2) @@ -2106,7 +2303,7 @@ libcompare (d1, d2) char *e2 = (*d2)->d_name + i2; while (*e1 && *e2 && *e1 == '.' && *e2 == '.' - && e1[1] && isdigit (e1[1]) && e2[1] && isdigit (e2[1])) + && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1])) { ++e1; ++e2; @@ -2119,7 +2316,7 @@ libcompare (d1, d2) if (*e1) { /* It has a valid numeric extension, prefer this one. */ - if (*e1 == '.' && e1[1] && isdigit (e1[1])) + if (*e1 == '.' && e1[1] && ISDIGIT (e1[1])) return 1; /* It has a invalid numeric extension, must prefer the other one. */ else @@ -2128,7 +2325,7 @@ libcompare (d1, d2) else if (*e2) { /* It has a valid numeric extension, prefer this one. */ - if (*e2 == '.' && e2[1] && isdigit (e2[1])) + if (*e2 == '.' && e2[1] && ISDIGIT (e2[1])) return -1; /* It has a invalid numeric extension, must prefer the other one. */ else @@ -2323,7 +2520,7 @@ scan_libraries (prog_name) char buf[1024]; FILE *inf; - /* If we don't have an `ldd', complain. */ + /* If we do not have an `ldd', complain. */ if (ldd_file_name == 0) { error ("cannot find `ldd'"); @@ -2401,7 +2598,7 @@ scan_libraries (prog_name) int ch, ch2; char *name, *end, *p = buf; - /* Extract names of libraries and add to list. */ + /* Extract names of libraries and add to list. */ PARSE_LDD_OUTPUT (p); if (p == 0) continue; @@ -2410,9 +2607,9 @@ scan_libraries (prog_name) if (strncmp (name, "not found", sizeof ("not found") - 1) == 0) fatal ("dynamic dependency %s not found", buf); - /* Find the end of the symbol name. */ + /* Find the end of the symbol name. */ for (end = p; - (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|'; + (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|'; end++) continue; *end = '\0'; @@ -2468,11 +2665,16 @@ scan_libraries (prog_name) # define GCC_SYMENT SYMENT # define GCC_OK_SYMBOL(X) \ (((X).n_sclass == C_EXT) && \ - (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \ - ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))) + ((X).n_scnum > N_UNDEF) && \ + (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \ + ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))) +# define GCC_UNDEF_SYMBOL(X) \ + (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF)) # define GCC_SYMINC(X) ((X).n_numaux+1) # define GCC_SYMZERO(X) 0 -# define GCC_CHECK_HDR(X) (1) +# define GCC_CHECK_HDR(X) \ + ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ + || (HEADER (X).f_magic == 0757 && aix64_flag)) #endif extern char *ldgetname (); @@ -2493,246 +2695,277 @@ scan_prog_file (prog_name, which_pass) { LDFILE *ldptr = NULL; int sym_index, sym_count; + int is_shared = 0; +#ifdef COLLECT_EXPORT_LIST + /* Should we generate an import list for given prog_name? */ + int import_flag = (which_pass == PASS_OBJ ? 0 : use_import_list (prog_name)); +#endif if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) return; - if ((ldptr = ldopen (prog_name, ldptr)) == NULL) - fatal ("%s: can't open as COFF file", prog_name); - - if (!MY_ISCOFF (HEADER (ldptr).f_magic)) - fatal ("%s: not a COFF file", prog_name); +#ifdef COLLECT_EXPORT_LIST + /* We do not need scanning for some standard C libraries. */ + if (which_pass == PASS_FIRST && ignore_library (prog_name)) + return; - if (GCC_CHECK_HDR (ldptr)) + /* On AIX we have a loop, because there is not much difference + between an object and an archive. This trick allows us to + eliminate scan_libraries() function. */ + do { - sym_count = GCC_SYMBOLS (ldptr); - sym_index = GCC_SYMZERO (ldptr); - while (sym_index < sym_count) +#endif + if ((ldptr = ldopen (prog_name, ldptr)) != NULL) { - GCC_SYMENT symbol; - - if (ldtbread (ldptr, sym_index, &symbol) <= 0) - break; - sym_index += GCC_SYMINC (symbol); + if (! MY_ISCOFF (HEADER (ldptr).f_magic)) + fatal ("%s: not a COFF file", prog_name); - if (GCC_OK_SYMBOL (symbol)) + if (GCC_CHECK_HDR (ldptr)) { - char *name; + sym_count = GCC_SYMBOLS (ldptr); + sym_index = GCC_SYMZERO (ldptr); - if ((name = ldgetname (ldptr, &symbol)) == NULL) - continue; /* should never happen */ +#ifdef COLLECT_EXPORT_LIST + /* Is current archive member a shared object? */ + is_shared = HEADER (ldptr).f_flags & F_SHROBJ; +#endif + + while (sym_index < sym_count) + { + GCC_SYMENT symbol; + + if (ldtbread (ldptr, sym_index, &symbol) <= 0) + break; + sym_index += GCC_SYMINC (symbol); + + if (GCC_OK_SYMBOL (symbol)) + { + char *name; + + if ((name = ldgetname (ldptr, &symbol)) == NULL) + continue; /* should never happen */ #ifdef XCOFF_DEBUGGING_INFO - /* All AIX function names have a duplicate entry beginning - with a dot. */ - if (*name == '.') - ++name; + /* All AIX function names have a duplicate entry + beginning with a dot. */ + if (*name == '.') + ++name; #endif - switch (is_ctor_dtor (name)) - { - case 1: - add_to_list (&constructors, name); - if (which_pass == PASS_OBJ) - add_to_list (&exports, name); - break; + switch (is_ctor_dtor (name)) + { + case 1: + if (! is_shared) add_to_list (&constructors, name); +#ifdef COLLECT_EXPORT_LIST + if (which_pass == PASS_OBJ) + add_to_list (&exports, name); + /* If this symbol was undefined and we are building + an import list, we should add a symbol to this + list. */ + else + if (import_flag + && is_in_list (name, undefined.first)) + add_to_list (&imports, name); +#endif + break; + + case 2: + if (! is_shared) add_to_list (&destructors, name); +#ifdef COLLECT_EXPORT_LIST + if (which_pass == PASS_OBJ) + add_to_list (&exports, name); + /* If this symbol was undefined and we are building + an import list, we should add a symbol to this + list. */ + else + if (import_flag + && is_in_list (name, undefined.first)) + add_to_list (&imports, name); +#endif + break; - case 2: - add_to_list (&destructors, name); - if (which_pass == PASS_OBJ) - add_to_list (&exports, name); - break; +#ifdef COLLECT_EXPORT_LIST + case 3: + if (is_shared) + add_to_list (&constructors, name); + break; - default: /* not a constructor or destructor */ - continue; - } + case 4: + if (is_shared) + add_to_list (&destructors, name); + break; +#endif + + default: /* not a constructor or destructor */ +#ifdef COLLECT_EXPORT_LIST + /* If we are building a shared object on AIX we need + to explicitly export all global symbols or add + them to import list. */ + if (shared_obj) + { + if (which_pass == PASS_OBJ && (! export_flag)) + add_to_list (&exports, name); + else if (! is_shared && which_pass == PASS_FIRST + && import_flag + && is_in_list(name, undefined.first)) + add_to_list (&imports, name); + } +#endif + continue; + } #if !defined(EXTENDED_COFF) - if (debug) - fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n", - symbol.n_scnum, symbol.n_sclass, - (symbol.n_type ? "0" : ""), symbol.n_type, - name); + if (debug) + fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n", + symbol.n_scnum, symbol.n_sclass, + (symbol.n_type ? "0" : ""), symbol.n_type, + name); #else - if (debug) - fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n", - symbol.iss, symbol.value, symbol.index, name); + if (debug) + fprintf (stderr, + "\tiss = %5d, value = %5ld, index = %5d, name = %s\n", + symbol.iss, (long) symbol.value, symbol.index, name); +#endif + } +#ifdef COLLECT_EXPORT_LIST + /* If we are building a shared object we should collect + information about undefined symbols for later + import list generation. */ + else if (shared_obj && GCC_UNDEF_SYMBOL (symbol)) + { + char *name; + + if ((name = ldgetname (ldptr, &symbol)) == NULL) + continue; /* should never happen */ + + /* All AIX function names have a duplicate entry + beginning with a dot. */ + if (*name == '.') + ++name; + add_to_list (&undefined, name); + } #endif + } + } +#ifdef COLLECT_EXPORT_LIST + else + { + /* If archive contains both 32-bit and 64-bit objects, + we want to skip objects in other mode so mismatch normal. */ + if (debug) + fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n", + prog_name, HEADER (ldptr).f_magic, aix64_flag); } +#endif + } + else + { + fatal ("%s: cannot open as COFF file", prog_name); } +#ifdef COLLECT_EXPORT_LIST + /* On AIX loop continues while there are more members in archive. */ } - + while (ldclose (ldptr) == FAILURE); +#else + /* Otherwise we simply close ldptr. */ (void) ldclose(ldptr); +#endif } -#ifdef XCOFF_SCAN_LIBS -/* Scan imported AIX libraries for GCC static ctors and dtors. - FIXME: it is possible to link an executable without the actual import - library by using an "import file" - a text file listing symbols - exported by a library. To support this, we would have to scan - import files as well as actual shared binaries to find GCC ctors. - TODO: use memory mapping instead of 'ld' routines, files are already - memory mapped, but we could eliminate the extra in-memory copies. - Is it worth the effort? */ -static void -scan_libraries (prog_name) +#ifdef COLLECT_EXPORT_LIST + +/* This new function is used to decide whether we should + generate import list for an object or to use it directly. */ +static int +use_import_list (prog_name) char *prog_name; { - LDFILE *ldptr; - SCNHDR ldsh; - static struct path_prefix libpath; /* we should only do this once */ - - if ((ldptr = ldopen (prog_name, ldptr)) == NULL) - fatal ("%s: can't open as COFF file", prog_name); - - if (!MY_ISCOFF (HEADER (ldptr).f_magic)) - fatal ("%s: not a COFF file", prog_name); - - /* find and read loader section */ - if (ldnshread (ldptr, _LOADER, &ldsh)) - { - LDHDR ldh; - char *impbuf; - int entry; - - FSEEK (ldptr, ldsh.s_scnptr, BEGINNING); - FREAD (&ldh, sizeof (ldh), 1, ldptr); - /* read import library list */ - impbuf = alloca (ldh.l_istlen); - FSEEK (ldptr, ldh.l_impoff + ldsh.s_scnptr, BEGINNING); - FREAD (impbuf, ldh.l_istlen, 1, ldptr); + char *p; - if (debug) - fprintf (stderr, "LIBPATH=%s\n", impbuf); - prefix_from_string (impbuf, &libpath); + /* If we do not build a shared object then import list should not be used. */ + if (! shared_obj) return 0; - /* skip LIBPATH and empty base and member fields */ - impbuf += strlen (impbuf) + 3; - for (entry = 1; entry < ldh.l_nimpid; ++entry) - { - char *impath = impbuf; - char *implib = impath + strlen (impath) + 1; - char *impmem = implib + strlen (implib) + 1; - char *soname = NULL; - char *trial; - int pathlen; - LDFILE *libptr = NULL; - struct prefix_list *pl; - ARCHDR ah; - - impbuf = impmem + strlen (impmem) + 1; - if (debug) - fprintf (stderr, "PATH+BASE=%s%s\n", impath, implib); - /* Skip AIX kernel exports */ - if (*impath == '/' && *(impath+1) == '\0' - && strcmp (implib, "unix") == 0) - continue; - pathlen = strlen (impath); - trial = alloca (MAX (pathlen + 1, libpath.max_len) - + strlen (implib) + 1); - if (*impath) - { - strcpy (trial, impath); - if (impath[pathlen - 1] != '/') - trial[pathlen++] = '/'; - strcpy (trial + pathlen, implib); - if (access (trial, R_OK) == 0) - soname = trial; - } - else - for (pl = libpath.plist; pl; pl = pl->next) - { - strcpy (trial, pl->prefix); - strcat (trial, implib); - if (access (trial, R_OK) == 0) - { - soname = trial; - break; - } - } + /* Currently we check only for libgcc, but this can be changed in future. */ + p = strstr (prog_name, "libgcc.a"); + if (p != 0 && (strlen (p) == sizeof ("libgcc.a") - 1)) + return 1; + return 0; +} - if (! soname) - fatal ("%s: library not found", implib); - if (debug) - if (*impmem) - fprintf (stderr, "%s (%s)\n", soname, impmem); - else - fprintf (stderr, "%s\n", soname); +/* Given a library name without "lib" prefix, this function + returns a full library name including a path. */ +static char * +resolve_lib_name (name) + char *name; +{ + char *lib_buf; + int i, j, l = 0; + + for (i = 0; libpaths[i]; i++) + if (libpaths[i]->max_len > l) + l = libpaths[i]->max_len; + + lib_buf = xmalloc (l + strlen(name) + 10); - do + for (i = 0; libpaths[i]; i++) + { + struct prefix_list *list = libpaths[i]->plist; + for (; list; list = list->next) + { + for (j = 0; libexts[j]; j++) { - /* scan imported shared objects for GCC GLOBAL ctors */ - short type; - if ((libptr = ldopen (soname, libptr)) == NULL) - fatal ("%s: can't open import library", soname); - if (TYPE (libptr) == ARTYPE) - { - LDFILE *memptr; - if (! *impmem) - fatal ("%s: no archive member specified", soname); - ldahread (libptr, &ah); - if (strcmp (ah.ar_name, impmem)) - continue; - } - type = HEADER (libptr).f_magic; - if (HEADER (libptr).f_flags & F_SHROBJ) + /* The following lines are needed because path_prefix list + may contain directories both with trailing '/' and + without it. */ + char *p = ""; + if (list->prefix[strlen(list->prefix)-1] != '/') + p = "/"; + sprintf (lib_buf, "%s%slib%s.%s", + list->prefix, p, name, libexts[j]); +if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); + if (file_exists (lib_buf)) { - SCNHDR soldsh; - LDHDR soldh; - long symcnt, i; - char *ldstrings; - LDSYM *lsyms; - if (!ldnshread (libptr, _LOADER, &soldsh)) - fatal ("%s: not an import library", soname); - FSEEK (libptr, soldsh.s_scnptr, BEGINNING); - if (FREAD (&soldh, sizeof (soldh), 1, libptr) != 1) - fatal ("%s: can't read loader section", soname); - /*fprintf (stderr, "\tscanning %s\n", soname);*/ - symcnt = soldh.l_nsyms; - lsyms = (LDSYM*) alloca (symcnt * sizeof (*lsyms)); - symcnt = FREAD (lsyms, sizeof (*lsyms), symcnt, libptr); - ldstrings = alloca (soldh.l_stlen); - FSEEK (libptr, soldsh.s_scnptr+soldh.l_stoff, BEGINNING); - FREAD (ldstrings, soldh.l_stlen, 1, libptr); - for (i = 0; i < symcnt; ++i) - { - LDSYM *l = lsyms + i; - if (LDR_EXPORT (*l)) - { - char *expname = 0; - if (l->l_zeroes) - expname = l->l_name; - else if (l->l_offset < soldh.l_stlen) - expname = ldstrings + l->l_offset; - switch (is_ctor_dtor (expname)) - { - case 3: - if (debug) - fprintf (stderr, "\t%s\n", expname); - add_to_list (&constructors, expname); - break; - - case 4: - add_to_list (&destructors, expname); - break; - - default: /* not a constructor or destructor */ - continue; - } - } - } +if (debug) fprintf (stderr, "found: %s\n", lib_buf); + return (lib_buf); } - else - fprintf (stderr, "%s: type = %04X flags = %04X\n", - ah.ar_name, type, HEADER (libptr).f_flags); } - while (ldclose (libptr) == FAILURE); - /* printf (stderr, "closed %s\n", soname); */ } } + if (debug) + fprintf (stderr, "not found\n"); + else + fatal ("Library lib%s not found", name); + return (NULL); +} + +/* Array of standard AIX libraries which should not + be scanned for ctors/dtors. */ +static char* aix_std_libs[] = { + "/unix", + "/lib/libc.a", + "/lib/libc_r.a", + "/usr/lib/libc.a", + "/usr/lib/libc_r.a", + "/usr/lib/threads/libc.a", + "/usr/ccs/lib/libc.a", + "/usr/ccs/lib/libc_r.a", + NULL +}; + +/* This function checks the filename and returns 1 + if this name matches the location of a standard AIX library. */ +static int +ignore_library (name) + char *name; +{ + char **p = &aix_std_libs[0]; + while (*p++ != NULL) + if (! strcmp (name, *p)) return 1; + return 0; } -#endif /* XCOFF_SCAN_LIBS */ + +#endif #endif /* OBJECT_FORMAT_COFF */ @@ -2787,7 +3020,7 @@ extern int encode_mach_o_hdr (); static void add_func_table PROTO((mo_header_t *, load_all_t *, symbol_info_t *, int)); static void print_header PROTO((mo_header_t *)); -static void print_load_command PROTO((load_union_t*, size_t, int)); +static void print_load_command PROTO((load_union_t *, size_t, int)); static void bad_header PROTO((int)); static struct file_info *read_file PROTO((char *, int, int)); static void end_file PROTO((struct file_info *)); @@ -2826,7 +3059,7 @@ scan_prog_file (prog_name, which_pass) prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY); if (prog_fd < 0) - fatal_perror ("can't read %s", prog_name); + fatal_perror ("cannot read %s", prog_name); obj_file = read_file (prog_name, prog_fd, rw); obj = obj_file->start; @@ -2930,10 +3163,10 @@ scan_prog_file (prog_name, which_pass) continue; str_sect = load_array[load_hdr->sym.symc_strings_section].section; - if (str_sect == (char *)0) + if (str_sect == (char *) 0) fatal ("string section missing"); - if (load_cmd->section == (char *)0) + if (load_cmd->section == (char *) 0) fatal ("section pointer missing"); num_syms = load_hdr->sym.symc_nentries; @@ -2998,11 +3231,11 @@ scan_prog_file (prog_name, which_pass) fatal ("no cmd_strings found"); /* Add __main to initializer list. - If we are building a program instead of a shared library, don't + If we are building a program instead of a shared library, do not do anything, since in the current version, you cannot do mallocs and such in the constructors. */ - if (main_sym != (symbol_info_t *)0 + if (main_sym != (symbol_info_t *) 0 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0)) add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION); @@ -3057,7 +3290,7 @@ scan_prog_file (prog_name, which_pass) if (debug) print_load_command (load_hdr, offset, i); - bcopy ((char *)load_hdr, (char *)(obj + offset), size); + bcopy ((char *) load_hdr, (char *) (obj + offset), size); offset += size; } } @@ -3096,7 +3329,7 @@ add_func_table (hdr_p, load_array, sym, type) load_cmd = &load_array[load_index]; load_cmd->load = ptr; - load_cmd->section = (char *)0; + load_cmd->section = (char *) 0; /* Fill in func table load command. */ ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE; @@ -3205,7 +3438,7 @@ print_load_command (load_hdr, offset, number) int number; { mo_long_t type = load_hdr->hdr.ldci_cmd_type; - char *type_str = (char *)0; + char *type_str = (char *) 0; switch (type) { @@ -3230,7 +3463,7 @@ print_load_command (load_hdr, offset, number) (long) load_hdr->hdr.ldci_section_off, (long) load_hdr->hdr.ldci_section_len); - if (type_str == (char *)0) + if (type_str == (char *) 0) fprintf (stderr, ", ty: unknown (%ld)\n", (long) type); else if (type != LDC_REGION) @@ -3269,7 +3502,7 @@ static void bad_header (status) int status; { - char *msg = (char *)0; + char *msg = (char *) 0; switch (status) { @@ -3281,7 +3514,7 @@ bad_header (status) case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break; } - if (msg == (char *)0) + if (msg == (char *) 0) fatal ("unknown {de,en}code_mach_o_hdr return value %d", status); else fatal ("%s", msg); @@ -3319,14 +3552,14 @@ read_file (name, fd, rw) page_size = sysconf (_SC_PAGE_SIZE); p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size; - p->start = mmap ((caddr_t)0, + p->start = mmap ((caddr_t) 0, (rw) ? p->rounded_size : p->size, (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ, MAP_FILE | MAP_VARIABLE | MAP_SHARED, fd, 0L); - if (p->start != (char *)0 && p->start != (char *)-1) + if (p->start != (char *) 0 && p->start != (char *) -1) p->use_mmap = 1; else diff --git a/contrib/gcc/combine.c b/contrib/gcc/combine.c index 473adc8..db9bb38 100644 --- a/contrib/gcc/combine.c +++ b/contrib/gcc/combine.c @@ -1,5 +1,5 @@ /* Optimize by combining instructions for GNU compiler. - Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -81,21 +81,23 @@ Boston, MA 02111-1307, USA. */ #include #endif -/* Must precede rtl.h for FFS. */ -#include +/* stdio.h must precede rtl.h for FFS. */ +#include "system.h" #include "rtl.h" #include "flags.h" #include "regs.h" #include "hard-reg-set.h" -#include "expr.h" #include "basic-block.h" #include "insn-config.h" +/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */ +#include "expr.h" #include "insn-flags.h" #include "insn-codes.h" #include "insn-attr.h" #include "recog.h" #include "real.h" +#include "toplev.h" /* It is not safe to use ordinary gen_lowpart in combine. Use gen_lowpart_for_combine instead. See comments there. */ @@ -140,9 +142,8 @@ static int max_uid_cuid; /* Get the cuid of an insn. */ -#define INSN_CUID(INSN) (INSN_UID (INSN) > max_uid_cuid \ - ? (abort(), 0) \ - : uid_cuid[INSN_UID (INSN)]) +#define INSN_CUID(INSN) \ +(INSN_UID (INSN) > max_uid_cuid ? insn_cuid (INSN) : uid_cuid[INSN_UID (INSN)]) /* Maximum register number, which is the size of the tables below. */ @@ -199,13 +200,6 @@ static HARD_REG_SET newpat_used_regs; static rtx added_links_insn; -/* This is the value of undobuf.num_undo when we started processing this - substitution. This will prevent gen_rtx_combine from re-used a piece - from the previous expression. Doing so can produce circular rtl - structures. */ - -static int previous_num_undos; - /* Basic block number of the block in which we are performing combines. */ static int this_basic_block; @@ -253,7 +247,7 @@ static int this_basic_block; reg_last_set_invalid[i] is set non-zero when register I is being assigned to and reg_last_set_table_tick[i] == label_tick. */ -/* Record last value assigned to (hard or pseudo) register n. */ +/* Record last value assigned to (hard or pseudo) register n. */ static rtx *reg_last_set_value; @@ -263,7 +257,7 @@ static rtx *reg_last_set_value; static int *reg_last_set_label; /* Record the value of label_tick when an expression involving register n - is placed in reg_last_set_value. */ + is placed in reg_last_set_value. */ static int *reg_last_set_table_tick; @@ -272,7 +266,7 @@ static int *reg_last_set_table_tick; static char *reg_last_set_invalid; -/* Incremented for each label. */ +/* Incremented for each label. */ static int label_tick; @@ -320,6 +314,7 @@ static char *reg_last_set_sign_bit_copies; struct undo { + struct undo *next; int is_int; union {rtx r; int i;} old_contents; union {rtx *r; int *i;} where; @@ -332,15 +327,19 @@ struct undo The value of storage is what to pass to obfree. other_insn is nonzero if we have modified some other insn in the process - of working on subst_insn. It must be verified too. */ + of working on subst_insn. It must be verified too. -#define MAX_UNDO 50 + previous_undos is the value of undobuf.undos when we started processing + this substitution. This will prevent gen_rtx_combine from re-used a piece + from the previous expression. Doing so can produce circular rtl + structures. */ struct undobuf { - int num_undo; char *storage; - struct undo undo[MAX_UNDO]; + struct undo *undos; + struct undo *frees; + struct undo *previous_undos; rtx other_insn; }; @@ -353,32 +352,44 @@ static struct undobuf undobuf; the undo table. */ #define SUBST(INTO, NEWVAL) \ - do { rtx _new = (NEWVAL); \ - if (undobuf.num_undo < MAX_UNDO) \ - { \ - undobuf.undo[undobuf.num_undo].is_int = 0; \ - undobuf.undo[undobuf.num_undo].where.r = &INTO; \ - undobuf.undo[undobuf.num_undo].old_contents.r = INTO; \ - INTO = _new; \ - if (undobuf.undo[undobuf.num_undo].old_contents.r != INTO) \ - undobuf.num_undo++; \ - } \ + do { rtx _new = (NEWVAL); \ + struct undo *_buf; \ + \ + if (undobuf.frees) \ + _buf = undobuf.frees, undobuf.frees = _buf->next; \ + else \ + _buf = (struct undo *) xmalloc (sizeof (struct undo)); \ + \ + _buf->is_int = 0; \ + _buf->where.r = &INTO; \ + _buf->old_contents.r = INTO; \ + INTO = _new; \ + if (_buf->old_contents.r == INTO) \ + _buf->next = undobuf.frees, undobuf.frees = _buf; \ + else \ + _buf->next = undobuf.undos, undobuf.undos = _buf; \ } while (0) -/* Similar to SUBST, but NEWVAL is an int. INTO will normally be an XINT - expression. - Note that substitution for the value of a CONST_INT is not safe. */ +/* Similar to SUBST, but NEWVAL is an int expression. Note that substitution + for the value of a HOST_WIDE_INT value (including CONST_INT) is + not safe. */ #define SUBST_INT(INTO, NEWVAL) \ - do { if (undobuf.num_undo < MAX_UNDO) \ -{ \ - undobuf.undo[undobuf.num_undo].is_int = 1; \ - undobuf.undo[undobuf.num_undo].where.i = (int *) &INTO; \ - undobuf.undo[undobuf.num_undo].old_contents.i = INTO; \ - INTO = NEWVAL; \ - if (undobuf.undo[undobuf.num_undo].old_contents.i != INTO) \ - undobuf.num_undo++; \ - } \ + do { struct undo *_buf; \ + \ + if (undobuf.frees) \ + _buf = undobuf.frees, undobuf.frees = _buf->next; \ + else \ + _buf = (struct undo *) xmalloc (sizeof (struct undo)); \ + \ + _buf->is_int = 1; \ + _buf->where.i = (int *) &INTO; \ + _buf->old_contents.i = INTO; \ + INTO = NEWVAL; \ + if (_buf->old_contents.i == INTO) \ + _buf->next = undobuf.frees, undobuf.frees = _buf; \ + else \ + _buf->next = undobuf.undos, undobuf.undos = _buf; \ } while (0) /* Number of times the pseudo being substituted for @@ -386,10 +397,11 @@ static struct undobuf undobuf; static int n_occurrences; -static void init_reg_last_arrays PROTO(()); -static void setup_incoming_promotions PROTO(()); +static void init_reg_last_arrays PROTO((void)); +static void setup_incoming_promotions PROTO((void)); static void set_nonzero_bits_and_sign_copies PROTO((rtx, rtx)); static int can_combine_p PROTO((rtx, rtx, rtx, rtx, rtx *, rtx *)); +static int sets_function_arg_p PROTO((rtx)); static int combinable_i3pat PROTO((rtx, rtx *, rtx, rtx, int, rtx *)); static rtx try_combine PROTO((rtx, rtx, rtx)); static void undo_all PROTO((void)); @@ -410,6 +422,7 @@ static rtx force_to_mode PROTO((rtx, enum machine_mode, unsigned HOST_WIDE_INT, rtx, int)); static rtx if_then_else_cond PROTO((rtx, rtx *, rtx *)); static rtx known_cond PROTO((rtx, enum rtx_code, rtx, rtx)); +static int rtx_equal_for_field_assignment_p PROTO((rtx, rtx)); static rtx make_field_assignment PROTO((rtx)); static rtx apply_distributive_law PROTO((rtx)); static rtx simplify_and_const_int PROTO((rtx, enum machine_mode, rtx, @@ -435,16 +448,17 @@ static void update_table_tick PROTO((rtx)); static void record_value_for_reg PROTO((rtx, rtx, rtx)); static void record_dead_and_set_regs_1 PROTO((rtx, rtx)); static void record_dead_and_set_regs PROTO((rtx)); -static int get_last_value_validate PROTO((rtx *, int, int)); +static int get_last_value_validate PROTO((rtx *, rtx, int, int)); static rtx get_last_value PROTO((rtx)); static int use_crosses_set_p PROTO((rtx, int)); static void reg_dead_at_p_1 PROTO((rtx, rtx)); static int reg_dead_at_p PROTO((rtx, rtx)); -static void move_deaths PROTO((rtx, int, rtx, rtx *)); +static void move_deaths PROTO((rtx, rtx, int, rtx, rtx *)); static int reg_bitfield_target_p PROTO((rtx, rtx)); static void distribute_notes PROTO((rtx, rtx, rtx, rtx, rtx, rtx)); static void distribute_links PROTO((rtx)); static void mark_used_regs_combine PROTO((rtx)); +static int insn_cuid PROTO((rtx)); /* Main entry point for combiner. F is the first insn of the function. NREGS is the first unused pseudo-reg number. */ @@ -454,7 +468,10 @@ combine_instructions (f, nregs) rtx f; int nregs; { - register rtx insn, next, prev; + register rtx insn, next; +#ifdef HAVE_cc0 + register rtx prev; +#endif register int i; register rtx links, nextlinks; @@ -462,7 +479,7 @@ combine_instructions (f, nregs) combine_merges = 0; combine_extras = 0; combine_successes = 0; - undobuf.num_undo = previous_num_undos = 0; + undobuf.undos = undobuf.previous_undos = 0; combine_max_regno = nregs; @@ -535,6 +552,12 @@ combine_instructions (f, nregs) { note_stores (PATTERN (insn), set_nonzero_bits_and_sign_copies); record_dead_and_set_regs (insn); + +#ifdef AUTO_INC_DEC + for (links = REG_NOTES (insn); links; links = XEXP (links, 1)) + if (REG_NOTE_KIND (links) == REG_INC) + set_nonzero_bits_and_sign_copies (XEXP (links, 0), NULL_RTX); +#endif } if (GET_CODE (insn) == CODE_LABEL) @@ -694,17 +717,18 @@ setup_incoming_promotions () for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (FUNCTION_ARG_REGNO_P (regno) && (reg = promoted_input_arg (regno, &mode, &unsignedp)) != 0) - record_value_for_reg (reg, first, - gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, - GET_MODE (reg), - gen_rtx (CLOBBER, mode, const0_rtx))); + { + record_value_for_reg + (reg, first, gen_rtx_fmt_e ((unsignedp ? ZERO_EXTEND + : SIGN_EXTEND), + GET_MODE (reg), + gen_rtx_CLOBBER (mode, const0_rtx))); + } #endif } -/* Called via note_stores. If X is a pseudo that is used in more than - one basic block, is narrower that HOST_BITS_PER_WIDE_INT, and is being - set, record what bits are known zero. If we are clobbering X, - ignore this "set" because the clobbered value won't be used. +/* Called via note_stores. If X is a pseudo that is narrower than + HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero. If we are setting only a portion of X and we can't figure out what portion, assume all bits will be used since we don't know what will @@ -723,18 +747,15 @@ set_nonzero_bits_and_sign_copies (x, set) if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER - && reg_n_sets[REGNO (x)] > 1 - && reg_basic_block[REGNO (x)] < 0 /* If this register is undefined at the start of the file, we can't say what its contents were. */ - && ! (basic_block_live_at_start[0][REGNO (x) / REGSET_ELT_BITS] - & ((REGSET_ELT_TYPE) 1 << (REGNO (x) % REGSET_ELT_BITS))) + && ! REGNO_REG_SET_P (basic_block_live_at_start[0], REGNO (x)) && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT) { - if (GET_CODE (set) == CLOBBER) + if (set == 0 || GET_CODE (set) == CLOBBER) { reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x)); - reg_sign_bit_copies[REGNO (x)] = 0; + reg_sign_bit_copies[REGNO (x)] = 1; return; } @@ -784,7 +805,7 @@ set_nonzero_bits_and_sign_copies (x, set) else { reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x)); - reg_sign_bit_copies[REGNO (x)] = 0; + reg_sign_bit_copies[REGNO (x)] = 1; } } } @@ -808,7 +829,10 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) { int i; rtx set = 0, src, dest; - rtx p, link; + rtx p; +#ifdef AUTO_INC_DEC + rtx link; +#endif int all_adjacent = (succ ? (next_active_insn (insn) == succ && next_active_insn (succ) == i3) : next_active_insn (insn) == i3); @@ -839,6 +863,43 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) switch (GET_CODE (elt)) { + /* This is important to combine floating point insns + for the SH4 port. */ + case USE: + /* Combining an isolated USE doesn't make sense. + We depend here on combinable_i3_pat to reject them. */ + /* The code below this loop only verifies that the inputs of + the SET in INSN do not change. We call reg_set_between_p + to verify that the REG in the USE does not change betweeen + I3 and INSN. + If the USE in INSN was for a pseudo register, the matching + insn pattern will likely match any register; combining this + with any other USE would only be safe if we knew that the + used registers have identical values, or if there was + something to tell them apart, e.g. different modes. For + now, we forgo such compilcated tests and simply disallow + combining of USES of pseudo registers with any other USE. */ + if (GET_CODE (XEXP (elt, 0)) == REG + && GET_CODE (PATTERN (i3)) == PARALLEL) + { + rtx i3pat = PATTERN (i3); + int i = XVECLEN (i3pat, 0) - 1; + int regno = REGNO (XEXP (elt, 0)); + do + { + rtx i3elt = XVECEXP (i3pat, 0, i); + if (GET_CODE (i3elt) == USE + && GET_CODE (XEXP (i3elt, 0)) == REG + && (REGNO (XEXP (i3elt, 0)) == regno + ? reg_set_between_p (XEXP (elt, 0), + PREV_INSN (insn), i3) + : regno >= FIRST_PSEUDO_REGISTER)) + return 0; + } + while (--i >= 0); + } + break; + /* We can ignore CLOBBERs. */ case CLOBBER: break; @@ -939,7 +1000,12 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) insns. Eliminate this problem by not combining with such an insn. Also, on some machines we don't want to extend the life of a hard - register. */ + register. + + This is the same test done in can_combine except that we don't test + if SRC is a CALL operation to permit a hard register with + SMALL_REGISTER_CLASSES, and that we have to take all_adjacent + into account. */ if (GET_CODE (src) == REG && ((REGNO (dest) < FIRST_PSEUDO_REGISTER @@ -947,13 +1013,16 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) /* Don't extend the life of a hard register unless it is user variable (if we have few registers) or it can't fit into the desired register (meaning something special - is going on). */ + is going on). + Also avoid substituting a return register into I3, because + reload can't handle a conflict with constraints of other + inputs. */ || (REGNO (src) < FIRST_PSEUDO_REGISTER && (! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)) -#ifdef SMALL_REGISTER_CLASSES - || ! REG_USERVAR_P (src) -#endif - )))) + || (SMALL_REGISTER_CLASSES + && ((! all_adjacent && ! REG_USERVAR_P (src)) + || (FUNCTION_VALUE_REGNO_P (REGNO (src)) + && ! REG_USERVAR_P (src)))))))) return 0; } else if (GET_CODE (dest) != CC0) @@ -971,14 +1040,26 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) return 0; /* If INSN contains anything volatile, or is an `asm' (whether volatile - or not), reject, unless nothing volatile comes between it and I3, - with the exception of SUCC. */ + or not), reject, unless nothing volatile comes between it and I3 */ if (GET_CODE (src) == ASM_OPERANDS || volatile_refs_p (src)) - for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p)) - if (GET_RTX_CLASS (GET_CODE (p)) == 'i' - && p != succ && volatile_refs_p (PATTERN (p))) - return 0; + { + /* Make sure succ doesn't contain a volatile reference. */ + if (succ != 0 && volatile_refs_p (PATTERN (succ))) + return 0; + + for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p)) + if (GET_RTX_CLASS (GET_CODE (p)) == 'i' + && p != succ && volatile_refs_p (PATTERN (p))) + return 0; + } + + /* If INSN is an asm, and DEST is a hard register, reject, since it has + to be an explicit register variable, and was chosen for a reason. */ + + if (GET_CODE (src) == ASM_OPERANDS + && GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER) + return 0; /* If there are any volatile insns between INSN and I3, reject, because they might affect machine state. */ @@ -1028,6 +1109,46 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) return 1; } +/* Check if PAT is an insn - or a part of it - used to set up an + argument for a function in a hard register. */ + +static int +sets_function_arg_p (pat) + rtx pat; +{ + int i; + rtx inner_dest; + + switch (GET_CODE (pat)) + { + case INSN: + return sets_function_arg_p (PATTERN (pat)); + + case PARALLEL: + for (i = XVECLEN (pat, 0); --i >= 0;) + if (sets_function_arg_p (XVECEXP (pat, 0, i))) + return 1; + + break; + + case SET: + inner_dest = SET_DEST (pat); + while (GET_CODE (inner_dest) == STRICT_LOW_PART + || GET_CODE (inner_dest) == SUBREG + || GET_CODE (inner_dest) == ZERO_EXTRACT) + inner_dest = XEXP (inner_dest, 0); + + return (GET_CODE (inner_dest) == REG + && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER + && FUNCTION_ARG_REGNO_P (REGNO (inner_dest))); + + default: + break; + } + + return 0; +} + /* LOC is the location within I3 that contains its pattern or the component of a PARALLEL of the pattern. We validate that it is valid for combining. @@ -1056,7 +1177,7 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc) If I1_NOT_IN_SRC is non-zero, it means that finding I1 in the source of a SET must prevent combination from occurring. - On machines where SMALL_REGISTER_CLASSES is defined, we don't combine + On machines where SMALL_REGISTER_CLASSES is non-zero, we don't combine if the destination of a SET is a hard register that isn't a user variable. @@ -1085,7 +1206,11 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed) rtx set = expand_field_assignment (x); rtx dest = SET_DEST (set); rtx src = SET_SRC (set); - rtx inner_dest = dest, inner_src = src; + rtx inner_dest = dest; + +#if 0 + rtx inner_src = src; +#endif SUBST (*loc, set); @@ -1123,17 +1248,28 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed) if ((inner_dest != dest && (reg_overlap_mentioned_p (i2dest, inner_dest) || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest)))) + /* This is the same test done in can_combine_p except that we allow a hard register with SMALL_REGISTER_CLASSES if SRC is a - CALL operation. */ + CALL operation. Moreover, we can't test all_adjacent; we don't + have to, since this instruction will stay in place, thus we are + not considering increasing the lifetime of INNER_DEST. + + Also, if this insn sets a function argument, combining it with + something that might need a spill could clobber a previous + function argument; the all_adjacent test in can_combine_p also + checks this; here, we do a more specific test for this case. */ + || (GET_CODE (inner_dest) == REG && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER && (! HARD_REGNO_MODE_OK (REGNO (inner_dest), GET_MODE (inner_dest)) -#ifdef SMALL_REGISTER_CLASSES - || (GET_CODE (src) != CALL && ! REG_USERVAR_P (inner_dest)) -#endif - )) + || (SMALL_REGISTER_CLASSES && GET_CODE (src) != CALL + && ! REG_USERVAR_P (inner_dest) + && (FUNCTION_VALUE_REGNO_P (REGNO (inner_dest)) + || (FUNCTION_ARG_REGNO_P (REGNO (inner_dest)) + && i3 != 0 + && sets_function_arg_p (prev_nonnote_insn (i3))))))) || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src))) return 0; @@ -1240,7 +1376,7 @@ try_combine (i3, i2, i1) combine_attempts++; - undobuf.num_undo = previous_num_undos = 0; + undobuf.undos = undobuf.previous_undos = 0; undobuf.other_insn = 0; /* Save the current high-water-mark so we can free storage if we didn't @@ -1273,11 +1409,10 @@ try_combine (i3, i2, i1) if (i1 == 0 && GET_CODE (i3) == INSN && GET_CODE (PATTERN (i3)) == SET && GET_CODE (SET_SRC (PATTERN (i3))) == REG && REGNO (SET_SRC (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER -#ifdef SMALL_REGISTER_CLASSES - && (GET_CODE (SET_DEST (PATTERN (i3))) != REG - || REGNO (SET_DEST (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER - || REG_USERVAR_P (SET_DEST (PATTERN (i3)))) -#endif + && (! SMALL_REGISTER_CLASSES + || (GET_CODE (SET_DEST (PATTERN (i3))) != REG + || REGNO (SET_DEST (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER + || REG_USERVAR_P (SET_DEST (PATTERN (i3))))) && find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3))) && GET_CODE (PATTERN (i2)) == PARALLEL && ! side_effects_p (SET_DEST (PATTERN (i3))) @@ -1304,7 +1439,8 @@ try_combine (i3, i2, i1) The problem can also happen if the dest of I3 is a memory ref, if another dest in I2 is an indirect memory ref. */ for (i = 0; i < XVECLEN (p2, 0); i++) - if (GET_CODE (XVECEXP (p2, 0, i)) == SET + if ((GET_CODE (XVECEXP (p2, 0, i)) == SET + || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER) && reg_overlap_mentioned_p (SET_DEST (PATTERN (i3)), SET_DEST (XVECEXP (p2, 0, i)))) break; @@ -1371,8 +1507,9 @@ try_combine (i3, i2, i1) as I2 will not cause a problem. */ subst_prev_insn = i1 - = gen_rtx (INSN, VOIDmode, INSN_UID (i2), 0, i2, - XVECEXP (PATTERN (i2), 0, 1), -1, 0, 0); + = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2, + XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX, + NULL_RTX); SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0)); SUBST (XEXP (SET_SRC (PATTERN (i2)), 0), @@ -1469,7 +1606,7 @@ try_combine (i3, i2, i1) I2DEST. */ i2pat = (GET_CODE (PATTERN (i2)) == PARALLEL - ? gen_rtx (SET, VOIDmode, i2dest, i2src) + ? gen_rtx_SET (VOIDmode, i2dest, i2src) : PATTERN (i2)); if (added_sets_2) @@ -1513,7 +1650,7 @@ try_combine (i3, i2, i1) i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0); } - previous_num_undos = undobuf.num_undo; + undobuf.previous_undos = undobuf.undos; } #ifndef HAVE_cc0 @@ -1533,8 +1670,10 @@ try_combine (i3, i2, i1) && XEXP (SET_SRC (PATTERN (i3)), 1) == const0_rtx && rtx_equal_p (XEXP (SET_SRC (PATTERN (i3)), 0), i2dest)) { +#ifdef EXTRA_CC_MODES rtx *cc_use; enum machine_mode compare_mode; +#endif newpat = PATTERN (i3); SUBST (XEXP (SET_SRC (newpat), 0), i2src); @@ -1555,10 +1694,10 @@ try_combine (i3, i2, i1) != GET_MODE (SET_DEST (newpat)))) { int regno = REGNO (SET_DEST (newpat)); - rtx new_dest = gen_rtx (REG, compare_mode, regno); + rtx new_dest = gen_rtx_REG (compare_mode, regno); if (regno < FIRST_PSEUDO_REGISTER - || (reg_n_sets[regno] == 1 && ! added_sets_2 + || (REG_N_SETS (regno) == 1 && ! added_sets_2 && ! REG_USERVAR_P (SET_DEST (newpat)))) { if (regno >= FIRST_PSEUDO_REGISTER) @@ -1587,7 +1726,7 @@ try_combine (i3, i2, i1) subst_low_cuid = INSN_CUID (i2); newpat = subst (PATTERN (i3), i2dest, i2src, 0, ! i1_feeds_i3 && i1dest_in_i1src); - previous_num_undos = undobuf.num_undo; + undobuf.previous_undos = undobuf.undos; /* Record whether i2's body now appears within i3's body. */ i2_is_used = n_occurrences; @@ -1600,7 +1739,7 @@ try_combine (i3, i2, i1) { /* Before we can do this substitution, we must redo the test done above (see detailed comments there) that ensures that I1DEST - isn't mentioned in any SETs in NEWPAT that are field assignments. */ + isn't mentioned in any SETs in NEWPAT that are field assignments. */ if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX, 0, NULL_PTR)) @@ -1612,7 +1751,7 @@ try_combine (i3, i2, i1) n_occurrences = 0; subst_low_cuid = INSN_CUID (i1); newpat = subst (newpat, i1dest, i1src, 0, 0); - previous_num_undos = undobuf.num_undo; + undobuf.previous_undos = undobuf.undos; } /* Fail if an autoincrement side-effect has been duplicated. Be careful @@ -1649,22 +1788,22 @@ try_combine (i3, i2, i1) { rtvec old = XVEC (newpat, 0); total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2; - newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets)); - bcopy ((char *) &old->elem[0], (char *) &XVECEXP (newpat, 0, 0), + newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets)); + bcopy ((char *) &old->elem[0], (char *) XVEC (newpat, 0)->elem, sizeof (old->elem[0]) * old->num_elem); } else { rtx old = newpat; total_sets = 1 + added_sets_1 + added_sets_2; - newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets)); + newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets)); XVECEXP (newpat, 0, 0) = old; } if (added_sets_1) XVECEXP (newpat, 0, --total_sets) = (GET_CODE (PATTERN (i1)) == PARALLEL - ? gen_rtx (SET, VOIDmode, i1dest, i1src) : PATTERN (i1)); + ? gen_rtx_SET (VOIDmode, i1dest, i1src) : PATTERN (i1)); if (added_sets_2) { @@ -1761,17 +1900,17 @@ try_combine (i3, i2, i1) && GET_MODE (SET_DEST (newpat)) != VOIDmode && GET_CODE (i2dest) == REG && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER - || (reg_n_sets[REGNO (i2dest)] == 1 && ! added_sets_2 + || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2 && ! REG_USERVAR_P (i2dest)))) - ni2dest = gen_rtx (REG, GET_MODE (SET_DEST (newpat)), + ni2dest = gen_rtx_REG (GET_MODE (SET_DEST (newpat)), REGNO (i2dest)); - m_split = split_insns (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, newpat, - gen_rtx (CLOBBER, - VOIDmode, - ni2dest))), - i3); + m_split = split_insns + (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, newpat, + gen_rtx_CLOBBER (VOIDmode, + ni2dest))), + i3); } if (m_split && GET_CODE (m_split) == SEQUENCE @@ -1798,9 +1937,12 @@ try_combine (i3, i2, i1) &i2_scratches); /* If I2 or I3 has multiple SETs, we won't know how to track - register status, so don't use these insns. */ + register status, so don't use these insns. If I2's destination + is used between I2 and I3, we also can't use these insns. */ - if (i2_code_number >= 0 && i2set && i3set) + 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); if (insn_code_number >= 0) @@ -1809,10 +1951,26 @@ try_combine (i3, i2, i1) /* It is possible that both insns now set the destination of I3. If so, we must show an extra use of it. */ - if (insn_code_number >= 0 && GET_CODE (SET_DEST (i3set)) == REG - && GET_CODE (SET_DEST (i2set)) == REG - && REGNO (SET_DEST (i3set)) == REGNO (SET_DEST (i2set))) - reg_n_sets[REGNO (SET_DEST (i2set))]++; + if (insn_code_number >= 0) + { + rtx new_i3_dest = SET_DEST (i3set); + rtx new_i2_dest = SET_DEST (i2set); + + while (GET_CODE (new_i3_dest) == ZERO_EXTRACT + || GET_CODE (new_i3_dest) == STRICT_LOW_PART + || GET_CODE (new_i3_dest) == SUBREG) + new_i3_dest = XEXP (new_i3_dest, 0); + + while (GET_CODE (new_i2_dest) == ZERO_EXTRACT + || GET_CODE (new_i2_dest) == STRICT_LOW_PART + || GET_CODE (new_i2_dest) == SUBREG) + new_i2_dest = XEXP (new_i2_dest, 0); + + if (GET_CODE (new_i3_dest) == REG + && GET_CODE (new_i2_dest) == REG + && REGNO (new_i3_dest) == REGNO (new_i2_dest)) + REG_N_SETS (REGNO (new_i2_dest))++; + } } /* If we can split it and use I2DEST, go ahead and see if that @@ -1827,7 +1985,7 @@ try_combine (i3, i2, i1) && (GET_MODE (*split) == GET_MODE (i2dest) || GET_MODE (*split) == VOIDmode || REGNO (i2dest) < FIRST_PSEUDO_REGISTER - || (reg_n_sets[REGNO (i2dest)] == 1 && ! added_sets_2 + || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2 && ! REG_USERVAR_P (i2dest))) && (next_real_insn (i2) == i3 || ! use_crosses_set_p (*split, INSN_CUID (i2))) @@ -1843,7 +2001,7 @@ try_combine (i3, i2, i1) validated that we can do this. */ if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode) { - newdest = gen_rtx (REG, split_mode, REGNO (i2dest)); + newdest = gen_rtx_REG (split_mode, REGNO (i2dest)); if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER) SUBST (regno_reg_rtx[REGNO (i2dest)], newdest); @@ -1956,7 +2114,7 @@ try_combine (i3, i2, i1) that destination. */ PATTERN (i3) = newpat; - distribute_links (gen_rtx (INSN_LIST, VOIDmode, i3, NULL_RTX)); + distribute_links (gen_rtx_INSN_LIST (VOIDmode, i3, NULL_RTX)); /* I3 now uses what used to be its destination and which is now I2's destination. That means we need a LOG_LINK from @@ -2010,8 +2168,21 @@ try_combine (i3, i2, i1) && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0)), XVECEXP (newpat, 0, 1))) { - newi2pat = XVECEXP (newpat, 0, 1); - newpat = XVECEXP (newpat, 0, 0); + /* Normally, it doesn't matter which of the two is done first, + but it does if one references cc0. In that case, it has to + be first. */ +#ifdef HAVE_cc0 + if (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0))) + { + newi2pat = XVECEXP (newpat, 0, 0); + newpat = XVECEXP (newpat, 0, 1); + } + else +#endif + { + newi2pat = XVECEXP (newpat, 0, 1); + newpat = XVECEXP (newpat, 0, 0); + } i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches); @@ -2063,7 +2234,7 @@ try_combine (i3, i2, i1) && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn))) { if (GET_CODE (XEXP (note, 0)) == REG) - reg_n_deaths[REGNO (XEXP (note, 0))]--; + REG_N_DEATHS (REGNO (XEXP (note, 0)))--; remove_note (undobuf.other_insn, note); } @@ -2071,7 +2242,7 @@ try_combine (i3, i2, i1) for (note = new_other_notes; note; note = XEXP (note, 1)) if (GET_CODE (XEXP (note, 0)) == REG) - reg_n_deaths[REGNO (XEXP (note, 0))]++; + REG_N_DEATHS (REGNO (XEXP (note, 0)))++; distribute_notes (new_other_notes, undobuf.other_insn, undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX); @@ -2085,10 +2256,15 @@ try_combine (i3, i2, i1) rtx i3links, i2links, i1links = 0; rtx midnotes = 0; register int regno; - /* Compute which registers we expect to eliminate. */ - rtx elim_i2 = (newi2pat || i2dest_in_i2src || i2dest_in_i1src + /* Compute which registers we expect to eliminate. newi2pat may be setting + either i3dest or i2dest, so we must check it. Also, i1dest may be the + same as i3dest, in which case newi2pat may be setting i1dest. */ + rtx elim_i2 = ((newi2pat && reg_set_p (i2dest, newi2pat)) + || i2dest_in_i2src || i2dest_in_i1src ? 0 : i2dest); - rtx elim_i1 = i1 == 0 || i1dest_in_i1src ? 0 : i1dest; + rtx elim_i1 = (i1 == 0 || i1dest_in_i1src + || (newi2pat && reg_set_p (i1dest, newi2pat)) + ? 0 : i1dest); /* Get the old REG_NOTES and LOG_LINKS from all our insns and clear them. */ @@ -2186,11 +2362,18 @@ try_combine (i3, i2, i1) } /* Get death notes for everything that is now used in either I3 or - I2 and used to die in a previous insn. */ + I2 and used to die in a previous insn. If we built two new + patterns, move from I1 to I2 then I2 to I3 so that we get the + proper movement on registers that I2 modifies. */ - move_deaths (newpat, i1 ? INSN_CUID (i1) : INSN_CUID (i2), i3, &midnotes); if (newi2pat) - move_deaths (newi2pat, INSN_CUID (i1), i2, &midnotes); + { + move_deaths (newi2pat, NULL_RTX, INSN_CUID (i1), i2, &midnotes); + move_deaths (newpat, newi2pat, INSN_CUID (i1), i3, &midnotes); + } + else + move_deaths (newpat, NULL_RTX, i1 ? INSN_CUID (i1) : INSN_CUID (i2), + i3, &midnotes); /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */ if (i3notes) @@ -2215,7 +2398,7 @@ try_combine (i3, i2, i1) { for (temp = new_i2_notes; temp; temp = XEXP (temp, 1)) if (GET_CODE (XEXP (temp, 0)) == REG) - reg_n_deaths[REGNO (XEXP (temp, 0))]++; + REG_N_DEATHS (REGNO (XEXP (temp, 0)))++; distribute_notes (new_i2_notes, i2, i2, NULL_RTX, NULL_RTX, NULL_RTX); } @@ -2224,41 +2407,44 @@ try_combine (i3, i2, i1) { for (temp = new_i3_notes; temp; temp = XEXP (temp, 1)) if (GET_CODE (XEXP (temp, 0)) == REG) - reg_n_deaths[REGNO (XEXP (temp, 0))]++; + REG_N_DEATHS (REGNO (XEXP (temp, 0)))++; distribute_notes (new_i3_notes, i3, i3, NULL_RTX, NULL_RTX, NULL_RTX); } /* If I3DEST was used in I3SRC, it really died in I3. We may need to - put a REG_DEAD note for it somewhere. Similarly for I2 and I1. + put a REG_DEAD note for it somewhere. If NEWI2PAT exists and sets + I3DEST, the death must be somewhere before I2, not I3. If we passed I3 + in that case, it might delete I2. Similarly for I2 and I1. Show an additional death due to the REG_DEAD note we make here. If we discard it in distribute_notes, we will decrement it again. */ if (i3dest_killed) { if (GET_CODE (i3dest_killed) == REG) - reg_n_deaths[REGNO (i3dest_killed)]++; + REG_N_DEATHS (REGNO (i3dest_killed))++; - distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i3dest_killed, - NULL_RTX), - NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, - NULL_RTX, NULL_RTX); + if (newi2pat && reg_set_p (i3dest_killed, newi2pat)) + distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed, + NULL_RTX), + NULL_RTX, i2, NULL_RTX, elim_i2, elim_i1); + else + distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed, + NULL_RTX), + NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, + elim_i2, elim_i1); } - /* For I2 and I1, we have to be careful. If NEWI2PAT exists and sets - I2DEST or I1DEST, the death must be somewhere before I2, not I3. If - we passed I3 in that case, it might delete I2. */ - if (i2dest_in_i2src) { if (GET_CODE (i2dest) == REG) - reg_n_deaths[REGNO (i2dest)]++; + REG_N_DEATHS (REGNO (i2dest))++; if (newi2pat && reg_set_p (i2dest, newi2pat)) - distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, NULL_RTX), + distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX), NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX); else - distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, NULL_RTX), + distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX), NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, NULL_RTX, NULL_RTX); } @@ -2266,13 +2452,13 @@ try_combine (i3, i2, i1) if (i1dest_in_i1src) { if (GET_CODE (i1dest) == REG) - reg_n_deaths[REGNO (i1dest)]++; + REG_N_DEATHS (REGNO (i1dest))++; if (newi2pat && reg_set_p (i1dest, newi2pat)) - distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, NULL_RTX), + distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX), NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX); else - distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, NULL_RTX), + distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX), NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, NULL_RTX, NULL_RTX); } @@ -2303,14 +2489,15 @@ try_combine (i3, i2, i1) /* If the reg formerly set in I2 died only once and that was in I3, zero its use count so it won't make `reload' do any work. */ - if (! added_sets_2 && newi2pat == 0 && ! i2dest_in_i2src) + if (! added_sets_2 + && (newi2pat == 0 || ! reg_mentioned_p (i2dest, newi2pat)) + && ! i2dest_in_i2src) { regno = REGNO (i2dest); - reg_n_sets[regno]--; - if (reg_n_sets[regno] == 0 - && ! (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] - & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)))) - reg_n_refs[regno] = 0; + REG_N_SETS (regno)--; + if (REG_N_SETS (regno) == 0 + && ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno)) + REG_N_REFS (regno) = 0; } } @@ -2329,11 +2516,10 @@ try_combine (i3, i2, i1) regno = REGNO (i1dest); if (! added_sets_1 && ! i1dest_in_i1src) { - reg_n_sets[regno]--; - if (reg_n_sets[regno] == 0 - && ! (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] - & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)))) - reg_n_refs[regno] = 0; + REG_N_SETS (regno)--; + if (REG_N_SETS (regno) == 0 + && ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno)) + REG_N_REFS (regno) = 0; } } @@ -2379,20 +2565,22 @@ try_combine (i3, i2, i1) static void undo_all () { - register int i; - if (undobuf.num_undo > MAX_UNDO) - undobuf.num_undo = MAX_UNDO; - for (i = undobuf.num_undo - 1; i >= 0; i--) + struct undo *undo, *next; + + for (undo = undobuf.undos; undo; undo = next) { - if (undobuf.undo[i].is_int) - *undobuf.undo[i].where.i = undobuf.undo[i].old_contents.i; + next = undo->next; + if (undo->is_int) + *undo->where.i = undo->old_contents.i; else - *undobuf.undo[i].where.r = undobuf.undo[i].old_contents.r; - + *undo->where.r = undo->old_contents.r; + + undo->next = undobuf.frees; + undobuf.frees = undo; } obfree (undobuf.storage); - undobuf.num_undo = 0; + undobuf.undos = undobuf.previous_undos = 0; /* Clear this here, so that subsequent get_last_value calls are not affected. */ @@ -2454,7 +2642,7 @@ find_split_point (loc, insn) && ! memory_address_p (GET_MODE (x), XEXP (x, 0))) { rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER]; - rtx seq = split_insns (gen_rtx (SET, VOIDmode, reg, XEXP (x, 0)), + rtx seq = split_insns (gen_rtx_SET (VOIDmode, reg, XEXP (x, 0)), subst_insn); /* This should have produced two insns, each of which sets our @@ -2531,6 +2719,11 @@ find_split_point (loc, insn) if (split && split != &SET_SRC (x)) return split; + /* See if we can split SET_DEST as it stands. */ + split = find_split_point (&SET_DEST (x), insn); + if (split && split != &SET_DEST (x)) + return split; + /* See if this is a bitfield assignment with everything constant. If so, this is an IOR of an AND, so split it into that. */ if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT @@ -2597,16 +2790,50 @@ find_split_point (loc, insn) && XEXP (*split, 0) == SET_DEST (x) && XEXP (*split, 1) == const0_rtx) { + rtx extraction = make_extraction (GET_MODE (SET_DEST (x)), + XEXP (SET_SRC (x), 0), + pos, NULL_RTX, 1, 1, 0, 0); + if (extraction != 0) + { + SUBST (SET_SRC (x), extraction); + return find_split_point (loc, insn); + } + } + break; + + case NE: + /* if STORE_FLAG_VALUE is -1, this is (NE X 0) and only one bit of X + is known to be on, this can be converted into a NEG of a shift. */ + if (STORE_FLAG_VALUE == -1 && XEXP (SET_SRC (x), 1) == const0_rtx + && GET_MODE (SET_SRC (x)) == GET_MODE (XEXP (SET_SRC (x), 0)) + && 1 <= (pos = exact_log2 + (nonzero_bits (XEXP (SET_SRC (x), 0), + GET_MODE (XEXP (SET_SRC (x), 0)))))) + { + enum machine_mode mode = GET_MODE (XEXP (SET_SRC (x), 0)); + SUBST (SET_SRC (x), - make_extraction (GET_MODE (SET_DEST (x)), - XEXP (SET_SRC (x), 0), - pos, NULL_RTX, 1, 1, 0, 0)); - return find_split_point (loc, insn); + gen_rtx_combine (NEG, mode, + gen_rtx_combine (LSHIFTRT, mode, + XEXP (SET_SRC (x), 0), + GEN_INT (pos)))); + + split = find_split_point (&SET_SRC (x), insn); + if (split && split != &SET_SRC (x)) + return split; } break; case SIGN_EXTEND: inner = XEXP (SET_SRC (x), 0); + + /* We can't optimize if either mode is a partial integer + mode as we don't know how many bits are significant + in those modes. */ + if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_PARTIAL_INT + || GET_MODE_CLASS (GET_MODE (SET_SRC (x))) == MODE_PARTIAL_INT) + break; + pos = 0; len = GET_MODE_BITSIZE (GET_MODE (inner)); unsignedp = 0; @@ -2626,6 +2853,9 @@ find_split_point (loc, insn) unsignedp = (code == ZERO_EXTRACT); } break; + + default: + break; } if (len && pos >= 0 && pos + len <= GET_MODE_BITSIZE (GET_MODE (inner))) @@ -2722,6 +2952,9 @@ find_split_point (loc, insn) SUBST (XEXP (x, 1), tem); } break; + + default: + break; } /* Otherwise, select our actions depending on our rtx class. */ @@ -2732,14 +2965,14 @@ find_split_point (loc, insn) split = find_split_point (&XEXP (x, 2), insn); if (split) return split; - /* ... fall through ... */ + /* ... fall through ... */ case '2': case 'c': case '<': split = find_split_point (&XEXP (x, 1), insn); if (split) return split; - /* ... fall through ... */ + /* ... fall through ... */ case '1': /* Some machines have (and (shift ...) ...) insns. If X is not an AND, but XEXP (X, 0) is, use it as our split point. */ @@ -2811,7 +3044,7 @@ subst (x, from, to, in_dest, unique_copy) So force this insn not to match in this (rare) case. */ if (! in_dest && code == REG && GET_CODE (from) == REG && REGNO (x) == REGNO (from)) - return gen_rtx (CLOBBER, GET_MODE (x), const0_rtx); + return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); /* If this is an object, we are done unless it is a MEM or LO_SUM, both of which may contain things that can be combined. */ @@ -2827,102 +3060,154 @@ subst (x, from, to, in_dest, unique_copy) if (COMBINE_RTX_EQUAL_P (x, to)) return to; - len = GET_RTX_LENGTH (code); - fmt = GET_RTX_FORMAT (code); - - /* We don't need to process a SET_DEST that is a register, CC0, or PC, so - set up to skip this common case. All other cases where we want to - suppress replacing something inside a SET_SRC are handled via the - IN_DEST operand. */ - if (code == SET - && (GET_CODE (SET_DEST (x)) == REG - || GET_CODE (SET_DEST (x)) == CC0 - || GET_CODE (SET_DEST (x)) == PC)) - fmt = "ie"; + /* Parallel asm_operands need special attention because all of the + inputs are shared across the arms. Furthermore, unsharing the + rtl results in recognition failures. Failure to handle this case + specially can result in circular rtl. - /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a constant. */ - if (fmt[0] == 'e') - op0_mode = GET_MODE (XEXP (x, 0)); + Solve this by doing a normal pass across the first entry of the + parallel, and only processing the SET_DESTs of the subsequent + entries. Ug. */ - for (i = 0; i < len; i++) + if (code == PARALLEL + && GET_CODE (XVECEXP (x, 0, 0)) == SET + && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS) { - if (fmt[i] == 'E') + new = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy); + + /* If this substitution failed, this whole thing fails. */ + if (GET_CODE (new) == CLOBBER + && XEXP (new, 0) == const0_rtx) + return new; + + SUBST (XVECEXP (x, 0, 0), new); + + for (i = XVECLEN (x, 0) - 1; i >= 1; i--) { - register int j; - for (j = XVECLEN (x, i) - 1; j >= 0; j--) + rtx dest = SET_DEST (XVECEXP (x, 0, i)); + + if (GET_CODE (dest) != REG + && GET_CODE (dest) != CC0 + && GET_CODE (dest) != PC) { - if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from)) - { - new = (unique_copy && n_occurrences ? copy_rtx (to) : to); - n_occurrences++; - } - else - { - new = subst (XVECEXP (x, i, j), from, to, 0, unique_copy); + new = subst (dest, from, to, 0, unique_copy); - /* If this substitution failed, this whole thing fails. */ - if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx) - return new; - } + /* If this substitution failed, this whole thing fails. */ + if (GET_CODE (new) == CLOBBER + && XEXP (new, 0) == const0_rtx) + return new; - SUBST (XVECEXP (x, i, j), new); + SUBST (SET_DEST (XVECEXP (x, 0, i)), new); } } - else if (fmt[i] == 'e') + } + else + { + len = GET_RTX_LENGTH (code); + fmt = GET_RTX_FORMAT (code); + + /* We don't need to process a SET_DEST that is a register, CC0, + or PC, so set up to skip this common case. All other cases + where we want to suppress replacing something inside a + SET_SRC are handled via the IN_DEST operand. */ + if (code == SET + && (GET_CODE (SET_DEST (x)) == REG + || GET_CODE (SET_DEST (x)) == CC0 + || GET_CODE (SET_DEST (x)) == PC)) + fmt = "ie"; + + /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a + constant. */ + if (fmt[0] == 'e') + op0_mode = GET_MODE (XEXP (x, 0)); + + for (i = 0; i < len; i++) { - if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from)) + if (fmt[i] == 'E') + { + register int j; + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + { + if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from)) + { + new = (unique_copy && n_occurrences + ? copy_rtx (to) : to); + n_occurrences++; + } + else + { + new = subst (XVECEXP (x, i, j), from, to, 0, + unique_copy); + + /* If this substitution failed, this whole thing + fails. */ + if (GET_CODE (new) == CLOBBER + && XEXP (new, 0) == const0_rtx) + return new; + } + + SUBST (XVECEXP (x, i, j), new); + } + } + else if (fmt[i] == 'e') { - /* In general, don't install a subreg involving two modes not - tieable. It can worsen register allocation, and can even - make invalid reload insns, since the reg inside may need to - be copied from in the outside mode, and that may be invalid - if it is an fp reg copied in integer mode. - - We allow two exceptions to this: It is valid if it is inside - another SUBREG and the mode of that SUBREG and the mode of - the inside of TO is tieable and it is valid if X is a SET - that copies FROM to CC0. */ - if (GET_CODE (to) == SUBREG - && ! MODES_TIEABLE_P (GET_MODE (to), - GET_MODE (SUBREG_REG (to))) - && ! (code == SUBREG - && MODES_TIEABLE_P (GET_MODE (x), - GET_MODE (SUBREG_REG (to)))) + if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from)) + { + /* In general, don't install a subreg involving two + modes not tieable. It can worsen register + allocation, and can even make invalid reload + insns, since the reg inside may need to be copied + from in the outside mode, and that may be invalid + if it is an fp reg copied in integer mode. + + We allow two exceptions to this: It is valid if + it is inside another SUBREG and the mode of that + SUBREG and the mode of the inside of TO is + tieable and it is valid if X is a SET that copies + FROM to CC0. */ + + if (GET_CODE (to) == SUBREG + && ! MODES_TIEABLE_P (GET_MODE (to), + GET_MODE (SUBREG_REG (to))) + && ! (code == SUBREG + && MODES_TIEABLE_P (GET_MODE (x), + GET_MODE (SUBREG_REG (to)))) #ifdef HAVE_cc0 - && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx) + && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx) #endif - ) - return gen_rtx (CLOBBER, VOIDmode, const0_rtx); + ) + return gen_rtx_CLOBBER (VOIDmode, const0_rtx); - new = (unique_copy && n_occurrences ? copy_rtx (to) : to); - n_occurrences++; + new = (unique_copy && n_occurrences ? copy_rtx (to) : to); + n_occurrences++; + } + else + /* If we are in a SET_DEST, suppress most cases unless we + have gone inside a MEM, in which case we want to + simplify the address. We assume here that things that + are actually part of the destination have their inner + parts in the first expression. This is true for SUBREG, + STRICT_LOW_PART, and ZERO_EXTRACT, which are the only + things aside from REG and MEM that should appear in a + SET_DEST. */ + new = subst (XEXP (x, i), from, to, + (((in_dest + && (code == SUBREG || code == STRICT_LOW_PART + || code == ZERO_EXTRACT)) + || code == SET) + && i == 0), unique_copy); + + /* If we found that we will have to reject this combination, + indicate that by returning the CLOBBER ourselves, rather than + an expression containing it. This will speed things up as + well as prevent accidents where two CLOBBERs are considered + to be equal, thus producing an incorrect simplification. */ + + if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx) + return new; + + SUBST (XEXP (x, i), new); } - else - /* If we are in a SET_DEST, suppress most cases unless we - have gone inside a MEM, in which case we want to - simplify the address. We assume here that things that - are actually part of the destination have their inner - parts in the first expression. This is true for SUBREG, - STRICT_LOW_PART, and ZERO_EXTRACT, which are the only - things aside from REG and MEM that should appear in a - SET_DEST. */ - new = subst (XEXP (x, i), from, to, - (((in_dest - && (code == SUBREG || code == STRICT_LOW_PART - || code == ZERO_EXTRACT)) - || code == SET) - && i == 0), unique_copy); - - /* If we found that we will have to reject this combination, - indicate that by returning the CLOBBER ourselves, rather than - an expression containing it. This will speed things up as - well as prevent accidents where two CLOBBERs are considered - to be equal, thus producing an incorrect simplification. */ - - if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx) - return new; - - SUBST (XEXP (x, i), new); } } @@ -3052,7 +3337,12 @@ simplify_rtx (x, op0_mode, last, in_dest) rtx cond, true, false; cond = if_then_else_cond (x, &true, &false); - if (cond != 0) + if (cond != 0 + /* If everything is a comparison, what we have is highly unlikely + to be simpler, so don't use it. */ + && ! (GET_RTX_CLASS (code) == '<' + && (GET_RTX_CLASS (GET_CODE (true)) == '<' + || GET_RTX_CLASS (GET_CODE (false)) == '<'))) { rtx cop1 = const0_rtx; enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1); @@ -3089,9 +3379,10 @@ simplify_rtx (x, op0_mode, last, in_dest) gen_binary (reverse_condition (cond_code), mode, cond, cop1)); else - return gen_rtx (IF_THEN_ELSE, mode, - gen_binary (cond_code, VOIDmode, cond, cop1), - true, false); + return gen_rtx_IF_THEN_ELSE (mode, + gen_binary (cond_code, VOIDmode, + cond, cop1), + true, false); code = GET_CODE (x); op0_mode = VOIDmode; @@ -3207,7 +3498,7 @@ simplify_rtx (x, op0_mode, last, in_dest) if that would change the meaning of the address. */ if (MEM_VOLATILE_P (SUBREG_REG (x)) || mode_dependent_address_p (XEXP (inner, 0))) - return gen_rtx (CLOBBER, mode, const0_rtx); + return gen_rtx_CLOBBER (mode, const0_rtx); if (BYTES_BIG_ENDIAN) { @@ -3219,10 +3510,10 @@ simplify_rtx (x, op0_mode, last, in_dest) } /* Note if the plus_constant doesn't make a valid address then this combination won't be accepted. */ - x = gen_rtx (MEM, mode, - plus_constant (XEXP (inner, 0), - (SUBREG_WORD (x) * UNITS_PER_WORD - + endian_offset))); + x = gen_rtx_MEM (mode, + 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); @@ -3264,10 +3555,10 @@ simplify_rtx (x, op0_mode, last, in_dest) { if (HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (x)) + SUBREG_WORD (x), mode)) - return gen_rtx (REG, mode, - REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)); + return gen_rtx_REG (mode, + REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)); else - return gen_rtx (CLOBBER, mode, const0_rtx); + return gen_rtx_CLOBBER (mode, const0_rtx); } /* For a constant, try to pick up the part we want. Handle a full @@ -3277,7 +3568,7 @@ simplify_rtx (x, op0_mode, last, in_dest) if (CONSTANT_P (SUBREG_REG (x)) && op0_mode != VOIDmode && GET_MODE_SIZE (mode) == UNITS_PER_WORD - && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD + && GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD && GET_MODE_CLASS (mode) == MODE_INT) { temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x), @@ -3289,9 +3580,17 @@ simplify_rtx (x, op0_mode, last, in_dest) /* If we want a subreg of a constant, at offset 0, take the low bits. On a little-endian machine, that's always valid. On a big-endian machine, it's valid - only if the constant's mode fits in one word. */ - if (CONSTANT_P (SUBREG_REG (x)) && subreg_lowpart_p (x) - && GET_MODE_SIZE (mode) < GET_MODE_SIZE (op0_mode) + only if the constant's mode fits in one word. Note that we + cannot use subreg_lowpart_p since SUBREG_REG may be VOIDmode. */ + if (CONSTANT_P (SUBREG_REG (x)) + && ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD + || ! WORDS_BIG_ENDIAN) + ? SUBREG_WORD (x) == 0 + : (SUBREG_WORD (x) + == ((GET_MODE_SIZE (op0_mode) + - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)) + / UNITS_PER_WORD))) + && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode) && (! WORDS_BIG_ENDIAN || GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD)) return gen_lowpart_for_combine (mode, SUBREG_REG (x)); @@ -3333,8 +3632,8 @@ simplify_rtx (x, op0_mode, last, in_dest) but this doesn't seem common enough to bother with. */ if (GET_CODE (XEXP (x, 0)) == ASHIFT && XEXP (XEXP (x, 0), 0) == const1_rtx) - return gen_rtx (ROTATE, mode, gen_unary (NOT, mode, mode, const1_rtx), - XEXP (XEXP (x, 0), 1)); + return gen_rtx_ROTATE (mode, gen_unary (NOT, mode, mode, const1_rtx), + XEXP (XEXP (x, 0), 1)); if (GET_CODE (XEXP (x, 0)) == SUBREG && subreg_lowpart_p (XEXP (x, 0)) @@ -3345,31 +3644,32 @@ simplify_rtx (x, op0_mode, last, in_dest) { enum machine_mode inner_mode = GET_MODE (SUBREG_REG (XEXP (x, 0))); - x = gen_rtx (ROTATE, inner_mode, - gen_unary (NOT, inner_mode, inner_mode, const1_rtx), - XEXP (SUBREG_REG (XEXP (x, 0)), 1)); + x = gen_rtx_ROTATE (inner_mode, + gen_unary (NOT, inner_mode, inner_mode, + const1_rtx), + XEXP (SUBREG_REG (XEXP (x, 0)), 1)); return gen_lowpart_for_combine (mode, x); } -#if STORE_FLAG_VALUE == -1 - /* (not (comparison foo bar)) can be done by reversing the comparison - code if valid. */ - if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' + /* If STORE_FLAG_VALUE is -1, (not (comparison foo bar)) can be done by + reversing the comparison code if valid. */ + if (STORE_FLAG_VALUE == -1 + && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' && reversible_comparison_p (XEXP (x, 0))) return gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))), mode, XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 1)); /* (ashiftrt foo C) where C is the number of bits in FOO minus 1 - is (lt foo (const_int 0)), so we can perform the above - simplification. */ + is (lt foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can + perform the above simplification. */ - if (XEXP (x, 1) == const1_rtx + if (STORE_FLAG_VALUE == -1 + && XEXP (x, 1) == const1_rtx && GET_CODE (XEXP (x, 0)) == ASHIFTRT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode) - 1) return gen_rtx_combine (GE, mode, XEXP (XEXP (x, 0), 0), const0_rtx); -#endif /* Apply De Morgan's laws to reduce number of patterns for machines with negating logical insns (and-not, nand, etc.). If result has @@ -3417,13 +3717,13 @@ simplify_rtx (x, op0_mode, last, in_dest) /* (neg (minus X Y)) can become (minus Y X). */ if (GET_CODE (XEXP (x, 0)) == MINUS && (! FLOAT_MODE_P (mode) - /* x-y != -(y-x) with IEEE floating point. */ + /* x-y != -(y-x) with IEEE floating point. */ || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math)) return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1), XEXP (XEXP (x, 0), 0)); - /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ + /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ if (GET_CODE (XEXP (x, 0)) == XOR && XEXP (XEXP (x, 0), 1) == const1_rtx && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1) return gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx); @@ -3484,10 +3784,66 @@ simplify_rtx (x, op0_mode, last, in_dest) break; case TRUNCATE: - if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + /* We can't handle truncation to a partial integer mode here + because we don't know the real bitsize of the partial + integer mode. */ + if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) + break; + + if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT + && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), + GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))) SUBST (XEXP (x, 0), force_to_mode (XEXP (x, 0), GET_MODE (XEXP (x, 0)), GET_MODE_MASK (mode), NULL_RTX, 0)); + + /* (truncate:SI ({sign,zero}_extend:DI foo:SI)) == foo:SI. */ + if ((GET_CODE (XEXP (x, 0)) == SIGN_EXTEND + || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND) + && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode) + return XEXP (XEXP (x, 0), 0); + + /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is + (OP:SI foo:SI) if OP is NEG or ABS. */ + if ((GET_CODE (XEXP (x, 0)) == ABS + || GET_CODE (XEXP (x, 0)) == NEG) + && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND + || GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND) + && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode) + return gen_unary (GET_CODE (XEXP (x, 0)), mode, mode, + XEXP (XEXP (XEXP (x, 0), 0), 0)); + + /* (truncate:SI (subreg:DI (truncate:SI X) 0)) is + (truncate:SI x). */ + if (GET_CODE (XEXP (x, 0)) == SUBREG + && GET_CODE (SUBREG_REG (XEXP (x, 0))) == TRUNCATE + && subreg_lowpart_p (XEXP (x, 0))) + 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) + return gen_lowpart_for_combine (mode, XEXP (x, 0)); + + /* A truncate of a comparison can be replaced with a subreg if + STORE_FLAG_VALUE permits. This is like the previous test, + but it works even if the comparison is done in a mode larger + than HOST_BITS_PER_WIDE_INT. */ + if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT + && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' + && ((HOST_WIDE_INT) STORE_FLAG_VALUE &~ GET_MODE_MASK (mode)) == 0) + return gen_lowpart_for_combine (mode, XEXP (x, 0)); + + /* Similarly, a truncate of a register whose value is a + comparison can be replaced with a subreg if STORE_FLAG_VALUE + permits. */ + if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT + && ((HOST_WIDE_INT) STORE_FLAG_VALUE &~ GET_MODE_MASK (mode)) == 0 + && (temp = get_last_value (XEXP (x, 0))) + && GET_RTX_CLASS (GET_CODE (temp)) == '<') + return gen_lowpart_for_combine (mode, XEXP (x, 0)); + break; case FLOAT_TRUNCATE: @@ -3627,16 +3983,15 @@ simplify_rtx (x, op0_mode, last, in_dest) break; case MINUS: -#if STORE_FLAG_VALUE == 1 - /* (minus 1 (comparison foo bar)) can be done by reversing the comparison - code if valid. */ - if (XEXP (x, 0) == const1_rtx + /* If STORE_FLAG_VALUE is 1, (minus 1 (comparison foo bar)) can be done + by reversing the comparison code if valid. */ + if (STORE_FLAG_VALUE == 1 + && XEXP (x, 0) == const1_rtx && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<' && reversible_comparison_p (XEXP (x, 1))) return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))), mode, XEXP (XEXP (x, 1), 0), XEXP (XEXP (x, 1), 1)); -#endif /* (minus (and (const_int -pow2))) becomes (and (const_int pow2-1)) */ @@ -3710,7 +4065,6 @@ simplify_rtx (x, op0_mode, last, in_dest) /* Simplify our comparison, if possible. */ new_code = simplify_comparison (code, &op0, &op1); -#if STORE_FLAG_VALUE == 1 /* If STORE_FLAG_VALUE is 1, we can convert (ne x 0) to simply X if only the low-order bit is possibly nonzero in X (such as when X is a ZERO_EXTRACT of one bit). Similarly, we can convert EQ to @@ -3723,13 +4077,14 @@ simplify_rtx (x, op0_mode, last, in_dest) ZERO_EXTRACT is indeed appropriate, it will be placed back by the call to make_compound_operation in the SET case. */ - if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT - && op1 == const0_rtx - && nonzero_bits (op0, mode) == 1) + if (STORE_FLAG_VALUE == 1 + && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT + && op1 == const0_rtx && nonzero_bits (op0, mode) == 1) return gen_lowpart_for_combine (mode, expand_compound_operation (op0)); - else if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT + else if (STORE_FLAG_VALUE == 1 + && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && (num_sign_bit_copies (op0, mode) == GET_MODE_BITSIZE (mode))) @@ -3739,7 +4094,8 @@ simplify_rtx (x, op0_mode, last, in_dest) gen_lowpart_for_combine (mode, op0)); } - else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT + else if (STORE_FLAG_VALUE == 1 + && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && nonzero_bits (op0, mode) == 1) { @@ -3749,7 +4105,8 @@ simplify_rtx (x, op0_mode, last, in_dest) const1_rtx); } - else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT + else if (STORE_FLAG_VALUE == 1 + && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && (num_sign_bit_copies (op0, mode) == GET_MODE_BITSIZE (mode))) @@ -3757,19 +4114,19 @@ simplify_rtx (x, op0_mode, last, in_dest) op0 = expand_compound_operation (op0); return plus_constant (gen_lowpart_for_combine (mode, op0), 1); } -#endif -#if STORE_FLAG_VALUE == -1 /* If STORE_FLAG_VALUE is -1, we have cases similar to those above. */ - if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT + if (STORE_FLAG_VALUE == -1 + && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && (num_sign_bit_copies (op0, mode) == GET_MODE_BITSIZE (mode))) return gen_lowpart_for_combine (mode, expand_compound_operation (op0)); - else if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT + else if (STORE_FLAG_VALUE == -1 + && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && nonzero_bits (op0, mode) == 1) { @@ -3778,7 +4135,8 @@ simplify_rtx (x, op0_mode, last, in_dest) gen_lowpart_for_combine (mode, op0)); } - else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT + else if (STORE_FLAG_VALUE == -1 + && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && (num_sign_bit_copies (op0, mode) == GET_MODE_BITSIZE (mode))) @@ -3789,14 +4147,14 @@ simplify_rtx (x, op0_mode, last, in_dest) } /* If X is 0/1, (eq X 0) is X-1. */ - else if (new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT + else if (STORE_FLAG_VALUE == -1 + && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && nonzero_bits (op0, mode) == 1) { op0 = expand_compound_operation (op0); return plus_constant (gen_lowpart_for_combine (mode, op0), -1); } -#endif /* If STORE_FLAG_VALUE says to just test the sign bit and X has just one bit that might be nonzero, we can convert (ne x 0) to @@ -3805,7 +4163,7 @@ simplify_rtx (x, op0_mode, last, in_dest) going to test the sign bit. */ if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT - && (STORE_FLAG_VALUE + && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode)) == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) && op1 == const0_rtx && mode == GET_MODE (op0) @@ -3838,7 +4196,7 @@ simplify_rtx (x, op0_mode, last, in_dest) case SIGN_EXTRACT: case ZERO_EXTEND: case SIGN_EXTEND: - /* If we are processing SET_DEST, we are done. */ + /* If we are processing SET_DEST, we are done. */ if (in_dest) return x; @@ -3852,11 +4210,16 @@ simplify_rtx (x, op0_mode, last, in_dest) case XOR: return simplify_logical (x, last); - case ABS: + case ABS: /* (abs (neg )) -> (abs ) */ if (GET_CODE (XEXP (x, 0)) == NEG) SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0)); + /* If the mode of the operand is VOIDmode (i.e. if it is ASM_OPERANDS), + do nothing. */ + if (GET_MODE (XEXP (x, 0)) == VOIDmode) + break; + /* If operand is something known to be positive, ignore the ABS. */ if (GET_CODE (XEXP (x, 0)) == FFS || GET_CODE (XEXP (x, 0)) == ABS || ((GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) @@ -3908,6 +4271,9 @@ simplify_rtx (x, op0_mode, last, in_dest) #endif break; + + default: + break; } return x; @@ -3928,11 +4294,11 @@ simplify_if_then_else (x) rtx temp; int i; - /* Simplify storing of the truth value. */ + /* Simplify storing of the truth value. */ if (comparison_p && true == const_true_rtx && false == const0_rtx) return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1)); - /* Also when the truth value has to be reversed. */ + /* Also when the truth value has to be reversed. */ if (comparison_p && reversible_comparison_p (cond) && true == const0_rtx && false == const_true_rtx) return gen_binary (reverse_condition (true_code), @@ -4018,6 +4384,10 @@ simplify_if_then_else (x) SUBST (XEXP (x, 2), true); temp = true, true = false, false = temp, cond = XEXP (x, 0); + + /* It is possible that the conditional has been simplified out. */ + true_code = GET_CODE (cond); + comparison_p = GET_RTX_CLASS (true_code) == '<'; } /* If the two arms are identical, we don't need the comparison. */ @@ -4025,6 +4395,16 @@ simplify_if_then_else (x) if (rtx_equal_p (true, false) && ! side_effects_p (cond)) return true; + /* Convert a == b ? b : a to "a". */ + if (true_code == EQ && ! side_effects_p (cond) + && rtx_equal_p (XEXP (cond, 0), false) + && rtx_equal_p (XEXP (cond, 1), true)) + return false; + else if (true_code == NE && ! side_effects_p (cond) + && rtx_equal_p (XEXP (cond, 0), true) + && rtx_equal_p (XEXP (cond, 1), false)) + return true; + /* Look for cases where we have (abs x) or (neg (abs X)). */ if (GET_MODE_CLASS (mode) == MODE_INT @@ -4041,6 +4421,8 @@ simplify_if_then_else (x) case LT: case LE: return gen_unary (NEG, mode, mode, gen_unary (ABS, mode, mode, true)); + default: + break; } /* Look for MIN or MAX. */ @@ -4064,18 +4446,19 @@ simplify_if_then_else (x) case LEU: case LTU: return gen_binary (UMIN, mode, true, false); + default: + break; } -#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1 - /* If we have (if_then_else COND (OP Z C1) Z) and OP is an identity when its second operand is zero, this can be done as (OP Z (mult COND C2)) where C2 = C1 * STORE_FLAG_VALUE. Similarly if OP has an outer ZERO_EXTEND or SIGN_EXTEND as long as Z is already extended (so we don't destroy it). We can do this kind of thing in some cases when STORE_FLAG_VALUE is - neither of the above, but it isn't worth checking for. */ + neither 1 or -1, but it isn't worth checking for. */ - if (comparison_p && mode != VOIDmode && ! side_effects_p (x)) + if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) + && comparison_p && mode != VOIDmode && ! side_effects_p (x)) { rtx t = make_compound_operation (true, SET); rtx f = make_compound_operation (false, SET); @@ -4093,7 +4476,7 @@ simplify_if_then_else (x) c1 = XEXP (t, 1), op = GET_CODE (t), z = f; /* If an identity-zero op is commutative, check whether there - would be a match if we swapped the operands. */ + would be a match if we swapped the operands. */ else if ((GET_CODE (t) == PLUS || GET_CODE (t) == IOR || GET_CODE (t) == XOR) && rtx_equal_p (XEXP (t, 1), f)) @@ -4184,7 +4567,6 @@ simplify_if_then_else (x) return temp; } } -#endif /* If we have (if_then_else (ne A 0) C1 0) and either A is known to be 0 or 1 and C1 is a single bit or A is known to be 0 or -1 and C1 is the @@ -4271,10 +4653,10 @@ simplify_set (x) if (compare_mode != GET_MODE (dest)) { int regno = REGNO (dest); - rtx new_dest = gen_rtx (REG, compare_mode, regno); + rtx new_dest = gen_rtx_REG (compare_mode, regno); if (regno < FIRST_PSEUDO_REGISTER - || (reg_n_sets[regno] == 1 && ! REG_USERVAR_P (dest))) + || (REG_N_SETS (regno) == 1 && ! REG_USERVAR_P (dest))) { if (regno >= FIRST_PSEUDO_REGISTER) SUBST (regno_reg_rtx[regno], new_dest); @@ -4370,7 +4752,7 @@ simplify_set (x) we only care about the low bits of the result. However, on machines without WORD_REGISTER_OPERATIONS defined, we cannot - perform a narrower operation that requested since the high-order bits will + perform a narrower operation than requested since the high-order bits will be undefined. On machine where it is defined, this transformation is safe as long as M1 and M2 have the same number of words. */ @@ -4407,7 +4789,7 @@ simplify_set (x) #ifdef LOAD_EXTEND_OP /* If we have (set FOO (subreg:M (mem:N BAR) 0)) with M wider than N, this would require a paradoxical subreg. Replace the subreg with a - zero_extend to avoid the reload that would otherwise be required. */ + zero_extend to avoid the reload that would otherwise be required. */ if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src) && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != NIL @@ -4535,7 +4917,7 @@ simplify_logical (x, last) /* If we have (ior (and (X C1) C2)) and the next restart would be the last, simplify this by making C1 as small as possible - and then exit. */ + and then exit. */ if (last && GET_CODE (x) == IOR && GET_CODE (op0) == AND && GET_CODE (XEXP (op0, 1)) == CONST_INT @@ -4658,9 +5040,9 @@ simplify_logical (x, last) && GET_CODE (XEXP (op1, 1)) == CONST_INT && (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1)) == GET_MODE_BITSIZE (mode))) - return gen_rtx (ROTATE, mode, XEXP (op0, 0), - (GET_CODE (op0) == ASHIFT - ? XEXP (op0, 1) : XEXP (op1, 1))); + return gen_rtx_ROTATE (mode, XEXP (op0, 0), + (GET_CODE (op0) == ASHIFT + ? XEXP (op0, 1) : XEXP (op1, 1))); /* If OP0 is (ashiftrt (plus ...) C), it might actually be a (sign_extend (plus ...)). If so, OP1 is a CONST_INT, and the PLUS @@ -4725,10 +5107,10 @@ simplify_logical (x, last) gen_unary (NOT, mode, mode, XEXP (op0, 1)), op1); -#if STORE_FLAG_VALUE == 1 /* (xor (comparison foo bar) (const_int 1)) can become the reversed - comparison. */ - if (op1 == const1_rtx + comparison if STORE_FLAG_VALUE is 1. */ + if (STORE_FLAG_VALUE == 1 + && op1 == const1_rtx && GET_RTX_CLASS (GET_CODE (op0)) == '<' && reversible_comparison_p (op0)) return gen_rtx_combine (reverse_condition (GET_CODE (op0)), @@ -4736,19 +5118,19 @@ simplify_logical (x, last) /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 is (lt foo (const_int 0)), so we can perform the above - simplification. */ + simplification if STORE_FLAG_VALUE is 1. */ - if (op1 == const1_rtx + if (STORE_FLAG_VALUE == 1 + && op1 == const1_rtx && GET_CODE (op0) == LSHIFTRT && GET_CODE (XEXP (op0, 1)) == CONST_INT && INTVAL (XEXP (op0, 1)) == GET_MODE_BITSIZE (mode) - 1) return gen_rtx_combine (GE, mode, XEXP (op0, 0), const0_rtx); -#endif /* (xor (comparison foo bar) (const_int sign-bit)) when STORE_FLAG_VALUE is the sign bit. */ if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT - && (STORE_FLAG_VALUE + && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode)) == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) && op1 == const_true_rtx && GET_RTX_CLASS (GET_CODE (op0)) == '<' @@ -4756,6 +5138,9 @@ simplify_logical (x, last) return gen_rtx_combine (reverse_condition (GET_CODE (op0)), mode, XEXP (op0, 0), XEXP (op0, 1)); break; + + default: + abort (); } return x; @@ -4839,7 +5224,7 @@ expand_compound_operation (x) with a (use (mem ...)) construct that only combine understands and is used only for this purpose. */ if (len + pos > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))) - SUBST (XEXP (x, 0), gen_rtx (USE, GET_MODE (x), XEXP (x, 0))); + SUBST (XEXP (x, 0), gen_rtx_USE (GET_MODE (x), XEXP (x, 0))); if (BITS_BIG_ENDIAN) pos = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - len - pos; @@ -4850,6 +5235,78 @@ expand_compound_operation (x) return x; } + /* We can optimize some special cases of ZERO_EXTEND. */ + if (GET_CODE (x) == ZERO_EXTEND) + { + /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI if we + know that the last value didn't have any inappropriate bits + set. */ + if (GET_CODE (XEXP (x, 0)) == TRUNCATE + && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x) + && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT + && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x)) + & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0) + return XEXP (XEXP (x, 0), 0); + + /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */ + if (GET_CODE (XEXP (x, 0)) == SUBREG + && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x) + && subreg_lowpart_p (XEXP (x, 0)) + && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT + && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x)) + & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0) + return SUBREG_REG (XEXP (x, 0)); + + /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI when foo + is a comparison and STORE_FLAG_VALUE permits. This is like + the first case, but it works even when GET_MODE (x) is larger + than HOST_WIDE_INT. */ + if (GET_CODE (XEXP (x, 0)) == TRUNCATE + && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x) + && GET_RTX_CLASS (GET_CODE (XEXP (XEXP (x, 0), 0))) == '<' + && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) + <= HOST_BITS_PER_WIDE_INT) + && ((HOST_WIDE_INT) STORE_FLAG_VALUE + & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0) + return XEXP (XEXP (x, 0), 0); + + /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */ + if (GET_CODE (XEXP (x, 0)) == SUBREG + && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x) + && subreg_lowpart_p (XEXP (x, 0)) + && GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0)))) == '<' + && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) + <= HOST_BITS_PER_WIDE_INT) + && ((HOST_WIDE_INT) STORE_FLAG_VALUE + & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0) + return SUBREG_REG (XEXP (x, 0)); + + /* If sign extension is cheaper than zero extension, then use it + if we know that no extraneous bits are set, and that the high + bit is not set. */ + if (flag_expensive_optimizations + && ((GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT + && ((nonzero_bits (XEXP (x, 0), GET_MODE (x)) + & ~ (((unsigned HOST_WIDE_INT) + GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) + >> 1)) + == 0)) + || (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' + && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) + <= HOST_BITS_PER_WIDE_INT) + && (((HOST_WIDE_INT) STORE_FLAG_VALUE + & ~ (((unsigned HOST_WIDE_INT) + GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) + >> 1)) + == 0)))) + { + rtx temp = gen_rtx_SIGN_EXTEND (GET_MODE (x), XEXP (x, 0)); + + if (rtx_cost (temp, SET) < rtx_cost (x, SET)) + return expand_compound_operation (temp); + } + } + /* If we reach here, we want to return a pair of shifts. The inner shift is a left shift of BITSIZE - POS - LEN bits. The outer shift is a right shift of BITSIZE - LEN bits. It is arithmetic or @@ -4907,7 +5364,7 @@ expand_field_assignment (x) rtx x; { rtx inner; - rtx pos; /* Always counts from low bit. */ + rtx pos; /* Always counts from low bit. */ int len; rtx mask; enum machine_mode compute_mode; @@ -4920,7 +5377,7 @@ expand_field_assignment (x) { inner = SUBREG_REG (XEXP (SET_DEST (x), 0)); len = GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0))); - pos = const0_rtx; + pos = GEN_INT (BITS_PER_WORD * SUBREG_WORD (XEXP (SET_DEST (x), 0))); } else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT) @@ -4933,7 +5390,7 @@ expand_field_assignment (x) surround INNER with a USE to indicate this. */ if (GET_CODE (pos) == CONST_INT && INTVAL (pos) + len > GET_MODE_BITSIZE (GET_MODE (inner))) - inner = gen_rtx (USE, GET_MODE (SET_DEST (x)), inner); + inner = gen_rtx_USE (GET_MODE (SET_DEST (x)), inner); if (BITS_BIG_ENDIAN) { @@ -4962,9 +5419,9 @@ expand_field_assignment (x) == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x)))) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))) { - x = gen_rtx (SET, VOIDmode, SUBREG_REG (SET_DEST (x)), - gen_lowpart_for_combine (GET_MODE (SUBREG_REG (SET_DEST (x))), - SET_SRC (x))); + x = gen_rtx_SET (VOIDmode, SUBREG_REG (SET_DEST (x)), + gen_lowpart_for_combine (GET_MODE (SUBREG_REG (SET_DEST (x))), + SET_SRC (x))); continue; } else @@ -4984,22 +5441,22 @@ expand_field_assignment (x) /* Now compute the equivalent expression. Make a copy of INNER for the SET_DEST in case it is a MEM into which we will substitute; we don't want shared RTL in that case. */ - x = gen_rtx (SET, VOIDmode, copy_rtx (inner), - gen_binary (IOR, compute_mode, - gen_binary (AND, compute_mode, - gen_unary (NOT, compute_mode, - compute_mode, - gen_binary (ASHIFT, - compute_mode, - mask, pos)), - inner), - gen_binary (ASHIFT, compute_mode, - gen_binary (AND, compute_mode, - gen_lowpart_for_combine - (compute_mode, - SET_SRC (x)), - mask), - pos))); + x = gen_rtx_SET (VOIDmode, copy_rtx (inner), + gen_binary (IOR, compute_mode, + gen_binary (AND, compute_mode, + gen_unary (NOT, compute_mode, + compute_mode, + gen_binary (ASHIFT, + compute_mode, + mask, pos)), + inner), + gen_binary (ASHIFT, compute_mode, + gen_binary (AND, compute_mode, + gen_lowpart_for_combine + (compute_mode, + SET_SRC (x)), + mask), + pos))); } return x; @@ -5027,7 +5484,10 @@ expand_field_assignment (x) IN_COMPARE is non-zero if we are in a COMPARE. This means that a ZERO_EXTRACT should be built even for bits starting at bit 0. - MODE is the desired mode of the result (if IN_DEST == 0). */ + MODE is the desired mode of the result (if IN_DEST == 0). + + The result is an RTX for the extraction or NULL_RTX if the target + can't handle it. */ static rtx make_extraction (mode, inner, pos, pos_rtx, len, @@ -5045,7 +5505,8 @@ make_extraction (mode, inner, pos, pos_rtx, len, ignore the POS lowest bits, etc. */ enum machine_mode is_mode = GET_MODE (inner); enum machine_mode inner_mode; - enum machine_mode wanted_mem_mode = byte_mode; + enum machine_mode wanted_inner_mode = byte_mode; + enum machine_mode wanted_inner_reg_mode = word_mode; enum machine_mode pos_mode = word_mode; enum machine_mode extraction_mode = word_mode; enum machine_mode tmode = mode_for_size (len, MODE_INT, 1); @@ -5092,7 +5553,8 @@ make_extraction (mode, inner, pos, pos_rtx, len, if (tmode != BLKmode && ! (spans_byte && inner_mode != tmode) - && ((pos_rtx == 0 && pos == 0 && GET_CODE (inner) != MEM + && ((pos_rtx == 0 && (pos % BITS_PER_WORD) == 0 + && GET_CODE (inner) != MEM && (! in_dest || (GET_CODE (inner) == REG && (movstrict_optab->handlers[(int) tmode].insn_code @@ -5112,8 +5574,8 @@ make_extraction (mode, inner, pos, pos_rtx, len, field. If the original and current mode are the same, we need not adjust the offset. Otherwise, we do if bytes big endian. - If INNER is not a MEM, get a piece consisting of the just the field - of interest (in this case POS must be 0). */ + If INNER is not a MEM, get a piece consisting of just the field + of interest (in this case POS % BITS_PER_WORD must be 0). */ if (GET_CODE (inner) == MEM) { @@ -5124,7 +5586,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, else offset = pos / BITS_PER_UNIT; - new = gen_rtx (MEM, tmode, plus_constant (XEXP (inner, 0), offset)); + 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); @@ -5134,13 +5596,14 @@ make_extraction (mode, inner, pos, pos_rtx, len, /* We can't call gen_lowpart_for_combine here since we always want a SUBREG and it would sometimes return a new hard register. */ if (tmode != inner_mode) - new = gen_rtx (SUBREG, tmode, inner, - (WORDS_BIG_ENDIAN - && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD - ? ((GET_MODE_SIZE (inner_mode) - - GET_MODE_SIZE (tmode)) - / UNITS_PER_WORD) - : 0)); + new = gen_rtx_SUBREG (tmode, inner, + (WORDS_BIG_ENDIAN + && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD + ? (((GET_MODE_SIZE (inner_mode) + - GET_MODE_SIZE (tmode)) + / UNITS_PER_WORD) + - pos / BITS_PER_WORD) + : pos / BITS_PER_WORD)); else new = inner; } @@ -5157,7 +5620,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, if (in_dest) return (GET_CODE (new) == MEM ? new : (GET_CODE (new) != SUBREG - ? gen_rtx (CLOBBER, tmode, const0_rtx) + ? gen_rtx_CLOBBER (tmode, const0_rtx) : gen_rtx_combine (STRICT_LOW_PART, VOIDmode, new))); /* Otherwise, sign- or zero-extend unless we already are in the @@ -5185,12 +5648,12 @@ make_extraction (mode, inner, pos, pos_rtx, len, || (pos_rtx != 0 && len != 1))) return 0; - /* Get the mode to use should INNER be a MEM, the mode for the position, + /* Get the mode to use should INNER not be a MEM, the mode for the position, and the mode for the result. */ #ifdef HAVE_insv if (in_dest) { - wanted_mem_mode = insn_operand_mode[(int) CODE_FOR_insv][0]; + 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]; } @@ -5199,7 +5662,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, #ifdef HAVE_extzv if (! in_dest && unsignedp) { - wanted_mem_mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; + 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]; } @@ -5208,7 +5671,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, #ifdef HAVE_extv if (! in_dest && ! unsignedp) { - wanted_mem_mode = insn_operand_mode[(int) CODE_FOR_extv][1]; + 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]; } @@ -5224,40 +5687,48 @@ make_extraction (mode, inner, pos, pos_rtx, len, && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx))) pos_mode = GET_MODE (pos_rtx); - /* If this is not from memory or we have to change the mode of memory and - cannot, the desired mode is EXTRACTION_MODE. */ - if (GET_CODE (inner) != MEM - || (inner_mode != wanted_mem_mode - && (mode_dependent_address_p (XEXP (inner, 0)) - || MEM_VOLATILE_P (inner)))) - wanted_mem_mode = extraction_mode; + /* If this is not from memory, the desired mode is wanted_inner_reg_mode; + if we have to change the mode of memory and cannot, the desired mode is + EXTRACTION_MODE. */ + if (GET_CODE (inner) != MEM) + wanted_inner_mode = wanted_inner_reg_mode; + else if (inner_mode != wanted_inner_mode + && (mode_dependent_address_p (XEXP (inner, 0)) + || MEM_VOLATILE_P (inner))) + wanted_inner_mode = extraction_mode; orig_pos = pos; if (BITS_BIG_ENDIAN) { - /* If position is constant, compute new position. Otherwise, - build subtraction. */ + /* POS is passed as if BITS_BIG_ENDIAN == 0, so we need to convert it to + BITS_BIG_ENDIAN style. If position is constant, compute new + position. Otherwise, build subtraction. + Note that POS is relative to the mode of the original argument. + If it's a MEM we need to recompute POS relative to that. + However, if we're extracting from (or inserting into) a register, + we want to recompute POS relative to wanted_inner_mode. */ + int width = (GET_CODE (inner) == MEM + ? GET_MODE_BITSIZE (is_mode) + : GET_MODE_BITSIZE (wanted_inner_mode)); + if (pos_rtx == 0) - pos = (MAX (GET_MODE_BITSIZE (is_mode), - GET_MODE_BITSIZE (wanted_mem_mode)) - - len - pos); + pos = width - len - pos; else pos_rtx = gen_rtx_combine (MINUS, GET_MODE (pos_rtx), - GEN_INT (MAX (GET_MODE_BITSIZE (is_mode), - GET_MODE_BITSIZE (wanted_mem_mode)) - - len), - pos_rtx); + GEN_INT (width - len), pos_rtx); + /* POS may be less than 0 now, but we check for that below. + Note that it can only be less than 0 if GET_CODE (inner) != MEM. */ } /* If INNER has a wider mode, make it smaller. If this is a constant extract, try to adjust the byte to point to the byte containing the value. */ - if (wanted_mem_mode != VOIDmode - && GET_MODE_SIZE (wanted_mem_mode) < GET_MODE_SIZE (is_mode) + if (wanted_inner_mode != VOIDmode + && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode) && ((GET_CODE (inner) == MEM - && (inner_mode == wanted_mem_mode + && (inner_mode == wanted_inner_mode || (! mode_dependent_address_p (XEXP (inner, 0)) && ! MEM_VOLATILE_P (inner)))))) { @@ -5268,7 +5739,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, If it is mixed, we must adjust. */ /* If bytes are big endian and we had a paradoxical SUBREG, we must - adjust OFFSET to compensate. */ + adjust OFFSET to compensate. */ if (BYTES_BIG_ENDIAN && ! spans_byte && GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (is_mode)) @@ -5278,19 +5749,19 @@ make_extraction (mode, inner, pos, pos_rtx, len, if (pos_rtx == 0) { offset += pos / BITS_PER_UNIT; - pos %= GET_MODE_BITSIZE (wanted_mem_mode); + pos %= GET_MODE_BITSIZE (wanted_inner_mode); } if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN && ! spans_byte - && is_mode != wanted_mem_mode) + && is_mode != wanted_inner_mode) offset = (GET_MODE_SIZE (is_mode) - - GET_MODE_SIZE (wanted_mem_mode) - offset); + - GET_MODE_SIZE (wanted_inner_mode) - offset); - if (offset != 0 || inner_mode != wanted_mem_mode) + if (offset != 0 || inner_mode != wanted_inner_mode) { - rtx newmem = gen_rtx (MEM, wanted_mem_mode, - plus_constant (XEXP (inner, 0), offset)); + 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); @@ -5298,13 +5769,23 @@ make_extraction (mode, inner, pos, pos_rtx, len, } } - /* If INNER is not memory, we can always get it into the proper mode. */ + /* If INNER is not memory, we can always get it into the proper mode. If we + are changing its mode, POS must be a constant and smaller than the size + of the new mode. */ else if (GET_CODE (inner) != MEM) - inner = force_to_mode (inner, extraction_mode, - pos_rtx || len + orig_pos >= HOST_BITS_PER_WIDE_INT - ? GET_MODE_MASK (extraction_mode) - : (((HOST_WIDE_INT) 1 << len) - 1) << orig_pos, - NULL_RTX, 0); + { + if (GET_MODE (inner) != wanted_inner_mode + && (pos_rtx != 0 + || orig_pos + len > GET_MODE_BITSIZE (wanted_inner_mode))) + return 0; + + inner = force_to_mode (inner, wanted_inner_mode, + pos_rtx + || len + orig_pos >= HOST_BITS_PER_WIDE_INT + ? GET_MODE_MASK (wanted_inner_mode) + : (((HOST_WIDE_INT) 1 << len) - 1) << orig_pos, + NULL_RTX, 0); + } /* Adjust mode of POS_RTX, if needed. If we want a wider mode, we have to zero extend. Otherwise, we can just use a SUBREG. */ @@ -5317,7 +5798,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, /* Make POS_RTX unless we already have it and it is correct. If we don't have a POS_RTX but we do have an ORIG_POS_RTX, the latter must - be a CONST_INT. */ + be a CONST_INT. */ if (pos_rtx == 0 && orig_pos_rtx != 0 && INTVAL (orig_pos_rtx) == pos) pos_rtx = orig_pos_rtx; @@ -5367,12 +5848,15 @@ extract_left_shift (x, count) /* If we can safely shift this constant and we find the inner shift, make a new operation. */ if (GET_CODE (XEXP (x,1)) == CONST_INT - && (INTVAL (XEXP (x, 1)) & (((HOST_WIDE_INT) 1 << count)) - 1) == 0 + && (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0 && (tem = extract_left_shift (XEXP (x, 0), count)) != 0) return gen_binary (code, mode, tem, GEN_INT (INTVAL (XEXP (x, 1)) >> count)); break; + + default: + break; } return 0; @@ -5476,10 +5960,10 @@ make_compound_operation (x, in_code) { /* Apply the distributive law, and then try to make extractions. */ new = gen_rtx_combine (GET_CODE (XEXP (x, 0)), mode, - gen_rtx (AND, mode, XEXP (XEXP (x, 0), 0), - XEXP (x, 1)), - gen_rtx (AND, mode, XEXP (XEXP (x, 0), 1), - XEXP (x, 1))); + gen_rtx_AND (mode, XEXP (XEXP (x, 0), 0), + XEXP (x, 1)), + gen_rtx_AND (mode, XEXP (XEXP (x, 0), 1), + XEXP (x, 1))); new = make_compound_operation (new, in_code); } @@ -5557,7 +6041,7 @@ make_compound_operation (x, in_code) break; } - /* ... fall through ... */ + /* ... fall through ... */ case ASHIFTRT: lhs = XEXP (x, 0); @@ -5614,6 +6098,27 @@ make_compound_operation (x, in_code) return newer; } + + /* If this is a paradoxical subreg, and the new code is a sign or + zero extension, omit the subreg and widen the extension. If it + is a regular subreg, we can still get rid of the subreg by not + widening so much, or in fact removing the extension entirely. */ + if ((GET_CODE (tem) == SIGN_EXTEND + || GET_CODE (tem) == ZERO_EXTEND) + && subreg_lowpart_p (x)) + { + if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (tem)) + || (GET_MODE_SIZE (mode) > + GET_MODE_SIZE (GET_MODE (XEXP (tem, 0))))) + tem = gen_rtx_combine (GET_CODE (tem), mode, XEXP (tem, 0)); + else + tem = gen_lowpart_for_combine (mode, XEXP (tem, 0)); + return tem; + } + break; + + default: + break; } if (new) @@ -5692,9 +6197,13 @@ force_to_mode (x, mode, mask, reg, just_select) unsigned HOST_WIDE_INT fuller_mask, nonzero; rtx op0, op1, temp; - /* If this is a CALL, don't do anything. Some of the code below - will do the wrong thing since the mode of a CALL is VOIDmode. */ - if (code == CALL) + /* If this is a CALL or ASM_OPERANDS, don't do anything. Some of the + code below will do the wrong thing since the mode of such an + expression is VOIDmode. + + Also do nothing if X is a CLOBBER; this can happen if X was + the return value from a call to gen_lowpart_for_combine. */ + if (code == CALL || code == ASM_OPERANDS || code == CLOBBER) return x; /* We want to perform the operation is its present mode unless we know @@ -5764,7 +6273,7 @@ force_to_mode (x, mode, mask, reg, just_select) { case CLOBBER: /* If X is a (clobber (const_int)), return it since we know we are - generating something that won't match. */ + generating something that won't match. */ return x; case USE: @@ -5870,15 +6379,35 @@ force_to_mode (x, mode, mask, reg, just_select) smask |= (HOST_WIDE_INT) -1 << width; if (GET_CODE (XEXP (x, 1)) == CONST_INT - && exact_log2 (- smask) >= 0 - && (nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0 - && (INTVAL (XEXP (x, 1)) & ~ mask) != 0) - return force_to_mode (plus_constant (XEXP (x, 0), - INTVAL (XEXP (x, 1)) & mask), - mode, mask, reg, next_select); + && exact_log2 (- smask) >= 0) + { +#ifdef STACK_BIAS + if (STACK_BIAS + && (XEXP (x, 0) == stack_pointer_rtx + || XEXP (x, 0) == frame_pointer_rtx)) + { + int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT; + 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) + return force_to_mode (plus_constant (XEXP (x, 0), + ((INTVAL (XEXP (x, 1)) - + STACK_BIAS) & mask) + + STACK_BIAS), + mode, mask, reg, next_select); + } +#endif + if ((nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0 + && (INTVAL (XEXP (x, 1)) & ~ mask) != 0) + return force_to_mode (plus_constant (XEXP (x, 0), + INTVAL (XEXP (x, 1)) & mask), + mode, mask, reg, next_select); + } } - /* ... fall through ... */ + /* ... fall through ... */ case MINUS: case MULT: @@ -5904,13 +6433,14 @@ force_to_mode (x, mode, mask, reg, just_select) + floor_log2 (INTVAL (XEXP (x, 1)))) < GET_MODE_BITSIZE (GET_MODE (x))) && (INTVAL (XEXP (x, 1)) - & ~ nonzero_bits (XEXP (x, 0), GET_MODE (x)) == 0)) + & ~ nonzero_bits (XEXP (x, 0), GET_MODE (x))) == 0) { temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask) << INTVAL (XEXP (XEXP (x, 0), 1))); temp = gen_binary (GET_CODE (x), GET_MODE (x), XEXP (XEXP (x, 0), 0), temp); - x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (x, 1)); + x = gen_binary (LSHIFTRT, GET_MODE (x), temp, + XEXP (XEXP (x, 0), 1)); return force_to_mode (x, mode, mask, reg, next_select); } @@ -6041,7 +6571,7 @@ force_to_mode (x, mode, mask, reg, just_select) if (GET_MODE_BITSIZE (GET_MODE (x)) > HOST_BITS_PER_WIDE_INT) { - nonzero = ~(HOST_WIDE_INT)0; + nonzero = ~ (HOST_WIDE_INT) 0; /* GET_MODE_BITSIZE (GET_MODE (x)) - INTVAL (XEXP (x, 1)) is the number of bits a full-width mask would have set. @@ -6145,6 +6675,10 @@ force_to_mode (x, mode, mask, reg, just_select) return force_to_mode (x, mode, mask, reg, next_select); } + /* (and (not FOO) CONST) is (not (or FOO (not CONST))), so we must + use the full mask inside the NOT. */ + mask = fuller_mask; + unop: op0 = gen_lowpart_for_combine (op_mode, force_to_mode (XEXP (x, 0), mode, mask, @@ -6155,10 +6689,11 @@ force_to_mode (x, mode, mask, reg, just_select) case NE: /* (and (ne FOO 0) CONST) can be (and FOO CONST) if CONST is included - in STORE_FLAG_VALUE and FOO has no bits that might be nonzero not - in CONST. */ - if ((mask & ~ STORE_FLAG_VALUE) == 0 && XEXP (x, 0) == const0_rtx - && (nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0) + in STORE_FLAG_VALUE and FOO has a single bit that might be nonzero, + which is equal to STORE_FLAG_VALUE. */ + if ((mask & ~ STORE_FLAG_VALUE) == 0 && XEXP (x, 1) == const0_rtx + && exact_log2 (nonzero_bits (XEXP (x, 0), mode)) >= 0 + && nonzero_bits (XEXP (x, 0), mode) == STORE_FLAG_VALUE) return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select); break; @@ -6176,6 +6711,9 @@ force_to_mode (x, mode, mask, reg, just_select) force_to_mode (XEXP (x, 2), mode, mask, reg,next_select))); break; + + default: + break; } /* Ensure we return a value of the proper mode. */ @@ -6227,17 +6765,25 @@ if_then_else_cond (x, ptrue, pfalse) if ((cond0 != 0 || cond1 != 0) && ! (cond0 != 0 && cond1 != 0 && ! rtx_equal_p (cond0, cond1))) { + /* If if_then_else_cond returned zero, then true/false are the + same rtl. We must copy one of them to prevent invalid rtl + sharing. */ + if (cond0 == 0) + true0 = copy_rtx (true0); + else if (cond1 == 0) + true1 = copy_rtx (true1); + *ptrue = gen_binary (code, mode, true0, true1); *pfalse = gen_binary (code, mode, false0, false1); return cond0 ? cond0 : cond1; } -#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1 - /* See if we have PLUS, IOR, XOR, MINUS or UMAX, where one of the - operands is zero when the other is non-zero, and vice-versa. */ + operands is zero when the other is non-zero, and vice-versa, + and STORE_FLAG_VALUE is 1 or -1. */ - if ((code == PLUS || code == IOR || code == XOR || code == MINUS + if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) + && (code == PLUS || code == IOR || code == XOR || code == MINUS || code == UMAX) && GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == MULT) { @@ -6270,7 +6816,8 @@ if_then_else_cond (x, ptrue, pfalse) /* Similarly for MULT, AND and UMIN, execpt that for these the result is always zero. */ - if ((code == MULT || code == AND || code == UMIN) + if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) + && (code == MULT || code == AND || code == UMIN) && GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == MULT) { cond0 = XEXP (XEXP (x, 0), 0); @@ -6292,7 +6839,6 @@ if_then_else_cond (x, ptrue, pfalse) return cond0; } } -#endif } else if (code == IF_THEN_ELSE) @@ -6390,6 +6936,8 @@ known_cond (x, cond, reg, val) case LT: case LE: return gen_unary (NEG, GET_MODE (XEXP (x, 0)), GET_MODE (XEXP (x, 0)), XEXP (x, 0)); + default: + break; } /* The only other cases we handle are MIN, MAX, and comparisons if the @@ -6426,6 +6974,8 @@ known_cond (x, cond, reg, val) return unsignedp ? XEXP (x, 1) : x; case LEU: case LTU: return unsignedp ? XEXP (x, 0) : x; + default: + break; } } } @@ -6445,6 +6995,43 @@ known_cond (x, cond, reg, val) return x; } +/* See if X and Y are equal for the purposes of seeing if we can rewrite an + assignment as a field assignment. */ + +static int +rtx_equal_for_field_assignment_p (x, y) + rtx x; + rtx y; +{ + if (x == y || rtx_equal_p (x, y)) + return 1; + + if (x == 0 || y == 0 || GET_MODE (x) != GET_MODE (y)) + return 0; + + /* Check for a paradoxical SUBREG of a MEM compared with the MEM. + Note that all SUBREGs of MEM are paradoxical; otherwise they + would have been rewritten. */ + if (GET_CODE (x) == MEM && GET_CODE (y) == SUBREG + && GET_CODE (SUBREG_REG (y)) == MEM + && rtx_equal_p (SUBREG_REG (y), + gen_lowpart_for_combine (GET_MODE (SUBREG_REG (y)), x))) + return 1; + + if (GET_CODE (y) == MEM && GET_CODE (x) == SUBREG + && GET_CODE (SUBREG_REG (x)) == MEM + && rtx_equal_p (SUBREG_REG (x), + gen_lowpart_for_combine (GET_MODE (SUBREG_REG (x)), y))) + return 1; + + /* We used to see if get_last_value of X and Y were the same but that's + not correct. In one direction, we'll cause the assignment to have + the wrong destination and in the case, we'll import a register into this + insn that might have already have been dead. So fail if none of the + above cases are true. */ + return 0; +} + /* See if X, a SET operation, can be rewritten as a bit-field assignment. Return that assignment if so. @@ -6457,6 +7044,7 @@ make_field_assignment (x) rtx dest = SET_DEST (x); rtx src = SET_SRC (x); rtx assign; + rtx rhs, lhs; HOST_WIDE_INT c1; int pos, len; rtx other; @@ -6470,13 +7058,13 @@ make_field_assignment (x) if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == ROTATE && GET_CODE (XEXP (XEXP (src, 0), 0)) == CONST_INT && INTVAL (XEXP (XEXP (src, 0), 0)) == -2 - && (rtx_equal_p (dest, XEXP (src, 1)) - || rtx_equal_p (dest, get_last_value (XEXP (src, 1))) - || rtx_equal_p (get_last_value (dest), XEXP (src, 1)))) + && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) { assign = make_extraction (VOIDmode, dest, 0, XEXP (XEXP (src, 0), 1), 1, 1, 1, 0); - return gen_rtx (SET, VOIDmode, assign, const0_rtx); + if (assign != 0) + return gen_rtx_SET (VOIDmode, assign, const0_rtx); + return x; } else if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == SUBREG @@ -6485,60 +7073,63 @@ make_field_assignment (x) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (src, 0))))) && GET_CODE (SUBREG_REG (XEXP (src, 0))) == ROTATE && INTVAL (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == -2 - && (rtx_equal_p (dest, XEXP (src, 1)) - || rtx_equal_p (dest, get_last_value (XEXP (src, 1))) - || rtx_equal_p (get_last_value (dest), XEXP (src, 1)))) + && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) { assign = make_extraction (VOIDmode, dest, 0, XEXP (SUBREG_REG (XEXP (src, 0)), 1), 1, 1, 1, 0); - return gen_rtx (SET, VOIDmode, assign, const0_rtx); + if (assign != 0) + return gen_rtx_SET (VOIDmode, assign, const0_rtx); + return x; } - /* If SRC is (ior (ashift (const_int 1) POS DEST)), this is a set of a + /* If SRC is (ior (ashift (const_int 1) POS) DEST), this is a set of a one-bit field. */ else if (GET_CODE (src) == IOR && GET_CODE (XEXP (src, 0)) == ASHIFT && XEXP (XEXP (src, 0), 0) == const1_rtx - && (rtx_equal_p (dest, XEXP (src, 1)) - || rtx_equal_p (dest, get_last_value (XEXP (src, 1))) - || rtx_equal_p (get_last_value (dest), XEXP (src, 1)))) + && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) { assign = make_extraction (VOIDmode, dest, 0, XEXP (XEXP (src, 0), 1), 1, 1, 1, 0); - return gen_rtx (SET, VOIDmode, assign, const1_rtx); + if (assign != 0) + return gen_rtx_SET (VOIDmode, assign, const1_rtx); + return x; } /* The other case we handle is assignments into a constant-position - field. They look like (ior (and DEST C1) OTHER). If C1 represents + field. They look like (ior/xor (and DEST C1) OTHER). If C1 represents a mask that has all one bits except for a group of zero bits and OTHER is known to have zeros where C1 has ones, this is such an assignment. Compute the position and length from C1. Shift OTHER to the appropriate position, force it to the required mode, and make the extraction. Check for the AND in both operands. */ - if (GET_CODE (src) == IOR && GET_CODE (XEXP (src, 0)) == AND - && GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT - && (rtx_equal_p (XEXP (XEXP (src, 0), 0), dest) - || rtx_equal_p (XEXP (XEXP (src, 0), 0), get_last_value (dest)) - || rtx_equal_p (get_last_value (XEXP (XEXP (src, 0), 1)), dest))) - c1 = INTVAL (XEXP (XEXP (src, 0), 1)), other = XEXP (src, 1); - else if (GET_CODE (src) == IOR && GET_CODE (XEXP (src, 1)) == AND - && GET_CODE (XEXP (XEXP (src, 1), 1)) == CONST_INT - && (rtx_equal_p (XEXP (XEXP (src, 1), 0), dest) - || rtx_equal_p (XEXP (XEXP (src, 1), 0), get_last_value (dest)) - || rtx_equal_p (get_last_value (XEXP (XEXP (src, 1), 0)), - dest))) - c1 = INTVAL (XEXP (XEXP (src, 1), 1)), other = XEXP (src, 0); + if (GET_CODE (src) != IOR && GET_CODE (src) != XOR) + return x; + + rhs = expand_compound_operation (XEXP (src, 0)); + lhs = expand_compound_operation (XEXP (src, 1)); + + if (GET_CODE (rhs) == AND + && GET_CODE (XEXP (rhs, 1)) == CONST_INT + && rtx_equal_for_field_assignment_p (XEXP (rhs, 0), dest)) + c1 = INTVAL (XEXP (rhs, 1)), other = lhs; + else if (GET_CODE (lhs) == AND + && GET_CODE (XEXP (lhs, 1)) == CONST_INT + && rtx_equal_for_field_assignment_p (XEXP (lhs, 0), dest)) + c1 = INTVAL (XEXP (lhs, 1)), other = rhs; else return x; - pos = get_pos_from_mask (c1 ^ GET_MODE_MASK (GET_MODE (dest)), &len); + pos = get_pos_from_mask ((~ c1) & GET_MODE_MASK (GET_MODE (dest)), &len); if (pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (dest)) - || (GET_MODE_BITSIZE (GET_MODE (other)) <= HOST_BITS_PER_WIDE_INT - && (c1 & nonzero_bits (other, GET_MODE (other))) != 0)) + || GET_MODE_BITSIZE (GET_MODE (dest)) > HOST_BITS_PER_WIDE_INT + || (c1 & nonzero_bits (other, GET_MODE (dest))) != 0) return x; assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0); + if (assign == 0) + return x; /* The mode to use for the source is the mode of the assignment, or of what is inside a possible STRICT_LOW_PART. */ @@ -6584,7 +7175,8 @@ apply_distributive_law (x) lhs = XEXP (x, 0), rhs = XEXP (x, 1); - /* If either operand is a primitive we can't do anything, so get out fast. */ + /* If either operand is a primitive we can't do anything, so get out + fast. */ if (GET_RTX_CLASS (GET_CODE (lhs)) == 'o' || GET_RTX_CLASS (GET_CODE (rhs)) == 'o') return x; @@ -6769,7 +7361,7 @@ simplify_and_const_int (x, mode, varop, constop) else varop = gen_lowpart_for_combine (mode, varop); - /* If we can't make the SUBREG, try to return what we were given. */ + /* If we can't make the SUBREG, try to return what we were given. */ if (GET_CODE (varop) == CLOBBER) return x ? x : varop; @@ -6793,6 +7385,13 @@ simplify_and_const_int (x, mode, varop, constop) return x; } +/* We let num_sign_bit_copies recur into nonzero_bits as that is useful. + We don't let nonzero_bits recur into num_sign_bit_copies, because that + is less useful. We can't allow both, because that results in exponential + run time recursion. There is a nullstone testcase that triggered + this. This macro avoids accidental uses of num_sign_bit_copies. */ +#define num_sign_bit_copies() + /* Given an expression, X, compute which bits in X can be non-zero. We don't care about bits outside of those defined in MODE. @@ -6864,12 +7463,26 @@ nonzero_bits (x, mode) stack to be momentarily aligned only to that amount, so we pick the least alignment. */ - if (x == stack_pointer_rtx) + /* We can't check for arg_pointer_rtx here, because it is not + guaranteed to have as much alignment as the stack pointer. + In particular, in the Irix6 n64 ABI, the stack has 128 bit + alignment but the argument pointer has only 64 bit alignment. */ + + if ((x == frame_pointer_rtx + || x == stack_pointer_rtx + || x == hard_frame_pointer_rtx + || (REGNO (x) >= FIRST_VIRTUAL_REGISTER + && REGNO (x) <= LAST_VIRTUAL_REGISTER)) +#ifdef STACK_BIAS + && !STACK_BIAS +#endif + ) { int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT; #ifdef PUSH_ROUNDING - sp_alignment = MIN (PUSH_ROUNDING (1), sp_alignment); + if (REGNO (x) == STACK_POINTER_REGNUM) + sp_alignment = MIN (PUSH_ROUNDING (1), sp_alignment); #endif /* We must return here, otherwise we may get a worse result from @@ -6886,7 +7499,7 @@ nonzero_bits (x, mode) if (reg_last_set_value[REGNO (x)] != 0 && reg_last_set_mode[REGNO (x)] == mode - && (reg_n_sets[REGNO (x)] == 1 + && (REG_N_SETS (REGNO (x)) == 1 || reg_last_set_label[REGNO (x)] == label_tick) && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid) return reg_last_set_nonzero_bits[REGNO (x)]; @@ -6958,18 +7571,26 @@ nonzero_bits (x, mode) break; case NEG: +#if 0 + /* Disabled to avoid exponential mutual recursion between nonzero_bits + and num_sign_bit_copies. */ if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x)) == GET_MODE_BITSIZE (GET_MODE (x))) nonzero = 1; +#endif if (GET_MODE_SIZE (GET_MODE (x)) < mode_width) nonzero |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (x))); break; case ABS: +#if 0 + /* Disabled to avoid exponential mutual recursion between nonzero_bits + and num_sign_bit_copies. */ if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x)) == GET_MODE_BITSIZE (GET_MODE (x))) nonzero = 1; +#endif break; case TRUNCATE: @@ -6990,9 +7611,9 @@ nonzero_bits (x, mode) if (GET_MODE (XEXP (x, 0)) != VOIDmode) { inner_nz &= GET_MODE_MASK (GET_MODE (XEXP (x, 0))); - if (inner_nz & - (((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1)))) + if (inner_nz + & (((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1)))) inner_nz |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))); } @@ -7036,6 +7657,22 @@ nonzero_bits (x, mode) switch (code) { case PLUS: +#ifdef STACK_BIAS + if (STACK_BIAS + && (XEXP (x, 0) == stack_pointer_rtx + || XEXP (x, 0) == frame_pointer_rtx) + && GET_CODE (XEXP (x, 1)) == CONST_INT) + { + int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT; + + nz0 = (GET_MODE_MASK (mode) & ~ (sp_alignment - 1)); + nz1 = INTVAL (XEXP (x, 1)) - STACK_BIAS; + width0 = floor_log2 (nz0) + 1; + width1 = floor_log2 (nz1) + 1; + low0 = floor_log2 (nz0 & -nz0); + low1 = floor_log2 (nz1 & -nz1); + } +#endif result_width = MAX (width0, width1) + 1; result_low = MIN (low0, low1); break; @@ -7062,6 +7699,8 @@ nonzero_bits (x, mode) result_width = MIN (width0, width1); result_low = MIN (low0, low1); break; + default: + abort (); } if (result_width < mode_width) @@ -7096,15 +7735,23 @@ nonzero_bits (x, mode) { nonzero &= nonzero_bits (SUBREG_REG (x), mode); -#ifndef WORD_REGISTER_OPERATIONS - /* On many CISC machines, accessing an object in a wider mode - causes the high-order bits to become undefined. So they are - not known to be zero. */ - if (GET_MODE_SIZE (GET_MODE (x)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) - nonzero |= (GET_MODE_MASK (GET_MODE (x)) - & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))); +#if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP) + /* If this is a typical RISC machine, we only have to worry + about the way loads are extended. */ + if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND + ? (nonzero + & (1L << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))) + : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND) #endif + { + /* On many CISC machines, accessing an object in a wider mode + causes the high-order bits to become undefined. So they are + not known to be zero. */ + if (GET_MODE_SIZE (GET_MODE (x)) + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) + nonzero |= (GET_MODE_MASK (GET_MODE (x)) + & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))); + } } break; @@ -7164,10 +7811,16 @@ nonzero_bits (x, mode) nonzero &= (nonzero_bits (XEXP (x, 1), mode) | nonzero_bits (XEXP (x, 2), mode)); break; + + default: + break; } return nonzero; } + +/* See the macro definition above. */ +#undef num_sign_bit_copies /* Return the number of bits at the high-order end of X that are known to be equal to the sign bit. X will be used in mode MODE; if MODE is @@ -7197,18 +7850,30 @@ num_sign_bit_copies (x, mode) bitwidth = GET_MODE_BITSIZE (mode); - /* For a smaller object, just ignore the high bits. */ + /* For a smaller object, just ignore the high bits. */ if (bitwidth < GET_MODE_BITSIZE (GET_MODE (x))) return MAX (1, (num_sign_bit_copies (x, GET_MODE (x)) - (GET_MODE_BITSIZE (GET_MODE (x)) - bitwidth))); + if (GET_MODE (x) != VOIDmode && bitwidth > GET_MODE_BITSIZE (GET_MODE (x))) + { #ifndef WORD_REGISTER_OPERATIONS /* If this machine does not do all register operations on the entire register and MODE is wider than the mode of X, we can say nothing at all about the high-order bits. */ - if (GET_MODE (x) != VOIDmode && bitwidth > GET_MODE_BITSIZE (GET_MODE (x))) - return 1; + return 1; +#else + /* Likewise on machines that do, if the mode of the object is smaller + than a word and loads of that size don't sign extend, we can say + nothing about the high order bits. */ + if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD +#ifdef LOAD_EXTEND_OP + && LOAD_EXTEND_OP (GET_MODE (x)) != SIGN_EXTEND #endif + ) + return 1; +#endif + } switch (code) { @@ -7224,7 +7889,7 @@ num_sign_bit_copies (x, mode) if (reg_last_set_value[REGNO (x)] != 0 && reg_last_set_mode[REGNO (x)] == mode - && (reg_n_sets[REGNO (x)] == 1 + && (REG_N_SETS (REGNO (x)) == 1 || reg_last_set_label[REGNO (x)] == label_tick) && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid) return reg_last_set_sign_bit_copies[REGNO (x)]; @@ -7264,7 +7929,7 @@ num_sign_bit_copies (x, mode) return MAX (bitwidth - GET_MODE_BITSIZE (GET_MODE (x)) + 1, num_sign_bit_copies (SUBREG_REG (x), mode)); - /* For a smaller object, just ignore the high bits. */ + /* For a smaller object, just ignore the high bits. */ if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))) { num0 = num_sign_bit_copies (SUBREG_REG (x), VOIDmode); @@ -7303,7 +7968,7 @@ num_sign_bit_copies (x, mode) + num_sign_bit_copies (XEXP (x, 0), VOIDmode)); case TRUNCATE: - /* For a smaller object, just ignore the high bits. */ + /* For a smaller object, just ignore the high bits. */ num0 = num_sign_bit_copies (XEXP (x, 0), VOIDmode); return MAX (1, (num0 - (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - bitwidth))); @@ -7329,13 +7994,15 @@ num_sign_bit_copies (x, mode) is known to be positive, the number of sign bit copies is the same as that of the input. Finally, if the input has just one bit that might be nonzero, all the bits are copies of the sign bit. */ + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + if (bitwidth > HOST_BITS_PER_WIDE_INT) + return num0 > 1 ? num0 - 1 : 1; + nonzero = nonzero_bits (XEXP (x, 0), mode); if (nonzero == 1) return bitwidth; - num0 = num_sign_bit_copies (XEXP (x, 0), mode); if (num0 > 1 - && bitwidth <= HOST_BITS_PER_WIDE_INT && (((HOST_WIDE_INT) 1 << (bitwidth - 1)) & nonzero)) num0--; @@ -7379,19 +8046,27 @@ num_sign_bit_copies (x, mode) result = bitwidth - (bitwidth - num0) - (bitwidth - num1); if (result > 0 - && bitwidth <= HOST_BITS_PER_WIDE_INT - && ((nonzero_bits (XEXP (x, 0), mode) - & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) - && (nonzero_bits (XEXP (x, 1), mode) - & ((HOST_WIDE_INT) 1 << (bitwidth - 1)) != 0)) + && (bitwidth > HOST_BITS_PER_WIDE_INT + || (((nonzero_bits (XEXP (x, 0), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) + && ((nonzero_bits (XEXP (x, 1), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)))) result--; return MAX (1, result); case UDIV: - /* The result must be <= the first operand. */ - return num_sign_bit_copies (XEXP (x, 0), mode); - + /* The result must be <= the first operand. If the first operand + has the high bit set, we know nothing about the number of sign + bit copies. */ + if (bitwidth > HOST_BITS_PER_WIDE_INT) + return 1; + else if ((nonzero_bits (XEXP (x, 0), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) + return 1; + else + return num_sign_bit_copies (XEXP (x, 0), mode); + case UMOD: /* The result must be <= the scond operand. */ return num_sign_bit_copies (XEXP (x, 1), mode); @@ -7402,20 +8077,20 @@ num_sign_bit_copies (x, mode) to add 1. */ result = num_sign_bit_copies (XEXP (x, 0), mode); if (result > 1 - && bitwidth <= HOST_BITS_PER_WIDE_INT - && (nonzero_bits (XEXP (x, 1), mode) - & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) - result --; + && (bitwidth > HOST_BITS_PER_WIDE_INT + || (nonzero_bits (XEXP (x, 1), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)) + result--; return result; case MOD: result = num_sign_bit_copies (XEXP (x, 1), mode); if (result > 1 - && bitwidth <= HOST_BITS_PER_WIDE_INT - && (nonzero_bits (XEXP (x, 1), mode) - & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) - result --; + && (bitwidth > HOST_BITS_PER_WIDE_INT + || (nonzero_bits (XEXP (x, 1), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)) + result--; return result; @@ -7444,11 +8119,14 @@ num_sign_bit_copies (x, mode) num1 = num_sign_bit_copies (XEXP (x, 2), mode); return MIN (num0, num1); -#if STORE_FLAG_VALUE == -1 case EQ: case NE: case GE: case GT: case LE: case LT: case GEU: case GTU: case LEU: case LTU: - return bitwidth; -#endif + if (STORE_FLAG_VALUE == -1) + return bitwidth; + break; + + default: + break; } /* If we haven't been able to figure it out by one of the above rules, @@ -7560,6 +8238,8 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) case NEG: op0 = NIL; break; + default: + break; } } @@ -7581,7 +8261,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) op0 = SET; else /* op1 == XOR */ /* (a ^ b) | b == a | b */ - ; + {;} break; case XOR: @@ -7601,6 +8281,8 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) /* (a ^ b) & b) == (~a) & b */ *pcomp_p = 1; break; + default: + break; } /* Check for NO-OP cases. */ @@ -7669,7 +8351,7 @@ simplify_shift_const (x, code, result_mode, varop, count) if (x) return x; - return gen_rtx (code, mode, varop, GEN_INT (count)); + return gen_rtx_fmt_ee (code, mode, varop, GEN_INT (count)); } /* Unless one of the branches of the `if' in this loop does a `continue', @@ -7694,7 +8376,7 @@ simplify_shift_const (x, code, result_mode, varop, count) /* We need to determine what mode we will do the shift in. If the shift is a right shift or a ROTATE, we must always do it in the mode it was originally done in. Otherwise, we can do it in MODE, the - widest mode encountered. */ + widest mode encountered. */ shift_mode = (code == ASHIFTRT || code == LSHIFTRT || code == ROTATE ? result_mode : mode); @@ -7727,7 +8409,7 @@ simplify_shift_const (x, code, result_mode, varop, count) /* Negative counts are invalid and should not have been made (a programmer-specified negative count should have been handled - above). */ + above). */ else if (count < 0) abort (); @@ -7787,11 +8469,11 @@ simplify_shift_const (x, code, result_mode, varop, count) MODE_INT, 1)) != BLKmode) { if (BYTES_BIG_ENDIAN) - new = gen_rtx (MEM, tmode, XEXP (varop, 0)); + new = gen_rtx_MEM (tmode, XEXP (varop, 0)); else - new = gen_rtx (MEM, tmode, - plus_constant (XEXP (varop, 0), - count / BITS_PER_UNIT)); + new = gen_rtx_MEM (tmode, + 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); @@ -7880,7 +8562,7 @@ simplify_shift_const (x, code, result_mode, varop, count) continue; } - /* ... fall through ... */ + /* ... fall through ... */ case LSHIFTRT: case ASHIFT: @@ -8216,9 +8898,9 @@ simplify_shift_const (x, code, result_mode, varop, count) STORE_FLAG_VALUE of 1 or logical with STORE_FLAG_VALUE == -1, we have a (neg (gt X 0)) operation. */ - if (GET_CODE (XEXP (varop, 0)) == ASHIFTRT + if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) + && GET_CODE (XEXP (varop, 0)) == ASHIFTRT && count == GET_MODE_BITSIZE (GET_MODE (varop)) - 1 - && (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) && (code == LSHIFTRT || code == ASHIFTRT) && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (varop, 0), 1)) == count @@ -8234,6 +8916,32 @@ simplify_shift_const (x, code, result_mode, varop, count) continue; } break; + + case TRUNCATE: + /* Change (lshiftrt (truncate (lshiftrt))) to (truncate (lshiftrt)) + if the truncate does not affect the value. */ + if (code == LSHIFTRT + && GET_CODE (XEXP (varop, 0)) == LSHIFTRT + && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT + && (INTVAL (XEXP (XEXP (varop, 0), 1)) + >= (GET_MODE_BITSIZE (GET_MODE (XEXP (varop, 0))) + - GET_MODE_BITSIZE (GET_MODE (varop))))) + { + rtx varop_inner = XEXP (varop, 0); + + varop_inner = gen_rtx_combine (LSHIFTRT, + GET_MODE (varop_inner), + XEXP (varop_inner, 0), + GEN_INT (count + INTVAL (XEXP (varop_inner, 1)))); + varop = gen_rtx_combine (TRUNCATE, GET_MODE (varop), + varop_inner); + count = 0; + continue; + } + break; + + default: + break; } break; @@ -8271,7 +8979,7 @@ simplify_shift_const (x, code, result_mode, varop, count) else if (GET_MODE (varop) != shift_mode) varop = gen_lowpart_for_combine (shift_mode, varop); - /* If we can't make the SUBREG, try to return what we were given. */ + /* If we can't make the SUBREG, try to return what we were given. */ if (GET_CODE (varop) == CLOBBER) return x ? x : varop; @@ -8421,10 +9129,10 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches) them. Then check to make sure that all of them are dead. */ if (num_clobbers_to_add) { - rtx newpat = gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (GET_CODE (pat) == PARALLEL - ? XVECLEN (pat, 0) + num_clobbers_to_add - : num_clobbers_to_add + 1)); + rtx newpat = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (GET_CODE (pat) == PARALLEL + ? XVECLEN (pat, 0) + num_clobbers_to_add + : num_clobbers_to_add + 1)); if (GET_CODE (pat) == PARALLEL) for (i = 0; i < XVECLEN (pat, 0); i++) @@ -8442,8 +9150,8 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches) 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); + notes = gen_rtx_EXPR_LIST (REG_UNUSED, + XEXP (XVECEXP (newpat, 0, i), 0), notes); } pat = newpat; } @@ -8483,7 +9191,7 @@ gen_lowpart_for_combine (mode, x) && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)) || GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (mode))) - return gen_rtx (CLOBBER, GET_MODE (x), const0_rtx); + return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); /* X might be a paradoxical (subreg (mem)). In that case, gen_lowpart won't know what to do. So we will strip off the SUBREG here and @@ -8502,7 +9210,7 @@ gen_lowpart_for_combine (mode, x) && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER && (GET_MODE_SIZE (GET_MODE (result)) != GET_MODE_SIZE (GET_MODE (SUBREG_REG (result))))) - reg_changes_size[REGNO (SUBREG_REG (result))] = 1; + REG_CHANGES_SIZE (REGNO (SUBREG_REG (result))) = 1; if (result) return result; @@ -8515,13 +9223,13 @@ gen_lowpart_for_combine (mode, x) /* Refuse to work on a volatile memory ref or one with a mode-dependent address. */ if (MEM_VOLATILE_P (x) || mode_dependent_address_p (XEXP (x, 0))) - return gen_rtx (CLOBBER, GET_MODE (x), const0_rtx); + return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); /* If we want to refer to something bigger than the original memref, generate a perverse subreg instead. That will force a reload of the original memref X. */ if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode)) - return gen_rtx (SUBREG, mode, x, 0); + return gen_rtx_SUBREG (mode, x, 0); if (WORDS_BIG_ENDIAN) offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) @@ -8533,7 +9241,7 @@ gen_lowpart_for_combine (mode, x) offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); } - new = gen_rtx (MEM, mode, plus_constant (XEXP (x, 0), offset)); + 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); @@ -8556,7 +9264,7 @@ gen_lowpart_for_combine (mode, x) word = ((GET_MODE_SIZE (GET_MODE (x)) - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)) / UNITS_PER_WORD); - return gen_rtx (SUBREG, mode, x, word); + return gen_rtx_SUBREG (mode, x, word); } } @@ -8578,9 +9286,10 @@ gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...)) va_list p; int n_args; rtx args[3]; - int i, j; + int j; char *fmt; rtx rt; + struct undo *undo; VA_START (p, mode); @@ -8607,17 +9316,17 @@ gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...)) /* See if this is in undobuf. Be sure we don't use objects that came from another insn; this could produce circular rtl structures. */ - for (i = previous_num_undos; i < undobuf.num_undo; i++) - if (!undobuf.undo[i].is_int - && GET_CODE (undobuf.undo[i].old_contents.r) == code - && GET_MODE (undobuf.undo[i].old_contents.r) == mode) + for (undo = undobuf.undos; undo != undobuf.previous_undos; undo = undo->next) + if (!undo->is_int + && GET_CODE (undo->old_contents.r) == code + && GET_MODE (undo->old_contents.r) == mode) { for (j = 0; j < n_args; j++) - if (XEXP (undobuf.undo[i].old_contents.r, j) != args[j]) + if (XEXP (undo->old_contents.r, j) != args[j]) break; if (j == n_args) - return undobuf.undo[i].old_contents.r; + return undo->old_contents.r; } /* Otherwise make a new rtx. We know we have 1, 2, or 3 args. @@ -8656,7 +9365,7 @@ gen_binary (code, mode, op0, op1) enum machine_mode op_mode = GET_MODE (op0); /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get - just (REL_OP X Y). */ + just (REL_OP X Y). */ if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) { op1 = XEXP (op0, 1); @@ -8684,6 +9393,13 @@ gen_binary (code, mode, op0, op1) && GET_RTX_CLASS (GET_CODE (op1)) != 'o'))) return gen_rtx_combine (code, mode, op1, op0); + /* If we are turning off bits already known off in OP0, we need not do + an AND. */ + else if (code == AND && GET_CODE (op1) == CONST_INT + && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT + && (nonzero_bits (op0, mode) & ~ INTVAL (op1)) == 0) + return op0; + return gen_rtx_combine (code, mode, op0, op1); } @@ -8816,18 +9532,18 @@ simplify_comparison (code, pop0, pop1) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner_op0)))) && (GET_MODE (SUBREG_REG (inner_op0)) == GET_MODE (SUBREG_REG (inner_op1))) - && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) + && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (inner_op0))) <= HOST_BITS_PER_WIDE_INT) - && (0 == (~c0) & nonzero_bits (SUBREG_REG (inner_op0), - GET_MODE (SUBREG_REG (op0)))) - && (0 == (~c1) & nonzero_bits (SUBREG_REG (inner_op1), - GET_MODE (SUBREG_REG (inner_op1))))) + && (0 == ((~c0) & nonzero_bits (SUBREG_REG (inner_op0), + GET_MODE (SUBREG_REG (inner_op0))))) + && (0 == ((~c1) & nonzero_bits (SUBREG_REG (inner_op1), + GET_MODE (SUBREG_REG (inner_op1)))))) { op0 = SUBREG_REG (inner_op0); op1 = SUBREG_REG (inner_op1); /* The resulting comparison is always unsigned since we masked - off the original sign bit. */ + off the original sign bit. */ code = unsigned_condition (code); changed = 1; @@ -8863,8 +9579,9 @@ simplify_comparison (code, pop0, pop1) } /* If the first operand is a constant, swap the operands and adjust the - comparison code appropriately. */ - if (CONSTANT_P (op0)) + comparison code appropriately, but don't do this if the second operand + is already a constant integer. */ + if (CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT) { tem = op0, op0 = op1, op1 = tem; code = swap_condition (code); @@ -8966,7 +9683,7 @@ simplify_comparison (code, pop0, pop1) break; case GE: - /* >= C is equivalent to > (C - 1). */ + /* >= C is equivalent to > (C - 1). */ if (const_op > 0) { const_op -= 1; @@ -9002,11 +9719,12 @@ simplify_comparison (code, pop0, pop1) const_op -= 1; op1 = GEN_INT (const_op); code = LEU; - /* ... fall through ... */ + /* ... fall through ... */ } /* (unsigned) < 0x80000000 is equivalent to >= 0. */ - else if (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1)) + else if ((mode_width <= HOST_BITS_PER_WIDE_INT) + && (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1))) { const_op = 0, op1 = const0_rtx; code = GE; @@ -9020,8 +9738,9 @@ simplify_comparison (code, pop0, pop1) if (const_op == 0) code = EQ; - /* (unsigned) <= 0x7fffffff is equivalent to >= 0. */ - else if (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1) + /* (unsigned) <= 0x7fffffff is equivalent to >= 0. */ + else if ((mode_width <= HOST_BITS_PER_WIDE_INT) + && (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1)) { const_op = 0, op1 = const0_rtx; code = GE; @@ -9035,11 +9754,12 @@ simplify_comparison (code, pop0, pop1) const_op -= 1; op1 = GEN_INT (const_op); code = GTU; - /* ... fall through ... */ + /* ... fall through ... */ } /* (unsigned) >= 0x80000000 is equivalent to < 0. */ - else if (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1)) + else if ((mode_width <= HOST_BITS_PER_WIDE_INT) + && (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1))) { const_op = 0, op1 = const0_rtx; code = LT; @@ -9054,12 +9774,16 @@ simplify_comparison (code, pop0, pop1) code = NE; /* (unsigned) > 0x7fffffff is equivalent to < 0. */ - else if (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1) + else if ((mode_width <= HOST_BITS_PER_WIDE_INT) + && (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1)) { const_op = 0, op1 = const0_rtx; code = LT; } break; + + default: + break; } /* Compute some predicates to simplify code below. */ @@ -9088,24 +9812,19 @@ simplify_comparison (code, pop0, pop1) /* If we are extracting a single bit from a variable position in a constant that has only a single bit set and are comparing it with zero, we can convert this into an equality comparison - between the position and the location of the single bit. We can't - do this if bit endian and we don't have an extzv since we then - can't know what mode to use for the endianness adjustment. */ + between the position and the location of the single bit. */ if (GET_CODE (XEXP (op0, 0)) == CONST_INT && XEXP (op0, 1) == const1_rtx && equality_comparison_p && const_op == 0 - && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0 - && (! BITS_BIG_ENDIAN -#ifdef HAVE_extzv - || HAVE_extzv -#endif - )) + && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0) { -#ifdef HAVE_extzv if (BITS_BIG_ENDIAN) +#ifdef HAVE_extzv i = (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i); +#else + i = BITS_PER_WORD - 1 - i; #endif op0 = XEXP (op0, 2); @@ -9117,7 +9836,7 @@ simplify_comparison (code, pop0, pop1) continue; } - /* ... fall through ... */ + /* ... fall through ... */ case SIGN_EXTRACT: tem = expand_compound_operation (op0); @@ -9177,7 +9896,7 @@ simplify_comparison (code, pop0, pop1) } /* If we have NEG of something whose two high-order bits are the - same, we know that "(-a) < 0" is equivalent to "a > 0". */ + same, we know that "(-a) < 0" is equivalent to "a > 0". */ if (num_sign_bit_copies (op0, mode) >= 2) { op0 = XEXP (op0, 0); @@ -9213,7 +9932,7 @@ simplify_comparison (code, pop0, pop1) continue; } - /* ... fall through ... */ + /* ... fall through ... */ case ABS: /* ABS is ignorable inside an equality comparison with zero. */ @@ -9280,7 +9999,7 @@ simplify_comparison (code, pop0, pop1) else break; - /* ... fall through ... */ + /* ... fall through ... */ case ZERO_EXTEND: if ((unsigned_comparison_p || equality_comparison_p) @@ -9484,6 +10203,48 @@ simplify_comparison (code, pop0, pop1) op0 = gen_lowpart_for_combine (tmode, XEXP (op0, 0)); continue; } + + /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1 fits + in both M1 and M2 and the SUBREG is either paradoxical or + represents the low part, permute the SUBREG and the AND and + try again. */ + if (GET_CODE (XEXP (op0, 0)) == SUBREG + && ((mode_width + >= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))) +#ifdef WORD_REGISTER_OPERATIONS + || subreg_lowpart_p (XEXP (op0, 0)) +#endif + ) +#ifndef WORD_REGISTER_OPERATIONS + /* It is unsafe to commute the AND into the SUBREG if the SUBREG + is paradoxical and WORD_REGISTER_OPERATIONS is not defined. + As originally written the upper bits have a defined value + due to the AND operation. However, if we commute the AND + inside the SUBREG then they no longer have defined values + and the meaning of the code has been changed. */ + && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0))) + <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))) +#endif + && GET_CODE (XEXP (op0, 1)) == CONST_INT + && mode_width <= HOST_BITS_PER_WIDE_INT + && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))) + <= HOST_BITS_PER_WIDE_INT) + && (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)) + != GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))) + + { + op0 + = gen_lowpart_for_combine + (mode, + gen_binary (AND, GET_MODE (SUBREG_REG (XEXP (op0, 0))), + SUBREG_REG (XEXP (op0, 0)), XEXP (op0, 1))); + continue; + } + break; case ASHIFT: @@ -9563,7 +10324,7 @@ simplify_comparison (code, pop0, pop1) continue; } - /* ... fall through ... */ + /* ... fall through ... */ case LSHIFTRT: /* If we have (compare (xshiftrt FOO N) (const_int C)) and the low order N bits of FOO are known to be zero, we can do this @@ -9597,13 +10358,16 @@ simplify_comparison (code, pop0, pop1) continue; } break; + + default: + break; } break; } /* Now make any compound operations involved in this comparison. Then, - check for an outmost SUBREG on OP0 that isn't doing anything or is + check for an outmost SUBREG on OP0 that is not doing anything or is paradoxical. The latter case can only occur when it is known that the "extra" bits will be zero. Therefore, it is safe to remove the SUBREG. We can never remove a SUBREG for a non-equality comparison because the @@ -9727,9 +10491,10 @@ reversible_comparison_p (x) x = get_last_value (XEXP (x, 0)); return (x && GET_CODE (x) == COMPARE && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))); + + default: + return 0; } - - return 0; } /* Utility function for following routine. Called when X is part of a value @@ -9832,11 +10597,12 @@ record_value_for_reg (reg, insn, value) /* The value being assigned might refer to X (like in "x++;"). In that case, we must replace it with (clobber (const_int 0)) to prevent infinite loops. */ - if (value && ! get_last_value_validate (&value, + if (value && ! get_last_value_validate (&value, insn, reg_last_set_label[regno], 0)) { value = copy_rtx (value); - if (! get_last_value_validate (&value, reg_last_set_label[regno], 1)) + if (! get_last_value_validate (&value, insn, + reg_last_set_label[regno], 1)) value = 0; } @@ -9957,8 +10723,9 @@ record_dead_and_set_regs (insn) we don't know exactly what registers it was produced from. */ static int -get_last_value_validate (loc, tick, replace) +get_last_value_validate (loc, insn, tick, replace) rtx *loc; + rtx insn; int tick; int replace; { @@ -9978,20 +10745,30 @@ get_last_value_validate (loc, tick, replace) if (reg_last_set_invalid[j] /* If this is a pseudo-register that was only set once, it is always valid. */ - || (! (regno >= FIRST_PSEUDO_REGISTER && reg_n_sets[regno] == 1) + || (! (regno >= FIRST_PSEUDO_REGISTER && REG_N_SETS (regno) == 1) && reg_last_set_label[j] > tick)) { if (replace) - *loc = gen_rtx (CLOBBER, GET_MODE (x), const0_rtx); + *loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); return replace; } return 1; } + /* If this is a memory reference, make sure that there were + no stores after it that might have clobbered the value. We don't + have alias info, so we assume any store invalidates it. */ + else if (GET_CODE (x) == MEM && ! RTX_UNCHANGING_P (x) + && INSN_CUID (insn) <= mem_last_set) + { + if (replace) + *loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); + return replace; + } for (i = 0; i < len; i++) if ((fmt[i] == 'e' - && get_last_value_validate (&XEXP (x, i), tick, replace) == 0) + && get_last_value_validate (&XEXP (x, i), insn, tick, replace) == 0) /* Don't bother with these. They shouldn't occur anyway. */ || fmt[i] == 'E') return 0; @@ -10013,7 +10790,7 @@ get_last_value (x) /* If this is a non-paradoxical SUBREG, get the value of its operand and then convert it to the desired mode. If this is a paradoxical SUBREG, - we cannot predict what values the "extra" bits might have. */ + we cannot predict what values the "extra" bits might have. */ if (GET_CODE (x) == SUBREG && subreg_lowpart_p (x) && (GET_MODE_SIZE (GET_MODE (x)) @@ -10027,10 +10804,11 @@ get_last_value (x) regno = REGNO (x); value = reg_last_set_value[regno]; - /* If we don't have a value or if it isn't for this basic block, return 0. */ + /* If we don't have a value or if it isn't for this basic block, + return 0. */ if (value == 0 - || (reg_n_sets[regno] != 1 + || (REG_N_SETS (regno) != 1 && reg_last_set_label[regno] != label_tick)) return 0; @@ -10077,7 +10855,7 @@ get_last_value (x) if (reg_mentioned_p (x, value)) value = replace_rtx (copy_rtx (value), x, - gen_rtx (CLOBBER, GET_MODE (x), const0_rtx)); + gen_rtx_CLOBBER (GET_MODE (x), const0_rtx)); if (reg_overlap_mentioned_p (x, value)) return 0; @@ -10087,14 +10865,16 @@ get_last_value (x) } /* If the value has all its registers valid, return it. */ - if (get_last_value_validate (&value, reg_last_set_label[regno], 0)) + if (get_last_value_validate (&value, reg_last_set[regno], + reg_last_set_label[regno], 0)) return value; /* Otherwise, make a copy and replace any invalid register with (clobber (const_int 0)). If that fails for some reason, return 0. */ value = copy_rtx (value); - if (get_last_value_validate (&value, reg_last_set_label[regno], 1)) + if (get_last_value_validate (&value, reg_last_set[regno], + reg_last_set_label[regno], 1)) return value; return 0; @@ -10240,8 +11020,7 @@ reg_dead_at_p (reg, insn) } for (i = reg_dead_regno; i < reg_dead_endregno; i++) - if (basic_block_live_at_start[block][i / REGSET_ELT_BITS] - & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))) + if (REGNO_REG_SET_P (basic_block_live_at_start[block], i)) return 0; return 1; @@ -10322,8 +11101,11 @@ mark_used_regs_combine (x) mark_used_regs_combine (XEXP (testreg, 0)); mark_used_regs_combine (SET_SRC (x)); - return; } + return; + + default: + break; } /* Recursively scan the operands of this expression. */ @@ -10360,7 +11142,7 @@ remove_death (regno, insn) if (note) { - reg_n_deaths[regno]--; + REG_N_DEATHS (regno)--; remove_note (insn, note); } @@ -10372,12 +11154,15 @@ remove_death (regno, insn) TO_INSN (exclusive), put a REG_DEAD note for that register in the list headed by PNOTES. + That said, don't move registers killed by maybe_kill_insn. + This is done when X is being merged by combination into TO_INSN. These notes will then be distributed as needed. */ static void -move_deaths (x, from_cuid, to_insn, pnotes) +move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes) rtx x; + rtx maybe_kill_insn; int from_cuid; rtx to_insn; rtx *pnotes; @@ -10392,6 +11177,11 @@ move_deaths (x, from_cuid, to_insn, pnotes) register rtx where_dead = reg_last_death[regno]; register rtx before_dead, after_dead; + /* Don't move the register if it gets killed in between from and to */ + if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn) + && !reg_referenced_p (x, maybe_kill_insn)) + return; + /* WHERE_DEAD could be a USE insn made by combine, so first we make sure that we have insns with valid INSN_CUID values. */ before_dead = where_dead; @@ -10420,7 +11210,7 @@ move_deaths (x, from_cuid, to_insn, pnotes) if (note != 0 && regno < FIRST_PSEUDO_REGISTER && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0))) - != GET_MODE_SIZE (GET_MODE (x)))) + > GET_MODE_SIZE (GET_MODE (x)))) { int deadregno = REGNO (XEXP (note, 0)); int deadend @@ -10432,24 +11222,34 @@ move_deaths (x, from_cuid, to_insn, pnotes) for (i = deadregno; i < deadend; i++) if (i < regno || i >= ourend) REG_NOTES (where_dead) - = gen_rtx (EXPR_LIST, REG_DEAD, - gen_rtx (REG, reg_raw_mode[i], i), - REG_NOTES (where_dead)); + = gen_rtx_EXPR_LIST (REG_DEAD, + gen_rtx_REG (reg_raw_mode[i], i), + REG_NOTES (where_dead)); } - /* If we didn't find any note, and we have a multi-reg hard + /* If we didn't find any note, or if we found a REG_DEAD note that + covers only part of the given reg, and we have a multi-reg hard register, then to be safe we must check for REG_DEAD notes for each register other than the first. They could have their own REG_DEAD notes lying around. */ - else if (note == 0 && regno < FIRST_PSEUDO_REGISTER + else if ((note == 0 + || (note != 0 + && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0))) + < GET_MODE_SIZE (GET_MODE (x))))) + && regno < FIRST_PSEUDO_REGISTER && HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1) { int ourend = regno + HARD_REGNO_NREGS (regno, GET_MODE (x)); - int i; + int i, offset; rtx oldnotes = 0; - for (i = regno + 1; i < ourend; i++) - move_deaths (gen_rtx (REG, reg_raw_mode[i], i), - from_cuid, to_insn, &oldnotes); + if (note) + offset = HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0))); + else + offset = 1; + + for (i = regno + offset; i < ourend; i++) + move_deaths (gen_rtx_REG (reg_raw_mode[i], i), + maybe_kill_insn, from_cuid, to_insn, &oldnotes); } if (note != 0 && GET_MODE (XEXP (note, 0)) == GET_MODE (x)) @@ -10458,9 +11258,9 @@ move_deaths (x, from_cuid, to_insn, pnotes) *pnotes = note; } else - *pnotes = gen_rtx (EXPR_LIST, REG_DEAD, x, *pnotes); + *pnotes = gen_rtx_EXPR_LIST (REG_DEAD, x, *pnotes); - reg_n_deaths[regno]++; + REG_N_DEATHS (regno)++; } return; @@ -10470,7 +11270,7 @@ move_deaths (x, from_cuid, to_insn, pnotes) { rtx dest = SET_DEST (x); - move_deaths (SET_SRC (x), from_cuid, to_insn, pnotes); + move_deaths (SET_SRC (x), maybe_kill_insn, from_cuid, to_insn, pnotes); /* In the case of a ZERO_EXTRACT, a STRICT_LOW_PART, or a SUBREG that accesses one word of a multi-word item, some @@ -10485,7 +11285,7 @@ move_deaths (x, from_cuid, to_insn, pnotes) == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))) { - move_deaths (dest, from_cuid, to_insn, pnotes); + move_deaths (dest, maybe_kill_insn, from_cuid, to_insn, pnotes); return; } @@ -10499,7 +11299,8 @@ move_deaths (x, from_cuid, to_insn, pnotes) being replaced so the old value is not used in this insn. */ if (GET_CODE (dest) == MEM) - move_deaths (XEXP (dest, 0), from_cuid, to_insn, pnotes); + move_deaths (XEXP (dest, 0), maybe_kill_insn, from_cuid, + to_insn, pnotes); return; } @@ -10515,10 +11316,11 @@ move_deaths (x, from_cuid, to_insn, pnotes) { register int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) - move_deaths (XVECEXP (x, i, j), from_cuid, to_insn, pnotes); + move_deaths (XVECEXP (x, i, j), maybe_kill_insn, from_cuid, + to_insn, pnotes); } else if (fmt[i] == 'e') - move_deaths (XEXP (x, i), from_cuid, to_insn, pnotes); + move_deaths (XEXP (x, i), maybe_kill_insn, from_cuid, to_insn, pnotes); } } @@ -10603,6 +11405,14 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) next_note = XEXP (note, 1); switch (REG_NOTE_KIND (note)) { + case REG_BR_PROB: + case REG_EXEC_COUNT: + /* Doesn't matter much where we put this, as long as it's somewhere. + It is preferable to keep these notes on branches, which is most + likely to be i3. */ + place = i3; + break; + case REG_UNUSED: /* Any clobbers for i3 may still exist, and so we must process REG_UNUSED notes from that insn. @@ -10647,6 +11457,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) case REG_EQUAL: case REG_EQUIV: case REG_NONNEG: + case REG_NOALIAS: /* These notes say something about results of an insn. We can only support them if they used to be on I3 in which case they remain on I3. Otherwise they are ignored. @@ -10749,9 +11560,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) special case. */ if (place == i3 && i2 != 0 && GET_CODE (XEXP (note, 0)) == REG - && reg_n_refs[REGNO (XEXP (note, 0))]== 2 + && REG_N_REFS (REGNO (XEXP (note, 0)))== 2 && reg_referenced_p (XEXP (note, 0), PATTERN (i2))) - reg_n_refs[REGNO (XEXP (note, 0))] = 3; + REG_N_REFS (REGNO (XEXP (note, 0))) = 3; if (place == 0) { @@ -10766,15 +11577,21 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) if (reg_set_p (XEXP (note, 0), PATTERN (tem))) { rtx set = single_set (tem); + rtx inner_dest = 0; + + if (set != 0) + for (inner_dest = SET_DEST (set); + GET_CODE (inner_dest) == STRICT_LOW_PART + || GET_CODE (inner_dest) == SUBREG + || GET_CODE (inner_dest) == ZERO_EXTRACT; + inner_dest = XEXP (inner_dest, 0)) + ; /* Verify that it was the set, and not a clobber that modified the register. */ if (set != 0 && ! side_effects_p (SET_SRC (set)) - && (rtx_equal_p (XEXP (note, 0), SET_DEST (set)) - || (GET_CODE (SET_DEST (set)) == SUBREG - && rtx_equal_p (XEXP (note, 0), - XEXP (SET_DEST (set), 0))))) + && rtx_equal_p (XEXP (note, 0), inner_dest)) { /* Move the notes and links of TEM elsewhere. This might delete other dead insns recursively. @@ -10791,6 +11608,21 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (tem) = 0; } + /* If the register is both set and used here, put the + REG_DEAD note here, but place a REG_UNUSED note + here too unless there already is one. */ + else if (reg_referenced_p (XEXP (note, 0), + PATTERN (tem))) + { + place = tem; + + if (! find_regno_note (tem, REG_UNUSED, + REGNO (XEXP (note, 0)))) + REG_NOTES (tem) + = gen_rtx_EXPR_LIST (REG_UNUSED, + XEXP (note, 0), + REG_NOTES (tem)); + } else { PUT_REG_NOTE_KIND (note, REG_UNUSED); @@ -10836,7 +11668,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) if (REG_NOTE_KIND (note) == REG_DEAD && place == 0 && tem != 0) { place - = emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (note, 0)), + = emit_insn_after (gen_rtx_USE (VOIDmode, XEXP (note, 0)), tem); /* If this insn was emitted between blocks, then update @@ -10847,13 +11679,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) } /* If the register is set or already dead at PLACE, we needn't do - anything with this note if it is still a REG_DEAD note. + anything with this note if it is still a REG_DEAD note. + We can here if it is set at all, not if is it totally replace, + which is what `dead_or_set_p' checks, so also check for it being + set partially. */ + - Note that we cannot use just `dead_or_set_p' here since we can - convert an assignment to a register into a bit-field assignment. - Therefore, we must also omit the note if the register is the - target of a bitfield assignment. */ - if (place && REG_NOTE_KIND (note) == REG_DEAD) { int regno = REGNO (XEXP (note, 0)); @@ -10895,7 +11726,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) if (! refers_to_regno_p (i, i + 1, PATTERN (place), 0) && ! find_regno_fusage (place, USE, i)) { - rtx piece = gen_rtx (REG, reg_raw_mode[i], i); + rtx piece = gen_rtx_REG (reg_raw_mode[i], i); rtx p; /* See if we already placed a USE note for this @@ -10914,12 +11745,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) if (p) { rtx use_insn - = emit_insn_before (gen_rtx (USE, VOIDmode, - piece), + = emit_insn_before (gen_rtx_USE (VOIDmode, + piece), p); REG_NOTES (use_insn) - = gen_rtx (EXPR_LIST, REG_DEAD, piece, - REG_NOTES (use_insn)); + = gen_rtx_EXPR_LIST (REG_DEAD, piece, + REG_NOTES (use_insn)); } all_used = 0; @@ -10942,7 +11773,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) for (i = regno; i < endregno; i++) { - rtx piece = gen_rtx (REG, reg_raw_mode[i], i); + rtx piece = gen_rtx_REG (reg_raw_mode[i], i); if ((reg_referenced_p (piece, PATTERN (place)) || (GET_CODE (place) == CALL_INSN @@ -10950,9 +11781,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) && ! dead_or_set_p (place, piece) && ! reg_bitfield_target_p (piece, PATTERN (place))) - REG_NOTES (place) = gen_rtx (EXPR_LIST, REG_DEAD, - piece, - REG_NOTES (place)); + REG_NOTES (place) + = gen_rtx_EXPR_LIST (REG_DEAD, + piece, REG_NOTES (place)); } place = 0; @@ -10975,17 +11806,19 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) else if ((REG_NOTE_KIND (note) == REG_DEAD || REG_NOTE_KIND (note) == REG_UNUSED) && GET_CODE (XEXP (note, 0)) == REG) - reg_n_deaths[REGNO (XEXP (note, 0))]--; + REG_N_DEATHS (REGNO (XEXP (note, 0)))--; if (place2) { if ((REG_NOTE_KIND (note) == REG_DEAD || REG_NOTE_KIND (note) == REG_UNUSED) && GET_CODE (XEXP (note, 0)) == REG) - reg_n_deaths[REGNO (XEXP (note, 0))]++; + REG_N_DEATHS (REGNO (XEXP (note, 0)))++; - REG_NOTES (place2) = gen_rtx (GET_CODE (note), REG_NOTE_KIND (note), - XEXP (note, 0), REG_NOTES (place2)); + REG_NOTES (place2) = gen_rtx_fmt_ee (GET_CODE (note), + REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (place2)); } } } @@ -11082,6 +11915,22 @@ distribute_links (links) } } +/* Compute INSN_CUID for INSN, which is an insn made by combine. */ + +static int +insn_cuid (insn) + rtx insn; +{ + while (insn != 0 && INSN_UID (insn) > max_uid_cuid + && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE) + insn = NEXT_INSN (insn); + + if (INSN_UID (insn) > max_uid_cuid) + abort (); + + return INSN_CUID (insn); +} + void dump_combine_stats (file) FILE *file; diff --git a/contrib/gcc/conditions.h b/contrib/gcc/conditions.h index c92226c..80d6047 100644 --- a/contrib/gcc/conditions.h +++ b/contrib/gcc/conditions.h @@ -85,6 +85,8 @@ extern CC_STATUS cc_status; /* This bit means that the current setting of the overflow flag is bogus and conditional jumps should pretend there is no overflow. */ +/* ??? Note that for most targets this macro is misnamed as it applies + to the carry flag, not the overflow flag. */ #define CC_NO_OVERFLOW 010 /* This bit means that what ought to be in the Z bit diff --git a/contrib/gcc/config.guess b/contrib/gcc/config.guess index 5508638..fd7602d 100755 --- a/contrib/gcc/config.guess +++ b/contrib/gcc/config.guess @@ -1,575 +1,4 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995 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 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner . -# The master version of this file is at the FSF in /home/gd/gnu/lib. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit system type (host/target name). -# -# Only a few systems have been added to this list; please add others -# (but try to keep the structure clean). -# - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 8/24/94.) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - alpha:OSF1:V*:*) - # After 1.2, OSF1 uses "V1.3" for uname -r. - echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'` - exit 0 ;; - alpha:OSF1:*:*) - # 1.2 uses "1.2" for uname -r. - echo alpha-dec-osf${UNAME_RELEASE} - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - amiga:NetBSD:*:*) - echo m68k-cbm-netbsd${UNAME_RELEASE} - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - Pyramid*:OSx*:*:*) - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - sun4*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - atari*:NetBSD:*:*) - echo m68k-atari-netbsd${UNAME_RELEASE} - exit 0 ;; - sun3*:NetBSD:*:*) - echo m68k-sun-netbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:NetBSD:*:*) - echo m68k-apple-netbsd${UNAME_RELEASE} - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - mips:*:4*:UMIPS) - echo mips-mips-riscos4sysv - exit 0 ;; - mips:*:5*:RISCos) - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ - -o ${TARGET_BINARY_INTERFACE}x = x ] ; then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i[34]86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:4) - if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=4.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[3478]??:HP-UX:*:*) - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/7?? | 9000/8?[79] ) HP_ARCH=hppa1.1 ;; - 9000/8?? ) HP_ARCH=hppa1.0 ;; - esac - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} - exit 0 ;; - CRAY*C90:*:*:*) - echo c90-cray-unicos${UNAME_RELEASE} - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; - hp3[0-9][05]:NetBSD:*:*) - echo m68k-hp-netbsd${UNAME_RELEASE} - exit 0 ;; - i[34]86:BSD/386:*:* | *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:NetBSD:*:*) - echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - *:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. - ld_help_string=`ld --help 2>&1` -# if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then -# echo "${UNAME_MACHINE}-unknown-linux" ; exit 0 - if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then - echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 - elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then - echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0 - elif test "${UNAME_MACHINE}" = "alpha" ; then - echo alpha-unknown-linux ; exit 0 - else - # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us - # useful --help. Gcc wants to distinguish between linuxoldld and linuxaout, - # and between different C library versions. - echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" - test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 - # Determine whether the default compiler is a.out or elf - cat >dummy.c < -main(argc, argv) -int argc; -char *argv[]; -{ -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-unknown-linux\n", argv[1]); -# else - printf ("%s-unknown-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-unknown-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-unknown-linuxaout\n", argv[1]); -#endif - return 0; -} -EOF - ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy - fi ;; -# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions -# are messed up and put the nodename in both sysname and nodename. - i[34]86:DYNIX/ptx:4*:*) - echo i386-sequent-sysv4 - exit 0 ;; - i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*) - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} - else - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - i[34]86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-unknown-sysv32 - fi - exit 0 ;; - Intel:Mach:3*:*) - echo i386-unknown-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - M680[234]0:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0) - uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3 && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m680[234]0:LynxOS:2.[23]*:*) - echo m68k-lynx-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - i[34]86:LynxOS:2.[23]*:*) - echo i386-lynx-lynxos${UNAME_RELEASE} - exit 0 ;; - TSUNAMI:LynxOS:2.[23]*:*) - echo sparc-lynx-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.[23]*:*) - echo rs6000-lynx-lynxos${UNAME_RELEASE} - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -cat >dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3"); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-unknown-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -#if !defined (ultrix) - printf ("vax-dec-bsd\n"); exit (0); -#else - printf ("vax-dec-ultrix\n"); exit (0); -#endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 -rm -f dummy.c dummy - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -#echo '(Unable to guess system type)' 1>&2 - -exit 1 +#!/bin/sh +# Use the top-level config.guess so that we don't have two of them. +guesssys=`echo $0 | sed 's|config.guess|../config.guess|'` +exec ${guesssys} "$@" diff --git a/contrib/gcc/config.in b/contrib/gcc/config.in new file mode 100644 index 0000000..b4e9898 --- /dev/null +++ b/contrib/gcc/config.in @@ -0,0 +1,202 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ +/* Define if printf supports "%p". */ +#undef HAVE_PRINTF_PTR + +/* Define if you want expensive run-time checks. */ +#undef ENABLE_CHECKING + +/* Define if your cpp understands the stringify operator. */ +#undef HAVE_CPP_STRINGIFY + +/* Define if your compiler understands volatile. */ +#undef HAVE_VOLATILE + +/* Define if your assembler supports specifying the maximum number + of bytes to skip when using the GAS .p2align command. */ +#undef HAVE_GAS_MAX_SKIP_P2ALIGN + +/* Define if your assembler supports .balign and .p2align. */ +#undef HAVE_GAS_BALIGN_AND_P2ALIGN + +/* Define if you have a working header file. */ +#undef HAVE_INTTYPES_H + +/* Whether malloc must be declared even if is included. */ +#undef NEED_DECLARATION_MALLOC + +/* Whether realloc must be declared even if is included. */ +#undef NEED_DECLARATION_REALLOC + +/* Whether calloc must be declared even if is included. */ +#undef NEED_DECLARATION_CALLOC + +/* Whether free must be declared even if is included. */ +#undef NEED_DECLARATION_FREE + +/* Whether bcopy must be declared even if is included. */ +#undef NEED_DECLARATION_BCOPY + +/* Whether bcmp must be declared even if is included. */ +#undef NEED_DECLARATION_BCMP + +/* Whether bzero must be declared even if is included. */ +#undef NEED_DECLARATION_BZERO + +/* Whether index must be declared even if is included. */ +#undef NEED_DECLARATION_INDEX + +/* Whether rindex must be declared even if is included. */ +#undef NEED_DECLARATION_RINDEX + +/* Whether getenv must be declared even if is included. */ +#undef NEED_DECLARATION_GETENV + +/* Whether atol must be declared even if is included. */ +#undef NEED_DECLARATION_ATOL + +/* Whether sbrk must be declared even if is included. */ +#undef NEED_DECLARATION_SBRK + +/* Whether abort must be declared even if is included. */ +#undef NEED_DECLARATION_ABORT + +/* Whether strerror must be declared even if is included. */ +#undef NEED_DECLARATION_STRERROR + +/* Whether getcwd must be declared even if is included. */ +#undef NEED_DECLARATION_GETCWD + +/* Whether getwd must be declared even if is included. */ +#undef NEED_DECLARATION_GETWD + +/* Whether getrlimit must be declared even if is included. */ +#undef NEED_DECLARATION_GETRLIMIT + +/* Whether setrlimit must be declared even if is included. */ +#undef NEED_DECLARATION_SETRLIMIT + +/* Define if you want expensive run-time checks. */ +#undef ENABLE_CHECKING + +/* Define if you don't have vprintf but do have _doprnt. */ +#undef HAVE_DOPRNT + +/* Define if you have the vprintf function. */ +#undef HAVE_VPRINTF + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if `sys_siglist' is declared by . */ +#undef SYS_SIGLIST_DECLARED + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if you have the atoll function. */ +#undef HAVE_ATOLL + +/* Define if you have the atoq function. */ +#undef HAVE_ATOQ + +/* Define if you have the bcmp function. */ +#undef HAVE_BCMP + +/* Define if you have the bcopy function. */ +#undef HAVE_BCOPY + +/* Define if you have the bsearch function. */ +#undef HAVE_BSEARCH + +/* Define if you have the bzero function. */ +#undef HAVE_BZERO + +/* Define if you have the getrlimit function. */ +#undef HAVE_GETRLIMIT + +/* Define if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if you have the index function. */ +#undef HAVE_INDEX + +/* Define if you have the isascii function. */ +#undef HAVE_ISASCII + +/* Define if you have the kill function. */ +#undef HAVE_KILL + +/* Define if you have the popen function. */ +#undef HAVE_POPEN + +/* 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 setrlimit function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* 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 strtoul function. */ +#undef HAVE_STRTOUL + +/* Define if you have the sysconf function. */ +#undef HAVE_SYSCONF + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_STAB_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIMES_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WAIT_H diff --git a/contrib/gcc/config.sub b/contrib/gcc/config.sub index 9bb45e9..b491c9f 100755 --- a/contrib/gcc/config.sub +++ b/contrib/gcc/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script, version 1.1. -# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc. # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. +# can handle that machine. It does not imply ALL GNU software can. # # 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 @@ -41,6 +41,8 @@ # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. if [ x$1 = x ] @@ -62,7 +64,7 @@ case $1 in ;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in @@ -91,38 +93,43 @@ case $os in -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp ) + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) os= basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos @@ -133,35 +140,52 @@ case $os in -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; + -psos*) + os=-psos + ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. - tahoe | i[3456]86 | i860 | m68k | m68000 | m88k | ns32k | arm \ - | arme[lb] | pyramid \ - | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \ - | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \ - | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \ - | pdp11 | mips64el | mips64orion | mips64orionel \ - | sparc) + tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 \ + | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \ + | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ + | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ + | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ + | mipstx39 | mipstx39el \ + | sparc | sparclet | sparclite | sparc64 | v850) basic_machine=$basic_machine-unknown ;; + thumb | thumbel) + basic_machine=$basic_machine-unknown + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[34567]86) + basic_machine=$basic_machine-pc + ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. - vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \ - | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \ - | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ - | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \ - | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \ - | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-*) + vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ + | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \ + | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ + | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mipstx39-* | mipstx39el-* \ + | f301-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -188,9 +212,9 @@ case $basic_machine in amiga | amiga-*) basic_machine=m68k-cbm ;; - amigados) + amigaos | amigados) basic_machine=m68k-cbm - os=-amigados + os=-amigaos ;; amigaunix | amix) basic_machine=m68k-cbm @@ -200,6 +224,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-sysv ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; balance) basic_machine=ns32k-sequent os=-dynix @@ -232,6 +260,10 @@ case $basic_machine in basic_machine=cray2-cray os=-unicos ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; crds | unos) basic_machine=m68k-crds ;; @@ -307,31 +339,49 @@ case $basic_machine in hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; - hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + hp9k6[0-9][0-9] | hp6[0-9][0-9] ) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9] ) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9] ) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | \ + hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893 ) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679] ) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; + hppa-next) + os=-nextstep3 + ;; i370-ibm* | ibm*) basic_machine=i370-ibm os=-mvs ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? - i[3456]86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; - i[3456]86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; - i[3456]86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; - i[3456]86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; iris | iris4d) @@ -362,6 +412,14 @@ case $basic_machine in miniframe) basic_machine=m68000-convergent ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; @@ -429,21 +487,23 @@ case $basic_machine in pc532 | pc532-*) basic_machine=ns32k-pc532 ;; - pentium | p5 | p6) - # We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium - basic_machine=i586-intel + pentium | p5 | k5 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | k6 | 6x86) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc ;; - pentium-* | p5-* | p6-*) - # We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium + pentium-* | p5-* | k5-* | nexen-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - k5) - # We don't have specific support for AMD's K5 yet, so just call it a Pentium - basic_machine=i586-amd + pentiumpro-* | p6-* | k6-* | 6x86-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - nexen) - # We don't have specific support for Nexgen yet, so just call it a Pentium - basic_machine=i586-nexgen + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -527,6 +587,12 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; tower | tower-32) basic_machine=m68k-ncr ;; @@ -546,6 +612,9 @@ case $basic_machine in basic_machine=vax-dec os=-vms ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -573,7 +642,11 @@ case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. mips) - basic_machine=mips-mips + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi ;; romp) basic_machine=romp-ibm @@ -625,6 +698,8 @@ esac if [ x"$os" != x"" ] then case $os in + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` @@ -632,28 +707,37 @@ case $os in -solaris) os=-solaris2 ;; - -unixware* | svr4*) + -svr4*) os=-sysv4 ;; + -unixware*) + os=-sysv4.2uw + ;; -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux|'` + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[345]* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \ - | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \ - | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* ) + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* ) # Remember, each alternative MUST END IN *, to match a version number. ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; @@ -678,6 +762,9 @@ case $os in -ctix* | -uts*) os=-sysv ;; + -ns2 ) + os=-nextstep2 + ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` @@ -771,7 +858,7 @@ case $basic_machine in os=-sysv ;; *-cbm) - os=-amigados + os=-amigaos ;; *-dg) os=-dgux @@ -785,6 +872,9 @@ case $basic_machine in m88k-omron*) os=-luna ;; + *-next ) + os=-nextstep + ;; *-sequent) os=-ptx ;; @@ -818,6 +908,12 @@ case $basic_machine in *-masscomp) os=-rtu ;; + f301-fujitsu) + os=-uxpv + ;; + *-be) + os=-beos + ;; *) os=-none ;; @@ -836,9 +932,6 @@ case $basic_machine in -sunos*) vendor=sun ;; - -lynxos*) - vendor=lynx - ;; -aix*) vendor=ibm ;; @@ -866,9 +959,15 @@ case $basic_machine in -ptx*) vendor=sequent ;; - -vxworks*) + -vxsim* | -vxworks*) vendor=wrs ;; + -aux*) + vendor=apple + ;; + -beos*) + vendor=be + ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c index b77dc14..0b72289 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, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -20,8 +20,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include #include "config.h" +#include "system.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" @@ -34,9 +34,44 @@ Boston, MA 02111-1307, USA. */ #include "flags.h" #include "recog.h" #include "reload.h" +#include "tree.h" #include "expr.h" #include "obstack.h" -#include "tree.h" +#include "except.h" +#include "function.h" +#include "toplev.h" + +/* External data. */ +extern char *version_string; +extern int rtx_equal_function_value_matters; + +/* Specify which cpu to schedule for. */ + +enum processor_type alpha_cpu; +static char* const alpha_cpu_name[] = +{ + "ev4", "ev5", "ev6" +}; + +/* Specify how accurate floating-point traps need to be. */ + +enum alpha_trap_precision alpha_tp; + +/* Specify the floating-point rounding mode. */ + +enum alpha_fp_rounding_mode alpha_fprm; + +/* Specify which things cause traps. */ + +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= */ /* Save information from a "cmpxx" operation until the branch or scc is emitted. */ @@ -44,26 +79,226 @@ Boston, MA 02111-1307, USA. */ rtx alpha_compare_op0, alpha_compare_op1; int alpha_compare_fp_p; -/* Save the name of the current function as used by the assembler. This - is used by the epilogue. */ - -char *alpha_function_name; - /* Non-zero if inside of a function, because the Alpha asm can't handle .files inside of functions. */ static int inside_function = FALSE; -/* Nonzero if the current function needs gp. */ +/* If non-null, this rtx holds the return address for the function. */ -int alpha_function_needs_gp; +static rtx alpha_return_addr_rtx; -extern char *version_string; -extern int rtx_equal_function_value_matters; +/* The number of cycles of latency we should assume on memory reads. */ + +int alpha_memory_latency = 3; + +/* Whether the function needs the GP. */ + +static int alpha_function_needs_gp; /* Declarations of static functions. */ -static void alpha_set_memflags_1 PROTO((rtx, int, int, int)); -static void add_long_const PROTO((FILE *, HOST_WIDE_INT, int, int, int)); +static void alpha_set_memflags_1 + PROTO((rtx, int, int, int)); +static rtx alpha_emit_set_const_1 + PROTO((rtx, enum machine_mode, HOST_WIDE_INT, int)); +static void alpha_expand_unaligned_load_words + PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); +static void alpha_expand_unaligned_store_words + PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); +static void alpha_sa_mask + PROTO((unsigned long *imaskP, unsigned long *fmaskP)); +static int alpha_does_function_need_gp + PROTO((void)); + + +/* Get the number of args of a function in one of two ways. */ +#ifdef OPEN_VMS +#define NUM_ARGS current_function_args_info.num_args +#else +#define NUM_ARGS current_function_args_info +#endif + +#define REG_PV 27 +#define REG_RA 26 + +/* Parse target option strings. */ + +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; + + if (TARGET_IEEE) + { + alpha_tp = ALPHA_TP_INSN; + alpha_fptm = ALPHA_FPTM_SU; + } + + if (TARGET_IEEE_WITH_INEXACT) + { + alpha_tp = ALPHA_TP_INSN; + alpha_fptm = ALPHA_FPTM_SUI; + } + + if (alpha_tp_string) + { + if (! strcmp (alpha_tp_string, "p")) + alpha_tp = ALPHA_TP_PROG; + else if (! strcmp (alpha_tp_string, "f")) + alpha_tp = ALPHA_TP_FUNC; + else if (! strcmp (alpha_tp_string, "i")) + alpha_tp = ALPHA_TP_INSN; + else + error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string); + } + + if (alpha_fprm_string) + { + if (! strcmp (alpha_fprm_string, "n")) + alpha_fprm = ALPHA_FPRM_NORM; + else if (! strcmp (alpha_fprm_string, "m")) + alpha_fprm = ALPHA_FPRM_MINF; + else if (! strcmp (alpha_fprm_string, "c")) + alpha_fprm = ALPHA_FPRM_CHOP; + else if (! strcmp (alpha_fprm_string,"d")) + alpha_fprm = ALPHA_FPRM_DYN; + else + error ("bad value `%s' for -mfp-rounding-mode switch", + alpha_fprm_string); + } + + if (alpha_fptm_string) + { + if (strcmp (alpha_fptm_string, "n") == 0) + alpha_fptm = ALPHA_FPTM_N; + else if (strcmp (alpha_fptm_string, "u") == 0) + alpha_fptm = ALPHA_FPTM_U; + else if (strcmp (alpha_fptm_string, "su") == 0) + alpha_fptm = ALPHA_FPTM_SU; + else if (strcmp (alpha_fptm_string, "sui") == 0) + alpha_fptm = ALPHA_FPTM_SUI; + else + error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string); + } + + /* Do some sanity checks on the above option. */ + + if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI) + && alpha_tp != ALPHA_TP_INSN) + { + warning ("fp software completion requires -mtrap-precision=i"); + alpha_tp = ALPHA_TP_INSN; + } + + if (TARGET_FLOAT_VAX) + { + if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN) + { + warning ("rounding mode not supported for VAX floats"); + alpha_fprm = ALPHA_FPRM_NORM; + } + if (alpha_fptm == ALPHA_FPTM_SUI) + { + warning ("trap mode not supported for VAX floats"); + alpha_fptm = ALPHA_FPTM_SU; + } + } + + { + char *end; + int lat; + + if (!alpha_mlat_string) + alpha_mlat_string = "L1"; + + if (isdigit (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]) + && alpha_mlat_string[2] == '\0') + { + static int const cache_latency[][4] = + { + { 3, 30, -1 }, /* ev4 -- Bcache is a guess */ + { 2, 12, 38 }, /* ev5 -- Bcache from PC164 LMbench numbers */ + { 3, 13, -1 }, /* ev6 -- Ho hum, doesn't exist yet */ + }; + + lat = alpha_mlat_string[1] - '0'; + if (lat < 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1) + { + warning ("L%d cache latency unknown for %s", + lat, alpha_cpu_name[alpha_cpu]); + lat = 3; + } + else + lat = cache_latency[alpha_cpu][lat-1]; + } + else if (! strcmp (alpha_mlat_string, "main")) + { + /* Most current memories have about 370ns latency. This is + a reasonable guess for a fast cpu. */ + lat = 150; + } + else + { + warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string); + lat = 3; + } + + alpha_memory_latency = lat; + } + + /* Default the definition of "small data" to 8 bytes. */ + if (!g_switch_set) + g_switch_value = 8; +} /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ @@ -102,6 +337,7 @@ 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)); } @@ -115,6 +351,7 @@ 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)); } @@ -123,10 +360,11 @@ reg_or_8bit_operand (op, mode) int cint8_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { - return (GET_CODE (op) == CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100); + return ((GET_CODE (op) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100) + || GET_CODE (op) == CONSTANT_P_RTX); } /* Return 1 if the operand is a valid second operand to an add insn. */ @@ -140,6 +378,8 @@ add_operand (op, mode) 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; return register_operand (op, mode); } @@ -155,6 +395,8 @@ sext_add_operand (op, 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 register_operand (op, mode); } @@ -164,7 +406,7 @@ sext_add_operand (op, mode) int const48_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return (GET_CODE (op) == CONST_INT && (INTVAL (op) == 4 || INTVAL (op) == 8)); @@ -185,6 +427,8 @@ 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); } @@ -199,6 +443,8 @@ 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); } @@ -209,10 +455,11 @@ or_operand (op, mode) int mode_width_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == 8 || INTVAL (op) == 16 || INTVAL (op) == 32)); + && (INTVAL (op) == 8 || INTVAL (op) == 16 + || INTVAL (op) == 32 || INTVAL (op) == 64)); } /* Return 1 if OP is a constant that is the width of an integral machine mode @@ -221,18 +468,24 @@ mode_width_operand (op, mode) int mode_mask_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { #if HOST_BITS_PER_WIDE_INT == 32 if (GET_CODE (op) == CONST_DOUBLE) - return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == -1; + return (CONST_DOUBLE_LOW (op) == -1 + && (CONST_DOUBLE_HIGH (op) == -1 + || CONST_DOUBLE_HIGH (op) == 0)); +#else + if (GET_CODE (op) == CONST_DOUBLE) + return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0); #endif return (GET_CODE (op) == CONST_INT && (INTVAL (op) == 0xff || INTVAL (op) == 0xffff -#if HOST_BITS_PER_WIDE_INT == 64 || INTVAL (op) == 0xffffffff +#if HOST_BITS_PER_WIDE_INT == 64 + || INTVAL (op) == 0xffffffffffffffff #endif )); } @@ -242,7 +495,7 @@ mode_mask_operand (op, mode) int mul8_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return (GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (op) < 64 @@ -270,6 +523,18 @@ reg_or_fp0_operand (op, mode) return fp0_operand (op, mode) || register_operand (op, mode); } +/* Return 1 if OP is a hard floating-point register. */ + +int +hard_fp_register_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + return ((GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS) + || (GET_CODE (op) == SUBREG + && hard_fp_register_operand (SUBREG_REG (op), mode))); +} + /* Return 1 if OP is a register or a constant integer. */ @@ -278,7 +543,9 @@ reg_or_cint_operand (op, mode) register rtx op; enum machine_mode mode; { - return GET_CODE (op) == CONST_INT || register_operand (op, mode); + return (GET_CODE (op) == CONST_INT + || GET_CODE (op) == CONSTANT_P_RTX + || register_operand (op, mode)); } /* Return 1 if OP is something that can be reloaded into a register; @@ -294,12 +561,15 @@ 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 REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: + case SYMBOL_REF: case CONST: case CONSTANT_P_RTX: return 1; case SUBREG: return some_operand (SUBREG_REG (op), VOIDmode); + + default: + break; } return 0; @@ -323,7 +593,7 @@ input_operand (op, mode) case LABEL_REF: case SYMBOL_REF: case CONST: - /* This handles both the Windows/NT and OSF cases. */ + /* This handles both the Windows/NT and OSF cases. */ return mode == ptr_mode || mode == DImode; case REG: @@ -334,13 +604,18 @@ input_operand (op, mode) return 1; /* ... fall through ... */ case MEM: - return mode != HImode && mode != QImode && general_operand (op, mode); + return ((TARGET_BWX || (mode != HImode && mode != QImode)) + && general_operand (op, mode)); case CONST_DOUBLE: 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); + + default: + break; } return 0; @@ -352,7 +627,7 @@ input_operand (op, mode) int current_file_function_operand (op, mode) rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return (GET_CODE (op) == SYMBOL_REF && ! profile_flag && ! profile_block_flag @@ -370,7 +645,9 @@ call_operand (op, mode) if (mode != Pmode) return 0; - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG); + return (GET_CODE (op) == SYMBOL_REF + || (GET_CODE (op) == REG + && (TARGET_OPEN_VMS || TARGET_WINDOWS_NT || REGNO (op) == 27))); } /* Return 1 if OP is a valid Alpha comparison operator. Here we know which @@ -390,17 +667,37 @@ alpha_comparison_operator (op, mode) || (mode == DImode && (code == LEU || code == LTU))); } +/* Return 1 if OP is a valid Alpha swapped comparison operator. */ + +int +alpha_swapped_comparison_operator (op, mode) + register rtx op; + enum machine_mode mode; +{ + enum rtx_code code = GET_CODE (op); + + if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<') + return 0; + + code = swap_condition (code); + return (code == EQ || code == LE || code == LT + || (mode == DImode && (code == LEU || code == LTU))); +} + /* Return 1 if OP is a signed comparison operation. */ int signed_comparison_operator (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { switch (GET_CODE (op)) { case EQ: case NE: case LE: case LT: case GE: case GT: return 1; + + default: + break; } return 0; @@ -411,12 +708,15 @@ signed_comparison_operator (op, mode) int divmod_operator (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { switch (GET_CODE (op)) { case DIV: case MOD: case UDIV: case UMOD: return 1; + + default: + break; } return 0; @@ -459,10 +759,7 @@ aligned_memory_operand (op, mode) op = XEXP (op, 0); return (GET_CODE (op) == REG - && (REGNO (op) == STACK_POINTER_REGNUM - || op == hard_frame_pointer_rtx - || (REGNO (op) >= FIRST_VIRTUAL_REGISTER - && REGNO (op) <= LAST_VIRTUAL_REGISTER))); + && REGNO_POINTER_ALIGN (REGNO (op)) >= 4); } /* Similar, but return 1 if OP is a MEM which is not alignable. */ @@ -496,10 +793,17 @@ unaligned_memory_operand (op, mode) op = XEXP (op, 0); return (GET_CODE (op) != REG - || (REGNO (op) != STACK_POINTER_REGNUM - && op != hard_frame_pointer_rtx - && (REGNO (op) < FIRST_VIRTUAL_REGISTER - || REGNO (op) > LAST_VIRTUAL_REGISTER))); + || REGNO_POINTER_ALIGN (REGNO (op)) < 4); +} + +/* Return 1 if OP is either a register or an unaligned memory location. */ + +int +reg_or_unaligned_mem_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return register_operand (op, mode) || unaligned_memory_operand (op, mode); } /* Return 1 if OP is any memory location. During reload a pseudo matches. */ @@ -507,7 +811,7 @@ unaligned_memory_operand (op, mode) int any_memory_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return (GET_CODE (op) == MEM || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) @@ -518,6 +822,17 @@ any_memory_operand (op, mode) && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)); } +/* Return 1 if this function can directly return via $26. */ + +int +direct_return () +{ + return (! TARGET_OPEN_VMS && reload_completed && alpha_sa_size () == 0 + && get_frame_size () == 0 + && current_function_outgoing_args_size == 0 + && current_function_pretend_args_size == 0); +} + /* REF is an alignable memory location. Place an aligned SImode reference into *PALIGNED_MEM and the number of bits to shift into *PBITNUM. */ @@ -551,7 +866,7 @@ get_aligned_mem (ref, paligned_mem, pbitnum) if (GET_CODE (base) == PLUS) offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); - *paligned_mem = gen_rtx (MEM, SImode, + *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); @@ -560,11 +875,13 @@ get_aligned_mem (ref, paligned_mem, pbitnum) *pbitnum = GEN_INT ((offset & 3) * 8); } -/* Similar, but just get the address. Handle the two reload cases. */ +/* Similar, but just get the address. Handle the two reload cases. + Add EXTRA_OFFSET to the address we return. */ rtx -get_unaligned_address (ref) +get_unaligned_address (ref, extra_offset) rtx ref; + int extra_offset; { rtx base; HOST_WIDE_INT offset = 0; @@ -590,7 +907,7 @@ get_unaligned_address (ref) if (GET_CODE (base) == PLUS) offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); - return plus_constant (base, offset); + return plus_constant (base, offset + extra_offset); } /* Subfunction of the following function. Update the flags of any MEM @@ -629,6 +946,9 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) MEM_VOLATILE_P (x) = volatile_p; RTX_UNCHANGING_P (x) = unchanging_p; break; + + default: + break; } } @@ -669,6 +989,26 @@ alpha_emit_set_const (target, mode, c, n) HOST_WIDE_INT c; int n; { + rtx pat; + int i; + + /* Try 1 insn, then 2, then up to N. */ + for (i = 1; i <= n; i++) + if ((pat = alpha_emit_set_const_1 (target, mode, c, i)) != 0) + return pat; + + return 0; +} + +/* Internal routine for the above to check for N or below insns. */ + +static rtx +alpha_emit_set_const_1 (target, mode, c, n) + rtx target; + enum machine_mode mode; + HOST_WIDE_INT c; + int n; +{ HOST_WIDE_INT new = c; int i, bits; /* Use a pseudo if highly optimizing and still generating RTL. */ @@ -688,12 +1028,10 @@ alpha_emit_set_const (target, mode, c, n) /* If this is a sign-extended 32-bit constant, we can do this in at most three insns, so do it if we have enough insns left. We always have - a sign-extended 32-bit constant when compiling on a narrow machine. - Note that we cannot handle the constant 0x80000000. */ + a sign-extended 32-bit constant when compiling on a narrow machine. */ - if ((HOST_BITS_PER_WIDE_INT != 64 - || c >> 31 == -1 || c >> 31 == 0) - && c != 0x80000000U) + if (HOST_BITS_PER_WIDE_INT != 64 + || c >> 31 == -1 || c >> 31 == 0) { HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); HOST_WIDE_INT tmp1 = c - low; @@ -712,13 +1050,19 @@ alpha_emit_set_const (target, mode, c, n) } if (c == low || (low == 0 && extra == 0)) - return copy_to_suggested_reg (GEN_INT (c), target, mode); - else if (n >= 2 + (extra != 0) - /* We can't do this when SImode if HIGH required adjustment. - This is because the code relies on an implicit overflow - which is invisible to the RTL. We can thus get incorrect - code if the two ldah instructions are combined. */ - && ! (mode == SImode && extra != 0)) + { + /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode) + but that meant that we can't handle INT_MIN on 32-bit machines + (like NT/Alpha), because we recurse indefinitely through + emit_move_insn to gen_movdi. So instead, since we know exactly + what we want, create it explicitly. */ + + if (target == NULL) + target = gen_reg_rtx (mode); + emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c))); + return target; + } + else if (n >= 2 + (extra != 0)) { temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode); @@ -795,9 +1139,11 @@ alpha_emit_set_const (target, mode, c, n) /* Now try high-order zero bits. Here we try the shifted-in bits as all zero and all ones. Be careful to avoid shifting outside the mode and to avoid shifting outside the host wide int size. */ + /* On narrow hosts, don't shift a 1 into the high bit, since we'll + confuse the recursive call and set all of the high 32 bits. */ if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) - - floor_log2 (c) - 1)) > 0) + - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0) for (; bits > 0; bits--) if ((temp = alpha_emit_set_const (subtarget, mode, c << bits, i)) != 0 @@ -829,128 +1175,1473 @@ alpha_emit_set_const (target, mode, c, n) return 0; } - -/* 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 -alpha_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; -{ - rtx set; - - /* If the dependence is an anti-dependence, there is no cost. For an - output dependence, there is sometimes a cost, but it doesn't seem - worth handling those few cases. */ - - if (REG_NOTE_KIND (link) != 0) - return 0; - - /* If INSN is a store insn and DEP_INSN is setting the data being stored, - we can sometimes lower the cost. */ - - if (recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_ST - && (set = single_set (dep_insn)) != 0 - && GET_CODE (PATTERN (insn)) == SET - && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) - switch (get_attr_type (dep_insn)) - { - case TYPE_LD: - /* No savings here. */ - return cost; - - case TYPE_IMULL: - case TYPE_IMULQ: - /* In these cases, we save one cycle. */ - return cost - 2; - - default: - /* In all other cases, we save two cycles. */ - return MAX (0, cost - 4); - } - /* Another case that needs adjustment is an arithmetic or logical - operation. It's cost is usually one cycle, but we default it to - two in the MD file. The only case that it is actually two is - for the address in loads and stores. */ - - if (recog_memoized (dep_insn) >= 0 - && get_attr_type (dep_insn) == TYPE_IADDLOG) - switch (get_attr_type (insn)) - { - case TYPE_LD: - case TYPE_ST: - return cost; +#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. */ - default: - return 2; - } +rtx +alpha_emit_set_long_const (target, c) + rtx target; + HOST_WIDE_INT c; +{ + /* 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(); + + /* 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); + else + r1 = expand_binop (DImode, add_optab, GEN_INT (d3), GEN_INT (d4), + subtarget, 0, OPTAB_WIDEN); - /* The final case is when a compare feeds into an integer branch. The cost - is only one cycle in that case. */ + /* Shift it into place */ + r2 = expand_binop (DImode, ashl_optab, r1, GEN_INT (32), + subtarget, 0, OPTAB_WIDEN); - if (recog_memoized (dep_insn) >= 0 - && get_attr_type (dep_insn) == TYPE_ICMP - && recog_memoized (insn) >= 0 - && get_attr_type (insn) == TYPE_IBR) - return 2; + 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); + } - /* Otherwise, return the default cost. */ + if (subtarget == 0) + r1 = copy_to_suggested_reg(r1, target, DImode); - return cost; + return r1; } - -/* Print an operand. Recognize special options, documented below. */ +#endif /* HOST_BITS_PER_WIDE_INT == 64 */ -void -print_operand (file, x, code) - FILE *file; - rtx x; - char code; +/* Generate the comparison for a conditional branch. */ + +rtx +alpha_emit_conditional_branch (code) + enum rtx_code code; { - int i; + enum rtx_code cmp_code, branch_code; + enum machine_mode cmp_mode, branch_mode = VOIDmode; + rtx op0 = alpha_compare_op0, op1 = alpha_compare_op1; + rtx tem; + /* The general case: fold the comparison code to the types of compares + that we have, choosing the branch as necessary. */ switch (code) { - case 'r': - /* If this operand is the constant zero, write it as "$31". */ - if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names[REGNO (x)]); - else if (x == CONST0_RTX (GET_MODE (x))) - fprintf (file, "$31"); - else - output_operand_lossage ("invalid %%r value"); + case EQ: case LE: case LT: case LEU: case LTU: + /* We have these compares: */ + cmp_code = code, branch_code = NE; + break; + case NE: + /* This must be reversed. */ + cmp_code = EQ, branch_code = EQ; break; - case 'R': - /* Similar, but for floating-point. */ - if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names[REGNO (x)]); - else if (x == CONST0_RTX (GET_MODE (x))) - fprintf (file, "$f31"); + case GE: case GT: case GEU: case GTU: + /* For FP, we swap them, for INT, we reverse them. */ + if (alpha_compare_fp_p) + { + cmp_code = swap_condition (code); + branch_code = NE; + tem = op0, op0 = op1, op1 = tem; + } else - output_operand_lossage ("invalid %%R value"); - + { + cmp_code = reverse_condition (code); + branch_code = EQ; + } break; - case 'N': - /* Write the 1's complement of a constant. */ - if (GET_CODE (x) != CONST_INT) - output_operand_lossage ("invalid %%N value"); + default: + abort (); + } - fprintf (file, "%ld", ~ INTVAL (x)); - break; + if (alpha_compare_fp_p) + { + cmp_mode = DFmode; + if (flag_fast_math) + { + /* When we are not as concerned about non-finite values, and we + are comparing against zero, we can branch directly. */ + if (op1 == CONST0_RTX (DFmode)) + cmp_code = NIL, branch_code = code; + else if (op0 == CONST0_RTX (DFmode)) + { + /* Undo the swap we probably did just above. */ + tem = op0, op0 = op1, op1 = tem; + branch_code = swap_condition (cmp_code); + cmp_code = NIL; + } + } + else + { + /* ??? We mark the the branch mode to be CCmode to prevent the + compare and branch from being combined, since the compare + insn follows IEEE rules that the branch does not. */ + branch_mode = CCmode; + } + } + else + { + cmp_mode = DImode; + + /* The following optimizations are only for signed compares. */ + if (code != LEU && code != LTU && code != GEU && code != GTU) + { + /* Whee. Compare and branch against 0 directly. */ + if (op1 == const0_rtx) + cmp_code = NIL, branch_code = code; + + /* We want to use cmpcc/bcc when we can, since there is a zero delay + bypass between logicals and br/cmov on EV5. But we don't want to + force valid immediate constants into registers needlessly. */ + else if (GET_CODE (op1) == CONST_INT) + { + HOST_WIDE_INT v = INTVAL (op1), n = -v; + + if (! CONST_OK_FOR_LETTER_P (v, 'I') + && (CONST_OK_FOR_LETTER_P (n, 'K') + || CONST_OK_FOR_LETTER_P (n, 'L'))) + { + cmp_code = PLUS, branch_code = code; + op1 = GEN_INT (n); + } + } + } + } + + /* Force op0 into a register. */ + if (GET_CODE (op0) != REG) + op0 = force_reg (cmp_mode, op0); + + /* Emit an initial compare instruction, if necessary. */ + tem = op0; + if (cmp_code != NIL) + { + tem = gen_reg_rtx (cmp_mode); + emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1)); + } + + /* Return the branch comparison. */ + return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode)); +} + + +/* Rewrite a comparison against zero CMP of the form + (CODE (cc0) (const_int 0)) so it can be written validly in + a conditional move (if_then_else CMP ...). + If both of the operands that set cc0 are non-zero we must emit + an insn to perform the compare (it can't be done within + the conditional move). */ +rtx +alpha_emit_conditional_move (cmp, mode) + rtx cmp; + enum machine_mode mode; +{ + enum rtx_code code = GET_CODE (cmp); + enum rtx_code cmov_code = NE; + rtx op0 = alpha_compare_op0; + rtx op1 = alpha_compare_op1; + enum machine_mode cmp_mode + = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0)); + enum machine_mode cmp_op_mode = alpha_compare_fp_p ? DFmode : DImode; + enum machine_mode cmov_mode = VOIDmode; + rtx tem; + + if (alpha_compare_fp_p != FLOAT_MODE_P (mode)) + return 0; + + /* We may be able to use a conditional move directly. + This avoids emitting spurious compares. */ + if (signed_comparison_operator (cmp, cmp_op_mode) + && (!alpha_compare_fp_p || flag_fast_math) + && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode))) + return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); + + /* We can't put the comparison insides a conditional move; + emit a compare instruction and put that inside the + conditional move. Make sure we emit only comparisons we have; + swap or reverse as necessary. */ + + switch (code) + { + case EQ: case LE: case LT: case LEU: case LTU: + /* We have these compares: */ + break; + + case NE: + /* This must be reversed. */ + code = reverse_condition (code); + cmov_code = EQ; + break; + + case GE: case GT: case GEU: case GTU: + /* These must be swapped. Make sure the new first operand is in + a register. */ + code = swap_condition (code); + tem = op0, op0 = op1, op1 = tem; + op0 = force_reg (cmp_mode, op0); + break; + + default: + abort (); + } + + /* ??? We mark the 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) + cmov_mode = CCmode; + + tem = gen_reg_rtx (cmp_op_mode); + emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1)); + return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode)); +} + +/* Use ext[wlq][lh] as the Architecture Handbook describes for extracting + unaligned data: + + unsigned: signed: + word: ldq_u r1,X(r11) ldq_u r1,X(r11) + ldq_u r2,X+1(r11) ldq_u r2,X+1(r11) + lda r3,X(r11) lda r3,X+2(r11) + extwl r1,r3,r1 extql r1,r3,r1 + extwh r2,r3,r2 extqh r2,r3,r2 + or r1.r2.r1 or r1,r2,r1 + sra r1,48,r1 + + long: ldq_u r1,X(r11) ldq_u r1,X(r11) + ldq_u r2,X+3(r11) ldq_u r2,X+3(r11) + lda r3,X(r11) lda r3,X(r11) + extll r1,r3,r1 extll r1,r3,r1 + extlh r2,r3,r2 extlh r2,r3,r2 + or r1.r2.r1 addl r1,r2,r1 + + quad: ldq_u r1,X(r11) + ldq_u r2,X+7(r11) + lda r3,X(r11) + extql r1,r3,r1 + extqh r2,r3,r2 + or r1.r2.r1 +*/ + +void +alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) + rtx tgt, mem; + HOST_WIDE_INT size, ofs; + int sign; +{ + rtx meml, memh, addr, extl, exth; + enum machine_mode mode; + + meml = gen_reg_rtx (DImode); + memh = gen_reg_rtx (DImode); + addr = gen_reg_rtx (DImode); + extl = gen_reg_rtx (DImode); + exth = gen_reg_rtx (DImode); + + emit_move_insn (meml, + change_address (mem, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP (mem, 0), + ofs), + GEN_INT (-8)))); + + emit_move_insn (memh, + change_address (mem, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP (mem, 0), + ofs + size - 1), + GEN_INT (-8)))); + + if (sign && size == 2) + { + emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs+2)); + + emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr)); + emit_insn (gen_extqh (exth, memh, addr)); + + /* We must use tgt here for the target. Alpha-vms port fails if we use + addr for the target, because addr is marked as a pointer and combine + knows that pointers are always sign-extended 32 bit values. */ + addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN); + addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48), + addr, 1, OPTAB_WIDEN); + } + else + { + emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs)); + emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr)); + switch (size) + { + case 2: + emit_insn (gen_extwh (exth, memh, addr)); + mode = HImode; + break; + + case 4: + emit_insn (gen_extlh (exth, memh, addr)); + mode = SImode; + break; + + case 8: + emit_insn (gen_extqh (exth, memh, addr)); + mode = DImode; + break; + } + + addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl), + gen_lowpart (mode, exth), gen_lowpart (mode, tgt), + sign, OPTAB_WIDEN); + } + + if (addr != tgt) + emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr)); +} + +/* Similarly, use ins and msk instructions to perform unaligned stores. */ + +void +alpha_expand_unaligned_store (dst, src, size, ofs) + rtx dst, src; + HOST_WIDE_INT size, ofs; +{ + rtx dstl, dsth, addr, insl, insh, meml, memh; + + dstl = gen_reg_rtx (DImode); + dsth = gen_reg_rtx (DImode); + insl = gen_reg_rtx (DImode); + insh = gen_reg_rtx (DImode); + + meml = change_address (dst, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP (dst, 0), ofs), + GEN_INT (-8))); + memh = change_address (dst, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP (dst, 0), + ofs+size-1), + GEN_INT (-8))); + + emit_move_insn (dsth, memh); + emit_move_insn (dstl, meml); + addr = copy_addr_to_reg (plus_constant (XEXP (dst, 0), ofs)); + + if (src != const0_rtx) + { + emit_insn (gen_insxh (insh, gen_lowpart (DImode, src), + GEN_INT (size*8), addr)); + + switch (size) + { + case 2: + emit_insn (gen_inswl (insl, gen_lowpart (HImode, src), addr)); + break; + case 4: + emit_insn (gen_insll (insl, gen_lowpart (SImode, src), addr)); + break; + case 8: + emit_insn (gen_insql (insl, src, addr)); + break; + } + } + + emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr)); + + switch (size) + { + case 2: + emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffff), addr)); + break; + case 4: + emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffffffff), addr)); + break; + case 8: + { +#if HOST_BITS_PER_WIDE_INT == 32 + rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode); +#else + rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode); +#endif + emit_insn (gen_mskxl (dstl, dstl, msk, addr)); + } + break; + } + + if (src != const0_rtx) + { + dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN); + dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN); + } + + /* Must store high before low for degenerate case of aligned. */ + emit_move_insn (memh, dsth); + emit_move_insn (meml, dstl); +} + +/* The block move code tries to maximize speed by separating loads and + stores at the expense of register pressure: we load all of the data + before we store it back out. There are two secondary effects worth + mentioning, that this speeds copying to/from aligned and unaligned + buffers, and that it makes the code significantly easier to write. */ + +#define MAX_MOVE_WORDS 8 + +/* Load an integral number of consecutive unaligned quadwords. */ + +static void +alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) + rtx *out_regs; + rtx smem; + HOST_WIDE_INT words, ofs; +{ + rtx const im8 = GEN_INT (-8); + rtx const i64 = GEN_INT (64); + rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1]; + rtx sreg, areg; + HOST_WIDE_INT i; + + /* Generate all the tmp registers we need. */ + for (i = 0; i < words; ++i) + { + data_regs[i] = out_regs[i]; + ext_tmps[i] = gen_reg_rtx (DImode); + } + data_regs[words] = gen_reg_rtx (DImode); + + if (ofs != 0) + smem = change_address (smem, GET_MODE (smem), + plus_constant (XEXP (smem, 0), ofs)); + + /* Load up all of the source data. */ + for (i = 0; i < words; ++i) + { + emit_move_insn (data_regs[i], + change_address (smem, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP(smem,0), + 8*i), + im8))); + } + emit_move_insn (data_regs[words], + change_address (smem, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP(smem,0), + 8*words - 1), + im8))); + + /* Extract the half-word fragments. Unfortunately DEC decided to make + extxh with offset zero a noop instead of zeroing the register, so + we must take care of that edge condition ourselves with cmov. */ + + sreg = copy_addr_to_reg (XEXP (smem, 0)); + areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL, + 1, OPTAB_WIDEN); + for (i = 0; i < words; ++i) + { + emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, sreg)); + + emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], sreg)); + emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i], + gen_rtx_IF_THEN_ELSE (DImode, + gen_rtx_EQ (DImode, areg, + const0_rtx), + const0_rtx, ext_tmps[i]))); + } + + /* Merge the half-words into whole words. */ + for (i = 0; i < words; ++i) + { + out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i], + ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN); + } +} + +/* Store an integral number of consecutive unaligned quadwords. DATA_REGS + may be NULL to store zeros. */ + +static void +alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) + rtx *data_regs; + rtx dmem; + HOST_WIDE_INT words, ofs; +{ + rtx const im8 = GEN_INT (-8); + rtx const i64 = GEN_INT (64); +#if HOST_BITS_PER_WIDE_INT == 32 + rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode); +#else + rtx const im1 = immed_double_const (0xffffffffffffffff, 0, DImode); +#endif + rtx ins_tmps[MAX_MOVE_WORDS]; + rtx st_tmp_1, st_tmp_2, dreg; + rtx st_addr_1, st_addr_2; + HOST_WIDE_INT i; + + /* Generate all the tmp registers we need. */ + if (data_regs != NULL) + for (i = 0; i < words; ++i) + ins_tmps[i] = gen_reg_rtx(DImode); + st_tmp_1 = gen_reg_rtx(DImode); + st_tmp_2 = gen_reg_rtx(DImode); + + if (ofs != 0) + dmem = change_address (dmem, GET_MODE (dmem), + plus_constant (XEXP (dmem, 0), ofs)); + + + st_addr_2 = change_address (dmem, DImode, + gen_rtx_AND (DImode, + plus_constant (XEXP(dmem,0), + words*8 - 1), + im8)); + st_addr_1 = change_address (dmem, DImode, + gen_rtx_AND (DImode, + XEXP (dmem, 0), + im8)); + + /* Load up the destination end bits. */ + emit_move_insn (st_tmp_2, st_addr_2); + emit_move_insn (st_tmp_1, st_addr_1); + + /* Shift the input data into place. */ + dreg = copy_addr_to_reg (XEXP (dmem, 0)); + if (data_regs != NULL) + { + for (i = words-1; i >= 0; --i) + { + emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg)); + emit_insn (gen_insql (data_regs[i], data_regs[i], dreg)); + } + for (i = words-1; i > 0; --i) + { + ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i], + ins_tmps[i-1], ins_tmps[i-1], 1, + OPTAB_WIDEN); + } + } + + /* Split and merge the ends with the destination data. */ + emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg)); + emit_insn (gen_mskxl (st_tmp_1, st_tmp_1, im1, dreg)); + + if (data_regs != NULL) + { + st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1], + st_tmp_2, 1, OPTAB_WIDEN); + st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0], + st_tmp_1, 1, OPTAB_WIDEN); + } + + /* Store it all. */ + emit_move_insn (st_addr_2, st_tmp_2); + for (i = words-1; i > 0; --i) + { + emit_move_insn (change_address (dmem, DImode, + gen_rtx_AND (DImode, + plus_constant(XEXP (dmem,0), + i*8), + im8)), + data_regs ? ins_tmps[i-1] : const0_rtx); + } + emit_move_insn (st_addr_1, st_tmp_1); +} + + +/* Expand string/block move operations. + + operands[0] is the pointer to the destination. + operands[1] is the pointer to the source. + operands[2] is the number of bytes to move. + operands[3] is the alignment. */ + +int +alpha_expand_block_move (operands) + rtx operands[]; +{ + rtx bytes_rtx = operands[2]; + rtx align_rtx = operands[3]; + HOST_WIDE_INT bytes = INTVAL (bytes_rtx); + HOST_WIDE_INT src_align = INTVAL (align_rtx); + HOST_WIDE_INT dst_align = src_align; + rtx orig_src = operands[1]; + rtx orig_dst = operands[0]; + rtx data_regs[2*MAX_MOVE_WORDS+16]; + rtx tmp; + int i, words, ofs, nregs = 0; + + if (bytes <= 0) + return 1; + if (bytes > MAX_MOVE_WORDS*8) + return 0; + + /* Look for additional alignment information from recorded register info. */ + + tmp = XEXP (orig_src, 0); + if (GET_CODE (tmp) == REG) + { + if (REGNO_POINTER_ALIGN (REGNO (tmp)) > src_align) + src_align = REGNO_POINTER_ALIGN (REGNO (tmp)); + } + else if (GET_CODE (tmp) == PLUS + && GET_CODE (XEXP (tmp, 0)) == REG + && GET_CODE (XEXP (tmp, 1)) == CONST_INT) + { + HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); + int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); + + if (a > src_align) + { + if (a >= 8 && c % 8 == 0) + src_align = 8; + else if (a >= 4 && c % 4 == 0) + src_align = 4; + else if (a >= 2 && c % 2 == 0) + src_align = 2; + } + } + + tmp = XEXP (orig_dst, 0); + if (GET_CODE (tmp) == REG) + { + if (REGNO_POINTER_ALIGN (REGNO (tmp)) > dst_align) + dst_align = REGNO_POINTER_ALIGN (REGNO (tmp)); + } + else if (GET_CODE (tmp) == PLUS + && GET_CODE (XEXP (tmp, 0)) == REG + && GET_CODE (XEXP (tmp, 1)) == CONST_INT) + { + HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); + int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); + + if (a > dst_align) + { + if (a >= 8 && c % 8 == 0) + dst_align = 8; + else if (a >= 4 && c % 4 == 0) + dst_align = 4; + else if (a >= 2 && c % 2 == 0) + dst_align = 2; + } + } + + /* + * Load the entire block into registers. + */ + + if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF) + { + enum machine_mode mode; + tmp = XEXP (XEXP (orig_src, 0), 0); + + mode = mode_for_size (bytes, MODE_INT, 1); + if (mode != BLKmode + && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes) + { + /* Whee! Optimize the load to use the existing register. */ + 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))); + } + + ofs = 0; + if (src_align >= 8 && bytes >= 8) + { + words = bytes / 8; + + for (i = 0; i < words; ++i) + data_regs[nregs+i] = gen_reg_rtx(DImode); + + 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))); + } + + nregs += words; + bytes -= words * 8; + ofs += words * 8; + } + if (src_align >= 4 && bytes >= 4) + { + words = bytes / 4; + + for (i = 0; i < words; ++i) + data_regs[nregs+i] = gen_reg_rtx(SImode); + + 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))); + } + + nregs += words; + bytes -= words * 4; + ofs += words * 4; + } + if (bytes >= 16) + { + words = bytes / 8; + + 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); + + nregs += words; + bytes -= words * 8; + ofs += words * 8; + } + if (!TARGET_BWX && bytes >= 8) + { + data_regs[nregs++] = tmp = gen_reg_rtx (DImode); + alpha_expand_unaligned_load (tmp, orig_src, 8, ofs, 0); + bytes -= 8; + ofs += 8; + } + if (!TARGET_BWX && bytes >= 4) + { + data_regs[nregs++] = tmp = gen_reg_rtx (SImode); + alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0); + bytes -= 4; + ofs += 4; + } + if (bytes >= 2) + { + if (src_align >= 2) + { + do { + data_regs[nregs++] = tmp = gen_reg_rtx (HImode); + emit_move_insn (tmp, + change_address (orig_src, HImode, + plus_constant (XEXP (orig_src, 0), + ofs))); + bytes -= 2; + ofs += 2; + } while (bytes >= 2); + } + else if (!TARGET_BWX) + { + data_regs[nregs++] = tmp = gen_reg_rtx (HImode); + alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0); + bytes -= 2; + ofs += 2; + } + } + while (bytes > 0) + { + data_regs[nregs++] = tmp = gen_reg_rtx (QImode); + emit_move_insn (tmp, + change_address (orig_src, QImode, + plus_constant (XEXP (orig_src, 0), + ofs))); + bytes -= 1; + ofs += 1; + } + src_done: + + if (nregs > sizeof(data_regs)/sizeof(*data_regs)) + abort(); + + /* + * Now save it back out again. + */ + + i = 0, ofs = 0; + + if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF) + { + 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) + { + emit_move_insn (tmp, data_regs[0]); + i = 1; + 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. */ + orig_dst = change_address (orig_dst, GET_MODE (orig_dst), + copy_addr_to_reg (XEXP (orig_dst, 0))); + } + + /* Write out the data in whatever chunks reading the source allowed. */ + if (dst_align >= 8) + { + while (i < nregs && GET_MODE (data_regs[i]) == DImode) + { + emit_move_insn (change_address(orig_dst, DImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), + data_regs[i]); + ofs += 8; + i++; + } + } + if (dst_align >= 4) + { + /* If the source has remaining DImode regs, write them out in + two pieces. */ + while (i < nregs && GET_MODE (data_regs[i]) == DImode) + { + 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)), + gen_lowpart (SImode, data_regs[i])); + emit_move_insn (change_address(orig_dst, SImode, + plus_constant (XEXP (orig_dst, 0), + ofs+4)), + gen_lowpart (SImode, tmp)); + ofs += 8; + i++; + } + + while (i < nregs && GET_MODE (data_regs[i]) == SImode) + { + emit_move_insn (change_address(orig_dst, SImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), + data_regs[i]); + ofs += 4; + i++; + } + } + if (i < nregs && GET_MODE (data_regs[i]) == DImode) + { + /* Write out a remaining block of words using unaligned methods. */ + + for (words = 1; i+words < nregs ; ++words) + if (GET_MODE (data_regs[i+words]) != DImode) + break; + + if (words == 1) + alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs); + else + alpha_expand_unaligned_store_words (data_regs+i, orig_dst, words, ofs); + + i += words; + ofs += words * 8; + } + + /* Due to the above, this won't be aligned. */ + /* ??? If we have more than one of these, consider constructing full + words in registers and using alpha_expand_unaligned_store_words. */ + while (i < nregs && GET_MODE (data_regs[i]) == SImode) + { + alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs); + ofs += 4; + i++; + } + + if (dst_align >= 2) + while (i < nregs && GET_MODE (data_regs[i]) == HImode) + { + emit_move_insn (change_address (orig_dst, HImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), + data_regs[i]); + i++; + ofs += 2; + } + else + while (i < nregs && GET_MODE (data_regs[i]) == HImode) + { + alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs); + i++; + ofs += 2; + } + while (i < nregs && GET_MODE (data_regs[i]) == QImode) + { + emit_move_insn (change_address (orig_dst, QImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), + data_regs[i]); + i++; + ofs += 1; + } + dst_done: + + if (i != nregs) + abort(); + + return 1; +} + +int +alpha_expand_block_clear (operands) + rtx operands[]; +{ + rtx bytes_rtx = operands[1]; + rtx align_rtx = operands[2]; + HOST_WIDE_INT bytes = INTVAL (bytes_rtx); + HOST_WIDE_INT align = INTVAL (align_rtx); + rtx orig_dst = operands[0]; + rtx tmp; + HOST_WIDE_INT i, words, ofs = 0; + + if (bytes <= 0) + return 1; + if (bytes > MAX_MOVE_WORDS*8) + return 0; + + /* Look for stricter alignment. */ + + tmp = XEXP (orig_dst, 0); + if (GET_CODE (tmp) == REG) + { + if (REGNO_POINTER_ALIGN (REGNO (tmp)) > align) + align = REGNO_POINTER_ALIGN (REGNO (tmp)); + } + else if (GET_CODE (tmp) == PLUS + && GET_CODE (XEXP (tmp, 0)) == REG + && GET_CODE (XEXP (tmp, 1)) == CONST_INT) + { + HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); + int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); + + if (a > align) + { + if (a >= 8 && c % 8 == 0) + align = 8; + else if (a >= 4 && c % 4 == 0) + align = 4; + else if (a >= 2 && c % 2 == 0) + align = 2; + } + } + + /* Handle a block of contiguous words first. */ + + if (align >= 8 && bytes >= 8) + { + words = bytes / 8; + + for (i = 0; i < words; ++i) + { + emit_move_insn (change_address(orig_dst, DImode, + plus_constant (XEXP (orig_dst, 0), + ofs + i*8)), + const0_rtx); + } + + bytes -= words * 8; + ofs += words * 8; + } + if (align >= 4 && bytes >= 4) + { + words = bytes / 4; + + for (i = 0; i < words; ++i) + { + emit_move_insn (change_address(orig_dst, SImode, + plus_constant (XEXP (orig_dst, 0), + ofs + i*4)), + const0_rtx); + } + + bytes -= words * 4; + ofs += words * 4; + } + if (bytes >= 16) + { + words = bytes / 8; + + alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs); + + bytes -= words * 8; + ofs += words * 8; + } + + /* Next clean up any trailing pieces. We know from the contiguous + block move that there are no aligned SImode or DImode hunks left. */ + + if (!TARGET_BWX && bytes >= 8) + { + alpha_expand_unaligned_store (orig_dst, const0_rtx, 8, ofs); + bytes -= 8; + ofs += 8; + } + if (!TARGET_BWX && bytes >= 4) + { + alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs); + bytes -= 4; + ofs += 4; + } + if (bytes >= 2) + { + if (align >= 2) + { + do { + emit_move_insn (change_address (orig_dst, HImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), + const0_rtx); + bytes -= 2; + ofs += 2; + } while (bytes >= 2); + } + else if (!TARGET_BWX) + { + alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs); + bytes -= 2; + ofs += 2; + } + } + while (bytes > 0) + { + emit_move_insn (change_address (orig_dst, QImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), + const0_rtx); + bytes -= 1; + ofs += 1; + } + + return 1; +} + + +/* 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 +alpha_adjust_cost (insn, link, dep_insn, cost) + rtx insn; + rtx link; + rtx dep_insn; + int cost; +{ + rtx set, set_src; + enum attr_type insn_type, dep_insn_type; + + /* If the dependence is an anti-dependence, there is no cost. For an + output dependence, there is sometimes a cost, but it doesn't seem + worth handling those few cases. */ + + if (REG_NOTE_KIND (link) != 0) + return 0; + + /* If we can't recognize the insns, we can't really do anything. */ + if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0) + return cost; + + insn_type = get_attr_type (insn); + dep_insn_type = get_attr_type (dep_insn); + + /* Bring in the user-defined memory latency. */ + if (dep_insn_type == TYPE_ILD + || dep_insn_type == TYPE_FLD + || dep_insn_type == TYPE_LDSYM) + cost += alpha_memory_latency-1; + + switch (alpha_cpu) + { + case PROCESSOR_EV4: + /* On EV4, if INSN is a store insn and DEP_INSN is setting the data + being stored, we can sometimes lower the cost. */ + + if ((insn_type == TYPE_IST || insn_type == TYPE_FST) + && (set = single_set (dep_insn)) != 0 + && GET_CODE (PATTERN (insn)) == SET + && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) + { + switch (dep_insn_type) + { + case TYPE_ILD: + case TYPE_FLD: + /* No savings here. */ + return cost; + + case TYPE_IMUL: + /* In these cases, we save one cycle. */ + return cost - 1; + + default: + /* In all other cases, we save two cycles. */ + return MAX (0, cost - 2); + } + } + + /* Another case that needs adjustment is an arithmetic or logical + operation. It's cost is usually one cycle, but we default it to + two in the MD file. The only case that it is actually two is + for the address in loads, stores, and jumps. */ + + if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG) + { + switch (insn_type) + { + case TYPE_ILD: + case TYPE_IST: + case TYPE_FLD: + case TYPE_FST: + case TYPE_JSR: + return cost; + default: + return 1; + } + } + + /* The final case is when a compare feeds into an integer branch; + the cost is only one cycle in that case. */ + + if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR) + return 1; + break; + + case PROCESSOR_EV5: + /* And the lord DEC saith: "A special bypass provides an effective + latency of 0 cycles for an ICMP or ILOG insn producing the test + operand of an IBR or ICMOV insn." */ + + if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG) + && (set = single_set (dep_insn)) != 0) + { + /* A branch only has one input. This must be it. */ + if (insn_type == TYPE_IBR) + return 0; + /* A conditional move has three, make sure it is the test. */ + if (insn_type == TYPE_ICMOV + && GET_CODE (set_src = PATTERN (insn)) == SET + && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE + && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0))) + return 0; + } + + /* "The multiplier is unable to receive data from IEU bypass paths. + The instruction issues at the expected time, but its latency is + increased by the time it takes for the input data to become + available to the multiplier" -- which happens in pipeline stage + six, when results are comitted to the register file. */ + + if (insn_type == TYPE_IMUL) + { + switch (dep_insn_type) + { + /* These insns produce their results in pipeline stage five. */ + case TYPE_ILD: + case TYPE_ICMOV: + case TYPE_IMUL: + case TYPE_MVI: + return cost + 1; + + /* Other integer insns produce results in pipeline stage four. */ + default: + return cost + 2; + } + } + break; + + case PROCESSOR_EV6: + /* There is additional latency to move the result of (most) FP + operations anywhere but the FP register file. */ + + if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI) + && (dep_insn_type == TYPE_FADD || + dep_insn_type == TYPE_FMUL || + dep_insn_type == TYPE_FCMOV)) + return cost + 2; + + break; + } + + /* Otherwise, return the default cost. */ + return cost; +} + +/* Functions to save and restore alpha_return_addr_rtx. */ + +struct machine_function +{ + rtx ra_rtx; +}; + +static void +alpha_save_machine_status (p) + struct function *p; +{ + struct machine_function *machine = + (struct machine_function *) xmalloc (sizeof (struct machine_function)); + + p->machine = machine; + machine->ra_rtx = alpha_return_addr_rtx; +} + +static void +alpha_restore_machine_status (p) + struct function *p; +{ + struct machine_function *machine = p->machine; + + alpha_return_addr_rtx = machine->ra_rtx; + + free (machine); + p->machine = (struct machine_function *)0; +} + +/* Do anything needed before RTL is emitted for each function. */ + +void +alpha_init_expanders () +{ + alpha_return_addr_rtx = NULL_RTX; + + /* Arrange to save and restore machine status around nested functions. */ + save_machine_status = alpha_save_machine_status; + restore_machine_status = alpha_restore_machine_status; +} + +/* Start the ball rolling with RETURN_ADDR_RTX. */ + +rtx +alpha_return_addr (count, frame) + int count; + rtx frame ATTRIBUTE_UNUSED; +{ + rtx init; + + if (count != 0) + return const0_rtx; + + if (alpha_return_addr_rtx) + return alpha_return_addr_rtx; + + /* 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, + gen_rtx_REG (Pmode, REG_RA)); + + /* Emit the insn to the prologue with the other argument copies. */ + push_topmost_sequence (); + emit_insn_after (init, get_insns ()); + pop_topmost_sequence (); + + return alpha_return_addr_rtx; +} + +static int +alpha_ra_ever_killed () +{ + rtx top; + +#ifdef ASM_OUTPUT_MI_THUNK + if (current_function_is_thunk) + return 0; +#endif + if (!alpha_return_addr_rtx) + return regs_ever_live[REG_RA]; + + push_topmost_sequence (); + top = get_insns(); + pop_topmost_sequence (); + + return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX); +} + + +/* Print an operand. Recognize special options, documented below. */ + +void +print_operand (file, x, code) + FILE *file; + rtx x; + char code; +{ + int i; + + switch (code) + { + case '&': + /* Generates fp-rounding mode suffix: nothing for normal, 'c' for + chopped, 'm' for minus-infinity, and 'd' for dynamic rounding + mode. alpha_fprm controls which suffix is generated. */ + switch (alpha_fprm) + { + case ALPHA_FPRM_NORM: + break; + case ALPHA_FPRM_MINF: + fputc ('m', file); + break; + case ALPHA_FPRM_CHOP: + fputc ('c', file); + break; + case ALPHA_FPRM_DYN: + fputc ('d', file); + break; + } + break; + + case '\'': + /* Generates trap-mode suffix for instructions that accept the su + suffix only (cmpt et al). */ + if (alpha_tp == ALPHA_TP_INSN) + fputs ("su", file); + break; + + case '`': + /* Generates trap-mode suffix for instructions that accept the + v and sv suffix. The only instruction that needs this is cvtql. */ + switch (alpha_fptm) + { + case ALPHA_FPTM_N: + break; + case ALPHA_FPTM_U: + fputs ("v", file); + break; + case ALPHA_FPTM_SU: + case ALPHA_FPTM_SUI: + fputs ("sv", file); + break; + } + break; + + case '(': + /* Generates trap-mode suffix for instructions that accept the + v, sv, and svi suffix. The only instruction that needs this + is cvttq. */ + switch (alpha_fptm) + { + case ALPHA_FPTM_N: + break; + case ALPHA_FPTM_U: + fputs ("v", file); + break; + case ALPHA_FPTM_SU: + fputs ("sv", file); + break; + case ALPHA_FPTM_SUI: + fputs ("svi", file); + break; + } + break; + + case ')': + /* Generates trap-mode suffix for instructions that accept the u, su, + and sui suffix. This is the bulk of the IEEE floating point + instructions (addt et al). */ + switch (alpha_fptm) + { + case ALPHA_FPTM_N: + break; + case ALPHA_FPTM_U: + fputc ('u', file); + break; + case ALPHA_FPTM_SU: + fputs ("su", file); + break; + case ALPHA_FPTM_SUI: + fputs ("sui", file); + break; + } + break; + + case '+': + /* Generates trap-mode suffix for instructions that accept the sui + suffix (cvtqt and cvtqs). */ + switch (alpha_fptm) + { + case ALPHA_FPTM_N: + case ALPHA_FPTM_U: + case ALPHA_FPTM_SU: /* cvtqt/cvtqs can't cause underflow */ + break; + case ALPHA_FPTM_SUI: + fputs ("sui", file); + break; + } + break; + + case ',': + /* Generates single precision instruction suffix. */ + fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'f' : 's')); + break; + + case '-': + /* Generates double precision instruction suffix. */ + fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'g' : 't')); + break; + + case 'r': + /* If this operand is the constant zero, write it as "$31". */ + if (GET_CODE (x) == REG) + fprintf (file, "%s", reg_names[REGNO (x)]); + else if (x == CONST0_RTX (GET_MODE (x))) + fprintf (file, "$31"); + else + output_operand_lossage ("invalid %%r value"); + + break; + + case 'R': + /* Similar, but for floating-point. */ + if (GET_CODE (x) == REG) + fprintf (file, "%s", reg_names[REGNO (x)]); + else if (x == CONST0_RTX (GET_MODE (x))) + fprintf (file, "$f31"); + else + output_operand_lossage ("invalid %%R value"); + + break; + + case 'N': + /* Write the 1's complement of a constant. */ + if (GET_CODE (x) != CONST_INT) + output_operand_lossage ("invalid %%N value"); + + fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x)); + break; case 'P': /* Write 1 << C, for a constant C. */ if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%P value"); - fprintf (file, "%ld", (HOST_WIDE_INT) 1 << INTVAL (x)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x)); break; case 'h': @@ -958,7 +2649,7 @@ print_operand (file, x, code) if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%h value"); - fprintf (file, "%ld", INTVAL (x) >> 16); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16); break; case 'L': @@ -966,7 +2657,8 @@ print_operand (file, x, code) if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%L value"); - fprintf (file, "%ld", (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, + (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000)); break; case 'm': @@ -988,7 +2680,7 @@ print_operand (file, x, code) if (value & 0xff) mask |= (1 << (i + sizeof (int))); - fprintf (file, "%ld", mask & 0xff); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff); } else if (GET_CODE (x) == CONST_INT) @@ -999,20 +2691,24 @@ print_operand (file, x, code) if (value & 0xff) mask |= (1 << i); - fprintf (file, "%ld", mask); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask); } else output_operand_lossage ("invalid %%m value"); break; case 'M': - /* 'b', 'w', or 'l' as the value of the constant. */ + /* 'b', 'w', 'l', or 'q' as the value of the constant. */ if (GET_CODE (x) != CONST_INT - || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32)) + || (INTVAL (x) != 8 && INTVAL (x) != 16 + && INTVAL (x) != 32 && INTVAL (x) != 64)) output_operand_lossage ("invalid %%M value"); fprintf (file, "%s", - INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l"); + (INTVAL (x) == 8 ? "b" + : INTVAL (x) == 16 ? "w" + : INTVAL (x) == 32 ? "l" + : "q")); break; case 'U': @@ -1021,14 +2717,24 @@ print_operand (file, x, code) fprintf (file, "b"); else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff) fprintf (file, "w"); + else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) + fprintf (file, "l"); #if HOST_BITS_PER_WIDE_INT == 32 else if (GET_CODE (x) == CONST_DOUBLE && CONST_DOUBLE_HIGH (x) == 0 && CONST_DOUBLE_LOW (x) == -1) fprintf (file, "l"); + else if (GET_CODE (x) == CONST_DOUBLE + && CONST_DOUBLE_HIGH (x) == -1 + && CONST_DOUBLE_LOW (x) == -1) + fprintf (file, "q"); #else - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) - fprintf (file, "l"); + else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffffffffffff) + fprintf (file, "q"); + else if (GET_CODE (x) == CONST_DOUBLE + && CONST_DOUBLE_HIGH (x) == 0 + && CONST_DOUBLE_LOW (x) == -1) + fprintf (file, "q"); #endif else output_operand_lossage ("invalid %%U value"); @@ -1041,7 +2747,7 @@ print_operand (file, x, code) && (INTVAL (x) & 7) != 8) output_operand_lossage ("invalid %%s value"); - fprintf (file, "%ld", INTVAL (x) / 8); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8); break; case 'S': @@ -1052,46 +2758,31 @@ print_operand (file, x, code) && (INTVAL (x) & 7) != 8) output_operand_lossage ("invalid %%s value"); - fprintf (file, "%ld", (64 - INTVAL (x)) / 8); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8); break; - case 'C': + case 'C': case 'D': case 'c': case 'd': /* Write out comparison name. */ - if (GET_RTX_CLASS (GET_CODE (x)) != '<') - output_operand_lossage ("invalid %%C value"); - - if (GET_CODE (x) == LEU) - fprintf (file, "ule"); - else if (GET_CODE (x) == LTU) - fprintf (file, "ult"); - else - fprintf (file, "%s", GET_RTX_NAME (GET_CODE (x))); - break; - - case 'D': - /* Similar, but write reversed code. We can't get an unsigned code - here. */ - if (GET_RTX_CLASS (GET_CODE (x)) != '<') - output_operand_lossage ("invalid %%D value"); - - fprintf (file, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x)))); - break; - - case 'c': - /* Similar to `c', but swap. We can't get unsigned here either. */ - if (GET_RTX_CLASS (GET_CODE (x)) != '<') - output_operand_lossage ("invalid %%D value"); - - fprintf (file, "%s", GET_RTX_NAME (swap_condition (GET_CODE (x)))); - break; - - case 'd': - /* Similar, but reverse and swap. We can't get unsigned here either. */ - if (GET_RTX_CLASS (GET_CODE (x)) != '<') - output_operand_lossage ("invalid %%D value"); - - fprintf (file, "%s", - GET_RTX_NAME (swap_condition (reverse_condition ((GET_CODE (x)))))); + { + enum rtx_code c = GET_CODE (x); + + if (GET_RTX_CLASS (c) != '<') + output_operand_lossage ("invalid %%C value"); + + if (code == 'D') + c = reverse_condition (c); + else if (code == 'c') + c = swap_condition (c); + else if (code == 'd') + c = swap_condition (reverse_condition (c)); + + if (c == LEU) + fprintf (file, "ule"); + else if (c == LTU) + fprintf (file, "ult"); + else + fprintf (file, "%s", GET_RTX_NAME (c)); + } break; case 'E': @@ -1136,6 +2827,65 @@ print_operand (file, x, code) } } +/* 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 + code. CXT is an RTX for the static chain value for the function. + + The three offset parameters are for the individual template's + layout. A JMPOFS < 0 indicates that the trampoline does not + contain instructions at all. + + We assume here that a function will be called many more times than + its address is taken (e.g., it might be passed to qsort), so we + take the trouble to initialize the "hint" field in the JMP insn. + Note that the hint field is PC (new) + 4 * bits 13:0. */ + +void +alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs) + rtx tramp, fnaddr, cxt; + 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. */ + enum machine_mode mode = TARGET_OPEN_VMS ? Pmode : ptr_mode; + + /* Store function address and CXT. */ + addr = memory_address (mode, plus_constant (tramp, fnofs)); + emit_move_insn (gen_rtx (MEM, mode, addr), fnaddr); + addr = memory_address (mode, plus_constant (tramp, cxtofs)); + emit_move_insn (gen_rtx (MEM, mode, addr), cxt); + + /* This has been disabled since the hint only has a 32k range, and in + no existing OS is the stack within 32k of the text segment. */ + if (0 && jmpofs >= 0) + { + /* Compute hint value. */ + temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX); + temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1, + OPTAB_WIDEN); + temp = expand_shift (RSHIFT_EXPR, Pmode, temp, + build_int_2 (2, 0), NULL_RTX, 1); + temp = expand_and (gen_lowpart (SImode, temp), GEN_INT (0x3fff), 0); + + /* Merge in the hint. */ + addr = memory_address (SImode, plus_constant (tramp, jmpofs)); + temp1 = force_reg (SImode, gen_rtx (MEM, SImode, addr)); + temp1 = expand_and (temp1, GEN_INT (0xffffc000), NULL_RTX); + temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1, + OPTAB_WIDEN); + emit_move_insn (gen_rtx (MEM, SImode, addr), temp1); + } + +#ifdef TRANSFER_FROM_TRAMPOLINE + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"), + 0, VOIDmode, 1, addr, Pmode); +#endif + + if (jmpofs >= 0) + emit_insn (gen_imb ()); +} + /* Do what is necessary for `va_start'. The argument is ignored; We look at the current function to determine if stdarg or varargs is used and fill in an initial va_list. A pointer to this constructor @@ -1143,9 +2893,9 @@ print_operand (file, x, code) struct rtx_def * alpha_builtin_saveregs (arglist) - tree arglist; + tree arglist ATTRIBUTE_UNUSED; { - rtx block, addr, argsize; + rtx block, addr, dest, argsize; tree fntype = TREE_TYPE (current_function_decl); int stdarg = (TYPE_ARG_TYPES (fntype) != 0 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) @@ -1153,11 +2903,11 @@ alpha_builtin_saveregs (arglist) /* Compute the current position into the args, taking into account both registers and memory. Both of these are already included in - current_function_args_info. */ + NUM_ARGS. */ - argsize = GEN_INT (current_function_args_info * UNITS_PER_WORD); + argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD); - /* SETUP_INCOMING_VARARGS moves the starting address base up by 48, + /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48, storing fp arg registers in the first 48 bytes, and the integer arg registers in the next 48 bytes. This is only done, however, if any integer registers need to be stored. @@ -1166,35 +2916,71 @@ alpha_builtin_saveregs (arglist) order to account for the integer arg registers which are counted in argsize above, but which are not actually stored on the stack. */ - addr = (current_function_args_info <= 5 + stdarg - ? plus_constant (virtual_incoming_args_rtx, 6 * UNITS_PER_WORD) - : plus_constant (virtual_incoming_args_rtx, - (6 * UNITS_PER_WORD))); - - addr = force_operand (addr, NULL_RTX); + if (TARGET_OPEN_VMS) + addr = plus_constant (virtual_incoming_args_rtx, + NUM_ARGS <= 5 + stdarg + ? UNITS_PER_WORD : - 6 * UNITS_PER_WORD); + else + addr = (NUM_ARGS <= 5 + stdarg + ? plus_constant (virtual_incoming_args_rtx, + 6 * UNITS_PER_WORD) + : plus_constant (virtual_incoming_args_rtx, + - (6 * UNITS_PER_WORD))); - /* Allocate the va_list constructor */ - block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD); - RTX_UNCHANGING_P (block) = 1; - RTX_UNCHANGING_P (XEXP (block, 0)) = 1; + /* For VMS, we include the argsize, while on Unix, it's handled as + a separate field. */ + if (TARGET_OPEN_VMS) + addr = plus_constant (addr, INTVAL (argsize)); - /* Store the address of the first integer register in the __base member. */ + addr = force_operand (addr, NULL_RTX); #ifdef POINTERS_EXTEND_UNSIGNED addr = convert_memory_address (ptr_mode, addr); #endif - emit_move_insn (change_address (block, ptr_mode, XEXP (block, 0)), addr); - - /* Store the argsize as the __va_offset member. */ - emit_move_insn (change_address (block, TYPE_MODE (integer_type_node), - plus_constant (XEXP (block, 0), - POINTER_SIZE/BITS_PER_UNIT)), - argsize); - - /* Return the address of the va_list constructor, but don't put it in a - register. Doing so would fail when not optimizing and produce worse - code when optimizing. */ - return XEXP (block, 0); + if (TARGET_OPEN_VMS) + return addr; + else + { + /* Allocate the va_list constructor */ + block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD); + RTX_UNCHANGING_P (block) = 1; + RTX_UNCHANGING_P (XEXP (block, 0)) = 1; + + /* Store the address of the first integer register in the __base + member. */ + + dest = change_address (block, ptr_mode, XEXP (block, 0)); + emit_move_insn (dest, addr); + + if (flag_check_memory_usage) + emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, + dest, ptr_mode, + GEN_INT (GET_MODE_SIZE (ptr_mode)), + TYPE_MODE (sizetype), + GEN_INT (MEMORY_USE_RW), + TYPE_MODE (integer_type_node)); + + /* Store the argsize as the __va_offset member. */ + dest = change_address (block, TYPE_MODE (integer_type_node), + plus_constant (XEXP (block, 0), + POINTER_SIZE/BITS_PER_UNIT)); + emit_move_insn (dest, argsize); + + if (flag_check_memory_usage) + emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, + dest, ptr_mode, + GEN_INT (GET_MODE_SIZE + (TYPE_MODE (integer_type_node))), + TYPE_MODE (sizetype), + GEN_INT (MEMORY_USE_RW), + TYPE_MODE (integer_type_node)); + + /* Return the address of the va_list constructor, but don't put it in a + register. Doing so would fail when not optimizing and produce worse + code when optimizing. */ + return XEXP (block, 0); + } } /* This page contains routines that are used to determine what the function @@ -1202,43 +2988,203 @@ alpha_builtin_saveregs (arglist) /* Compute the size of the save area in the stack. */ +/* These variables are used for communication between the following functions. + They indicate various things about the current function being compiled + that are used to tell what kind of prologue, epilogue and procedure + descriptior to generate. */ + +/* Nonzero if we need a stack procedure. */ +static int vms_is_stack_procedure; + +/* Register number (either FP or SP) that is used to unwind the frame. */ +static int vms_unwind_regno; + +/* Register number used to save FP. We need not have one for RA since + we don't modify it for register procedures. This is only defined + for register frame procedures. */ +static int vms_save_fp_regno; + +/* Register number used to reference objects off our PV. */ +static int vms_base_regno; + +/* Compute register masks for saved registers. */ + +static void +alpha_sa_mask (imaskP, fmaskP) + unsigned long *imaskP; + unsigned long *fmaskP; +{ + unsigned long imask = 0; + unsigned long fmask = 0; + int i; + +#ifdef ASM_OUTPUT_MI_THUNK + if (!current_function_is_thunk) +#endif + { + if (TARGET_OPEN_VMS && vms_is_stack_procedure) + imask |= (1L << HARD_FRAME_POINTER_REGNUM); + + /* One for every register we have to save. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (! fixed_regs[i] && ! call_used_regs[i] + && regs_ever_live[i] && i != REG_RA) + { + if (i < 32) + imask |= (1L << i); + else + fmask |= (1L << (i - 32)); + } + + if (imask || fmask || alpha_ra_ever_killed ()) + imask |= (1L << REG_RA); + } + + *imaskP = imask; + *fmaskP = fmask; +} + int alpha_sa_size () { - int size = 0; + int sa_size = 0; int i; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i]) - size++; +#ifdef ASM_OUTPUT_MI_THUNK + if (current_function_is_thunk) + sa_size = 0; + else +#endif + { + /* One for every register we have to save. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (! fixed_regs[i] && ! call_used_regs[i] + && regs_ever_live[i] && i != REG_RA) + sa_size++; + } - /* If some registers were saved but not reg 26, reg 26 must also - be saved, so leave space for it. */ - if (size != 0 && ! regs_ever_live[26]) - size++; + if (TARGET_OPEN_VMS) + { + /* Start by assuming we can use a register procedure if we don't + make any calls (REG_RA not used) or need to save any + registers and a stack procedure if we do. */ + vms_is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed (); + + /* Decide whether to refer to objects off our PV via FP or PV. + If we need FP for something else or if we receive a nonlocal + goto (which expects PV to contain the value), we must use PV. + Otherwise, start by assuming we can use FP. */ + vms_base_regno = (frame_pointer_needed + || current_function_has_nonlocal_label + || vms_is_stack_procedure + || current_function_outgoing_args_size + ? REG_PV : HARD_FRAME_POINTER_REGNUM); + + /* If we want to copy PV into FP, we need to find some register + in which to save FP. */ + + vms_save_fp_regno = -1; + if (vms_base_regno == HARD_FRAME_POINTER_REGNUM) + for (i = 0; i < 32; i++) + if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i]) + vms_save_fp_regno = i; + + if (vms_save_fp_regno == -1) + vms_base_regno = REG_PV, vms_is_stack_procedure = 1; + + /* Stack unwinding should be done via FP unless we use it for PV. */ + vms_unwind_regno = (vms_base_regno == REG_PV + ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); + + /* If this is a stack procedure, allow space for saving FP and RA. */ + if (vms_is_stack_procedure) + sa_size += 2; + } + else + { + /* If some registers were saved but not RA, RA must also be saved, + so leave space for it. */ + if (sa_size != 0 || alpha_ra_ever_killed ()) + sa_size++; + + /* Our size must be even (multiple of 16 bytes). */ + if (sa_size & 1) + sa_size++; + } - /* Our size must be even (multiple of 16 bytes). */ - if (size & 1) - size ++; + return sa_size * 8; +} - return size * 8; +int +alpha_pv_save_size () +{ + alpha_sa_size (); + return vms_is_stack_procedure ? 8 : 0; } -/* Return 1 if this function can directly return via $26. */ +int +alpha_using_fp () +{ + alpha_sa_size (); + return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM; +} int -direct_return () +vms_valid_decl_attribute_p (decl, attributes, identifier, args) + tree decl ATTRIBUTE_UNUSED; + tree attributes ATTRIBUTE_UNUSED; + tree identifier; + tree args; { - return (reload_completed && alpha_sa_size () == 0 - && get_frame_size () == 0 - && current_function_outgoing_args_size == 0 - && current_function_pretend_args_size == 0); + if (is_attribute_p ("overlaid", identifier)) + return (args == NULL_TREE); + return 0; +} + +static int +alpha_does_function_need_gp () +{ + rtx insn; + + /* We never need a GP for Windows/NT or VMS. */ + if (TARGET_WINDOWS_NT || TARGET_OPEN_VMS) + return 0; + +#ifdef TARGET_PROFILING_NEEDS_GP + if (profile_flag) + return 1; +#endif + +#ifdef ASM_OUTPUT_MI_THUNK + if (current_function_is_thunk) + return 1; +#endif + + /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. + Even if we are a static function, we still need to do this in case + our address is taken and passed to something like qsort. */ + + push_topmost_sequence (); + insn = get_insns (); + pop_topmost_sequence (); + + for (; insn; insn = NEXT_INSN (insn)) + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER) + { + enum attr_type type = get_attr_type (insn); + if (type == TYPE_LDSYM || type == TYPE_JSR) + return 1; + } + + return 0; } /* Write a version stamp. Don't write anything if we are running as a cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */ -#if !defined(CROSS_COMPILE) && !defined(_WIN32) +#ifdef HAVE_STAMP_H #include #endif @@ -1251,85 +3197,267 @@ alpha_write_verstamp (file) #endif } -/* Write code to add constant C to register number IN_REG (possibly 31) - and put the result into OUT_REG. Use TEMP_REG as a scratch register; - usually this will be OUT_REG, but should not be if OUT_REG is - STACK_POINTER_REGNUM, since it must be updated in a single instruction. - Write the code to FILE. */ +/* Write function prologue. */ -static void -add_long_const (file, c, in_reg, out_reg, temp_reg) - FILE *file; - HOST_WIDE_INT c; - int in_reg, out_reg, temp_reg; +/* On vms we have two kinds of functions: + + - stack frame (PROC_STACK) + these are 'normal' functions with local vars and which are + calling other functions + - register frame (PROC_REGISTER) + keeps all data in registers, needs no stack + + We must pass this to the assembler so it can generate the + proper pdsc (procedure descriptor) + This is done with the '.pdesc' command. + + On not-vms, we don't really differentiate between the two, as we can + simply allocate stack without saving registers. */ + +void +alpha_expand_prologue () { - HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); - HOST_WIDE_INT tmp1 = c - low; - HOST_WIDE_INT high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); - HOST_WIDE_INT extra = 0; + /* Registers to save. */ + unsigned long imask = 0; + unsigned long fmask = 0; + /* Stack space needed for pushing registers clobbered by us. */ + HOST_WIDE_INT sa_size; + /* Complete stack size needed. */ + HOST_WIDE_INT frame_size; + /* Offset from base reg to register save area. */ + HOST_WIDE_INT reg_offset; + rtx sa_reg; + int i; - /* We don't have code to write out constants larger than 32 bits. */ -#if HOST_BITS_PER_LONG_INT == 64 - if ((unsigned HOST_WIDE_INT) c >> 32 != 0) - abort (); -#endif + sa_size = alpha_sa_size (); + + frame_size = get_frame_size (); + if (TARGET_OPEN_VMS) + frame_size = ALPHA_ROUND (sa_size + + (vms_is_stack_procedure ? 8 : 0) + + frame_size + + current_function_pretend_args_size); + else + frame_size = (ALPHA_ROUND (current_function_outgoing_args_size) + + sa_size + + ALPHA_ROUND (frame_size + + current_function_pretend_args_size)); + + if (TARGET_OPEN_VMS) + reg_offset = 8; + else + reg_offset = ALPHA_ROUND (current_function_outgoing_args_size); + + alpha_sa_mask (&imask, &fmask); + + /* Adjust the stack by the frame size. If the frame size is > 4096 + bytes, we need to be sure we probe somewhere in the first and last + 4096 bytes (we can probably get away without the latter test) and + every 8192 bytes in between. If the frame size is > 32768, we + do this in a loop. Otherwise, we generate the explicit probe + instructions. - /* If HIGH will be interpreted as negative, we must adjust it to do two - ldha insns. Note that we will never be building a negative constant - here. */ + Note that we are only allowed to adjust sp once in the prologue. */ + + if (frame_size <= 32768) + { + if (frame_size > 4096) + { + int probed = 4096; + + do + emit_insn (gen_probe_stack (GEN_INT (-probed))); + while ((probed += 8192) < frame_size); + + /* We only have to do this probe if we aren't saving registers. */ + if (sa_size == 0 && probed + 4096 < frame_size) + emit_insn (gen_probe_stack (GEN_INT (-frame_size))); + } - if (high & 0x8000) + if (frame_size != 0) + { + emit_move_insn (stack_pointer_rtx, + plus_constant (stack_pointer_rtx, -frame_size)); + } + } + else { - extra = 0x4000; - tmp1 -= 0x40000000; - high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + /* Here we generate code to set R22 to SP + 4096 and set R23 to the + number of 8192 byte blocks to probe. We then probe each block + in the loop and then set SP to the proper location. If the + amount remaining is > 4096, we have to do one more probe if we + are not saving any registers. */ + + HOST_WIDE_INT blocks = (frame_size + 4096) / 8192; + HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192; + rtx ptr = gen_rtx_REG (DImode, 22); + rtx count = gen_rtx_REG (DImode, 23); + + emit_move_insn (count, GEN_INT (blocks)); + emit_move_insn (ptr, plus_constant (stack_pointer_rtx, 4096)); + + /* Because of the difficulty in emitting a new basic block this + late in the compilation, generate the loop as a single insn. */ + emit_insn (gen_prologue_stack_probe_loop (count, ptr)); + + if (leftover > 4096 && sa_size == 0) + { + rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover)); + MEM_VOLATILE_P (last) = 1; + emit_move_insn (last, const0_rtx); + } + + emit_move_insn (stack_pointer_rtx, plus_constant (ptr, -leftover)); } - if (low != 0) + /* Cope with very large offsets to the register save area. */ + sa_reg = stack_pointer_rtx; + if (reg_offset + sa_size > 0x8000) { - int result_reg = (extra == 0 && high == 0) ? out_reg : temp_reg; + int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000; + HOST_WIDE_INT bias; - if (low >= 0 && low < 255) - fprintf (file, "\taddq $%d,%d,$%d\n", in_reg, low, result_reg); - else - fprintf (file, "\tlda $%d,%d($%d)\n", result_reg, low, in_reg); + if (low + sa_size <= 0x8000) + bias = reg_offset - low, reg_offset = low; + else + bias = reg_offset, reg_offset = 0; + + sa_reg = gen_rtx_REG (DImode, 24); + emit_move_insn (sa_reg, plus_constant (stack_pointer_rtx, 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)); + } - in_reg = result_reg; + /* 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)); + imask &= ~(1L << REG_RA); + reg_offset += 8; } - if (extra) + /* Now save any other registers required to be saved. */ + 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)); + 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)); + reg_offset += 8; + } + + if (TARGET_OPEN_VMS) { - int result_reg = (high == 0) ? out_reg : temp_reg; + 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); + } + + if (vms_base_regno != REG_PV) + 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); + } - fprintf (file, "\tldah $%d,%d($%d)\n", result_reg, extra, in_reg); - in_reg = result_reg; + /* 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))); + } } + else + { + /* If we need a frame pointer, set it from the stack pointer. */ + if (frame_pointer_needed) + { + if (TARGET_CAN_FAULT_IN_PROLOGUE) + 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)); + } + } + } + + /* The ABIs for VMS and OSF/1 say that while we can schedule insns into + the prologue, for exception handling reasons, we cannot do this for + any insn that might fault. We could prevent this for mems with a + (clobber:BLK (scratch)), but this doesn't work for fp insns. So we + have to prevent all such scheduling with a blockage. + + Linux, on the other hand, never bothered to implement OSF/1's + exception handling, and so doesn't care about such things. Anyone + planning to use dwarf2 frame-unwind info can also omit the blockage. */ - if (high) - fprintf (file, "\tldah $%d,%d($%d)\n", out_reg, high, in_reg); + if (! TARGET_CAN_FAULT_IN_PROLOGUE) + emit_insn (gen_blockage ()); } -/* Write function prologue. */ +/* Output the textual info surrounding the prologue. */ void -output_prolog (file, size) +alpha_start_function (file, fnname, decl) FILE *file; - int size; -{ - HOST_WIDE_INT out_args_size - = ALPHA_ROUND (current_function_outgoing_args_size); - HOST_WIDE_INT sa_size = alpha_sa_size (); - HOST_WIDE_INT frame_size - = (out_args_size + sa_size - + ALPHA_ROUND (size + current_function_pretend_args_size)); - HOST_WIDE_INT reg_offset = out_args_size; - HOST_WIDE_INT start_reg_offset = reg_offset; - HOST_WIDE_INT actual_start_reg_offset = start_reg_offset; - int int_reg_save_area_size = 0; - rtx insn; - unsigned reg_mask = 0; + char *fnname; + tree decl ATTRIBUTE_UNUSED; +{ + unsigned long imask = 0; + unsigned long fmask = 0; + /* Stack space needed for pushing registers clobbered by us. */ + HOST_WIDE_INT sa_size; + /* Complete stack size needed. */ + HOST_WIDE_INT frame_size; + /* Offset from base reg to register save area. */ + HOST_WIDE_INT reg_offset; + char *entry_label = (char *) alloca (strlen (fnname) + 6); int i; + sa_size = alpha_sa_size (); + + frame_size = get_frame_size (); + if (TARGET_OPEN_VMS) + frame_size = ALPHA_ROUND (sa_size + + (vms_is_stack_procedure ? 8 : 0) + + frame_size + + current_function_pretend_args_size); + else + frame_size = (ALPHA_ROUND (current_function_outgoing_args_size) + + sa_size + + ALPHA_ROUND (frame_size + + current_function_pretend_args_size)); + + if (TARGET_OPEN_VMS) + reg_offset = 8; + else + reg_offset = ALPHA_ROUND (current_function_outgoing_args_size); + + alpha_sa_mask (&imask, &fmask); + /* Ecoff can handle multiple .file directives, so put out file and lineno. We have to do that before the .ent directive as we cannot switch files within procedures with native ecoff because line numbers are @@ -1347,264 +3475,353 @@ output_prolog (file, size) DECL_SOURCE_LINE (current_function_decl)); } - /* The assembly language programmer's guide states that the second argument - to the .ent directive, the lex_level, is ignored by the assembler, - so we might as well omit it. */ - - fprintf (file, "\t.ent "); - assemble_name (file, alpha_function_name); - fprintf (file, "\n"); - ASM_OUTPUT_LABEL (file, alpha_function_name); + /* Issue function start and label. */ + if (TARGET_OPEN_VMS || !flag_inhibit_size_directive) + { + fputs ("\t.ent ", file); + assemble_name (file, fnname); + putc ('\n', file); + } + + strcpy (entry_label, fnname); + if (TARGET_OPEN_VMS) + strcat (entry_label, "..en"); + ASM_OUTPUT_LABEL (file, entry_label); inside_function = TRUE; - /* Set up offsets to alpha virtual arg/local debugging pointer. */ + if (TARGET_OPEN_VMS) + fprintf (file, "\t.base $%d\n", vms_base_regno); + + if (!TARGET_OPEN_VMS && TARGET_IEEE_CONFORMANT + && !flag_inhibit_size_directive) + { + /* Set flags in procedure descriptor to request IEEE-conformant + math-library routines. The value we set it to is PDSC_EXC_IEEE + (/usr/include/pdsc.h). */ + fputs ("\t.eflag 48\n", file); + } + /* Set up offsets to alpha virtual arg/local debugging pointer. */ alpha_auto_offset = -frame_size + current_function_pretend_args_size; alpha_arg_offset = -frame_size + 48; - /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. - Even if we are a static function, we still need to do this in case - our address is taken and passed to something like qsort. - - We never need a GP for Windows/NT. */ - - alpha_function_needs_gp = 0; - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if ((GET_CODE (insn) == CALL_INSN) - || (GET_RTX_CLASS (GET_CODE (insn)) == 'i' - && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER - && (get_attr_type (insn) == TYPE_LDSYM - || get_attr_type (insn) == TYPE_ISUBR))) - { - alpha_function_needs_gp = 1; - break; - } - - if (WINDOWS_NT == 0) + /* Describe our frame. If the frame size is larger than an integer, + print it as zero to avoid an assembler error. We won't be + properly describing such a frame, but that's the best we can do. */ + if (TARGET_OPEN_VMS) { - if (alpha_function_needs_gp) - fprintf (file, "\tldgp $29,0($27)\n"); - - /* Put a label after the GP load so we can enter the function at it. */ - assemble_name (file, alpha_function_name); - fprintf (file, "..ng:\n"); + fprintf (file, "\t.frame $%d,", vms_unwind_regno); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, + frame_size >= (1l << 31) ? 0 : frame_size); + fputs (",$26,", file); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset); + fputs ("\n", file); } - - /* Adjust the stack by the frame size. If the frame size is > 4096 - bytes, we need to be sure we probe somewhere in the first and last - 4096 bytes (we can probably get away without the latter test) and - every 8192 bytes in between. If the frame size is > 32768, we - do this in a loop. Otherwise, we generate the explicit probe - instructions. - - Note that we are only allowed to adjust sp once in the prologue. */ - - if (frame_size < 32768) + else if (!flag_inhibit_size_directive) { - if (frame_size > 4096) - { - int probed = 4096; - - fprintf (file, "\tstq $31,-%d($30)\n", probed); - - while (probed + 8192 < frame_size) - fprintf (file, "\tstq $31,-%d($30)\n", probed += 8192); - - /* We only have to do this probe if we aren't saving registers. */ - if (sa_size == 0 && probed + 4096 < frame_size) - fprintf (file, "\tstq $31,-%d($30)\n", frame_size); - } + fprintf (file, "\t.frame $%d,", + (frame_pointer_needed + ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, + frame_size >= (1l << 31) ? 0 : frame_size); + fprintf (file, ",$26,%d\n", current_function_pretend_args_size); + } - if (frame_size != 0) - fprintf (file, "\tlda $30,-%d($30)\n", frame_size); + /* Describe which registers were spilled. */ + if (TARGET_OPEN_VMS) + { + if (imask) + /* ??? Does VMS care if mask contains ra? The old code did'nt + set it, so I don't here. */ + fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA)); + if (fmask) + fprintf (file, "\t.fmask 0x%lx,0\n", fmask); + if (!vms_is_stack_procedure) + fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno); } - else + else if (!flag_inhibit_size_directive) { - /* Here we generate code to set R4 to SP + 4096 and set R5 to the - number of 8192 byte blocks to probe. We then probe each block - in the loop and then set SP to the proper location. If the - amount remaining is > 4096, we have to do one more probe if we - are not saving any registers. */ - - HOST_WIDE_INT blocks = (frame_size + 4096) / 8192; - HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192; - - add_long_const (file, blocks, 31, 5, 5); - - fprintf (file, "\tlda $4,4096($30)\n"); - - assemble_name (file, alpha_function_name); - fprintf (file, "..sc:\n"); - - fprintf (file, "\tstq $31,-8192($4)\n"); - fprintf (file, "\tsubq $5,1,$5\n"); - fprintf (file, "\tlda $4,-8192($4)\n"); - - fprintf (file, "\tbne $5,"); - assemble_name (file, alpha_function_name); - fprintf (file, "..sc\n"); - - if (leftover > 4096 && sa_size == 0) - fprintf (file, "\tstq $31,-%d($4)\n", leftover); + if (imask) + { + fprintf (file, "\t.mask 0x%lx,", imask); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, + frame_size >= (1l << 31) ? 0 : reg_offset - frame_size); + putc ('\n', file); + + for (i = 0; i < 32; ++i) + if (imask & (1L << i)) + reg_offset += 8; + } - fprintf (file, "\tlda $30,-%d($4)\n", leftover); + if (fmask) + { + fprintf (file, "\t.fmask 0x%lx,", fmask); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, + frame_size >= (1l << 31) ? 0 : reg_offset - frame_size); + putc ('\n', file); + } } - /* Describe our frame. */ - fprintf (file, "\t.frame $%d,%d,$26,%d\n", - (frame_pointer_needed - ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM), - frame_size, current_function_pretend_args_size); - - /* Save register 26 if any other register needs to be saved. */ - if (sa_size != 0) + /* Emit GP related things. It is rather unfortunate about the alignment + issues surrounding a CODE_LABEL that forces us to do the label in + plain text. */ + if (!TARGET_OPEN_VMS && !TARGET_WINDOWS_NT) { - reg_mask |= 1 << 26; - fprintf (file, "\tstq $26,%d($30)\n", reg_offset); - reg_offset += 8; - int_reg_save_area_size += 8; - } - - /* Now save any other used integer registers required to be saved. */ - for (i = 0; i < 32; i++) - if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26) - { - reg_mask |= 1 << i; - fprintf (file, "\tstq $%d,%d($30)\n", i, reg_offset); - reg_offset += 8; - int_reg_save_area_size += 8; - } - - /* Print the register mask and do floating-point saves. */ - if (reg_mask) - fprintf (file, "\t.mask 0x%x,%d\n", reg_mask, - actual_start_reg_offset - frame_size); - - start_reg_offset = reg_offset; - reg_mask = 0; + alpha_function_needs_gp = alpha_does_function_need_gp (); + if (alpha_function_needs_gp) + fputs ("\tldgp $29,0($27)\n", file); - for (i = 0; i < 32; i++) - if (! fixed_regs[i + 32] && ! call_used_regs[i + 32] - && regs_ever_live[i + 32]) - { - reg_mask |= 1 << i; - fprintf (file, "\tstt $f%d,%d($30)\n", i, reg_offset); - reg_offset += 8; - } + putc ('$', file); + assemble_name (file, fnname); + fputs ("..ng:\n", file); + } - /* Print the floating-point mask, if we've saved any fp register. */ - if (reg_mask) - fprintf (file, "\t.fmask 0x%x,%d\n", reg_mask, - actual_start_reg_offset - frame_size + int_reg_save_area_size); +#ifdef OPEN_VMS + /* Ifdef'ed cause readonly_section and link_section are only + available then. */ + readonly_section (); + fprintf (file, "\t.align 3\n"); + assemble_name (file, fnname); fputs ("..na:\n", file); + fputs ("\t.ascii \"", file); + assemble_name (file, fnname); + fputs ("\\0\"\n", file); + + link_section (); + fprintf (file, "\t.align 3\n"); + fputs ("\t.name ", file); + assemble_name (file, fnname); + fputs ("..na\n", file); + ASM_OUTPUT_LABEL (file, fnname); + fprintf (file, "\t.pdesc "); + assemble_name (file, fnname); + fprintf (file, "..en,%s\n", vms_is_stack_procedure ? "stack" : "reg"); + alpha_need_linkage (fnname, 1); + text_section (); +#endif +} - /* If we need a frame pointer, set it from the stack pointer. Note that - this must always be the last instruction in the prologue. */ - if (frame_pointer_needed) - fprintf (file, "\tbis $30,$30,$15\n"); +/* Emit the .prologue note at the scheduled end of the prologue. */ - /* End the prologue and say if we used gp. */ - fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp); +void +output_end_prologue (file) + FILE *file; +{ + if (TARGET_OPEN_VMS) + fputs ("\t.prologue\n", file); + else if (TARGET_WINDOWS_NT) + fputs ("\t.prologue 0\n", file); + else if (!flag_inhibit_size_directive) + fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp); } /* Write function epilogue. */ void -output_epilog (file, size) - FILE *file; - int size; -{ - rtx insn = get_last_insn (); - HOST_WIDE_INT out_args_size - = ALPHA_ROUND (current_function_outgoing_args_size); - HOST_WIDE_INT sa_size = alpha_sa_size (); - HOST_WIDE_INT frame_size - = (out_args_size + sa_size - + ALPHA_ROUND (size + current_function_pretend_args_size)); - HOST_WIDE_INT reg_offset = out_args_size; - HOST_WIDE_INT frame_size_from_reg_save = frame_size - reg_offset; - int restore_fp - = frame_pointer_needed && regs_ever_live[HARD_FRAME_POINTER_REGNUM]; +alpha_expand_epilogue () +{ + /* Registers to save. */ + unsigned long imask = 0; + unsigned long fmask = 0; + /* Stack space needed for pushing registers clobbered by us. */ + HOST_WIDE_INT sa_size; + /* Complete stack size needed. */ + HOST_WIDE_INT frame_size; + /* Offset from base reg to register save area. */ + HOST_WIDE_INT reg_offset; + int fp_is_frame_pointer, fp_offset; + rtx sa_reg, sa_reg_exp = NULL; + rtx sp_adj1, sp_adj2; int i; - /* If the last insn was a BARRIER, we don't have to write anything except - the .end pseudo-op. */ - if (GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - if (insn == 0 || GET_CODE (insn) != BARRIER) - { - int fp_offset = 0; + sa_size = alpha_sa_size (); + + frame_size = get_frame_size (); + if (TARGET_OPEN_VMS) + frame_size = ALPHA_ROUND (sa_size + + (vms_is_stack_procedure ? 8 : 0) + + frame_size + + current_function_pretend_args_size); + else + frame_size = (ALPHA_ROUND (current_function_outgoing_args_size) + + sa_size + + ALPHA_ROUND (frame_size + + current_function_pretend_args_size)); + + if (TARGET_OPEN_VMS) + reg_offset = 8; + else + reg_offset = ALPHA_ROUND (current_function_outgoing_args_size); + + alpha_sa_mask (&imask, &fmask); + fp_is_frame_pointer = ((TARGET_OPEN_VMS && vms_is_stack_procedure) + || (!TARGET_OPEN_VMS && frame_pointer_needed)); + + if (sa_size) + { /* If we have a frame pointer, restore SP from it. */ - if (frame_pointer_needed) - fprintf (file, "\tbis $15,$15,$30\n"); + if ((TARGET_OPEN_VMS + && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM) + || (!TARGET_OPEN_VMS && frame_pointer_needed)) + { + emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); + } - /* Restore all the registers, starting with the return address - register. */ - if (sa_size != 0) + /* Cope with very large offsets to the register save area. */ + sa_reg = stack_pointer_rtx; + if (reg_offset + sa_size > 0x8000) { - fprintf (file, "\tldq $26,%d($30)\n", reg_offset); - reg_offset += 8; + int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000; + HOST_WIDE_INT bias; + + if (low + sa_size <= 0x8000) + bias = reg_offset - low, reg_offset = low; + else + bias = reg_offset, reg_offset = 0; + + sa_reg = gen_rtx_REG (DImode, 22); + sa_reg_exp = plus_constant (stack_pointer_rtx, bias); + + emit_move_insn (sa_reg, sa_reg_exp); } + + /* Restore registers in order, excepting a true frame pointer. */ - /* Now restore any other used integer registers that that we saved, - except for FP if it is being used as FP, since it must be - restored last. */ + emit_move_insn (gen_rtx_REG (DImode, REG_RA), + gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset))); + reg_offset += 8; + imask &= ~(1L << REG_RA); - for (i = 0; i < 32; i++) - if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] - && i != 26) + for (i = 0; i < 32; ++i) + if (imask & (1L << i)) { - if (i == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) + if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer) fp_offset = reg_offset; else - fprintf (file, "\tldq $%d,%d($30)\n", i, reg_offset); + { + emit_move_insn (gen_rtx_REG (DImode, i), + gen_rtx_MEM (DImode, + plus_constant(sa_reg, + reg_offset))); + } reg_offset += 8; } - for (i = 0; i < 32; i++) - if (! fixed_regs[i + 32] && ! call_used_regs[i + 32] - && regs_ever_live[i + 32]) + for (i = 0; i < 32; ++i) + if (fmask & (1L << i)) { - fprintf (file, "\tldt $f%d,%d($30)\n", i, reg_offset); + emit_move_insn (gen_rtx_REG (DFmode, i+32), + gen_rtx_MEM (DFmode, + plus_constant(sa_reg, reg_offset))); reg_offset += 8; } + } - /* If the stack size is large and we have a frame pointer, compute the - size of the stack into a register because the old FP restore, stack - pointer adjust, and return are required to be consecutive - instructions. */ - if (frame_size > 32767 && restore_fp) - add_long_const (file, frame_size, 31, 1, 1); - - /* If we needed a frame pointer and we have to restore it, do it - now. This must be done in one instruction immediately - before the SP update. */ - if (restore_fp && fp_offset) - fprintf (file, "\tldq $15,%d($30)\n", fp_offset); - - /* Now update the stack pointer, if needed. Only one instruction must - modify the stack pointer. It must be the last instruction in the - sequence and must be an ADDQ or LDA instruction. If the frame - pointer was loaded above, we may only put one instruction here. */ - - if (frame_size > 32768 && restore_fp) - fprintf (file, "\taddq $1,$30,$30\n"); + if (frame_size) + { + /* 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); + } + else if (frame_size < 0x40007fffL) + { + int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000; + + sp_adj2 = plus_constant (stack_pointer_rtx, 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); + } + sp_adj2 = GEN_INT (low); + } else - add_long_const (file, frame_size, 30, 30, 1); + { + sp_adj2 = gen_rtx_REG (DImode, 23); + sp_adj1 = alpha_emit_set_const (sp_adj2, DImode, frame_size, 3); + if (!sp_adj1) + { + /* 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) + abort (); +#else + abort (); +#endif + } + sp_adj2 = stack_pointer_rtx; + } + + /* From now on, things must be in order. So emit blockages. */ + + /* Restore the frame pointer. */ + 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))); + } + else if (TARGET_OPEN_VMS) + { + emit_insn (gen_blockage ()); + emit_move_insn (hard_frame_pointer_rtx, + gen_rtx_REG (DImode, vms_save_fp_regno)); + } - /* Finally return to the caller. */ - fprintf (file, "\tret $31,($26),1\n"); + /* Restore the stack pointer. */ + emit_insn (gen_blockage ()); + 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)); + } } + /* Return. */ + emit_jump_insn (gen_return_internal ()); +} + +/* Output the rest of the textual info surrounding the epilogue. */ + +void +alpha_end_function (file, fnname, decl) + FILE *file; + char *fnname; + tree decl ATTRIBUTE_UNUSED; +{ /* End the function. */ - fprintf (file, "\t.end "); - assemble_name (file, alpha_function_name); - fprintf (file, "\n"); + if (!flag_inhibit_size_directive) + { + fputs ("\t.end ", file); + assemble_name (file, fnname); + putc ('\n', file); + } inside_function = FALSE; - /* Show that we know this function if it is called again. */ - SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1; + /* Show that we know this function if it is called again. + + 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? */ + + if (!flag_pic || !TREE_PUBLIC (current_function_decl)) + SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1; } /* Debugging support. */ @@ -1655,7 +3872,7 @@ alpha_output_filename (stream, name) fprintf (stream, "\t#@stabs\n"); } - else if (!TARGET_GAS && write_symbols == DBX_DEBUG) + else if (write_symbols == DBX_DEBUG) { ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0); fprintf (stream, "%s ", ASM_STABS_OP); @@ -1664,7 +3881,7 @@ alpha_output_filename (stream, name) } else if (name != current_function_file - && strcmp (name, current_function_file) != 0) + && strcmp (name, current_function_file) != 0) { if (inside_function && ! TARGET_GAS) fprintf (stream, "\t#.file\t%d ", num_source_filenames); @@ -1687,7 +3904,7 @@ alpha_output_lineno (stream, line) FILE *stream; int line; { - if (! TARGET_GAS && write_symbols == DBX_DEBUG) + if (write_symbols == DBX_DEBUG) { /* mips-tfile doesn't understand .stabd directives. */ ++sym_lineno; @@ -1697,3 +3914,543 @@ alpha_output_lineno (stream, line) else fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line); } + +/* Structure to show the current status of registers and memory. */ + +struct shadow_summary +{ + struct { + unsigned long i : 31; /* Mask of int regs */ + unsigned long fp : 31; /* Mask of fp regs */ + unsigned long mem : 1; /* mem == imem | fpmem */ + } used, defd; +}; + +static void summarize_insn PROTO((rtx, struct shadow_summary *, int)); +static void alpha_handle_trap_shadows PROTO((rtx)); + +/* Summary the effects of expression X on the machine. Update SUM, a pointer + to the summary structure. SET is nonzero if the insn is setting the + object, otherwise zero. */ + +static void +summarize_insn (x, sum, set) + rtx x; + struct shadow_summary *sum; + int set; +{ + char *format_ptr; + int i, j; + + if (x == 0) + return; + + switch (GET_CODE (x)) + { + /* ??? Note that this case would be incorrect if the Alpha had a + ZERO_EXTRACT in SET_DEST. */ + case SET: + summarize_insn (SET_SRC (x), sum, 0); + summarize_insn (SET_DEST (x), sum, 1); + break; + + case CLOBBER: + summarize_insn (XEXP (x, 0), sum, 1); + break; + + case USE: + summarize_insn (XEXP (x, 0), sum, 0); + break; + + case ASM_OPERANDS: + for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--) + summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0); + break; + + case PARALLEL: + for (i = XVECLEN (x, 0) - 1; i >= 0; i--) + summarize_insn (XVECEXP (x, 0, i), sum, 0); + break; + + case SUBREG: + summarize_insn (SUBREG_REG (x), sum, 0); + break; + + case REG: + { + int regno = REGNO (x); + unsigned long mask = 1UL << (regno % 32); + + if (regno == 31 || regno == 63) + break; + + if (set) + { + if (regno < 32) + sum->defd.i |= mask; + else + sum->defd.fp |= mask; + } + else + { + if (regno < 32) + sum->used.i |= mask; + else + sum->used.fp |= mask; + } + } + break; + + case MEM: + if (set) + sum->defd.mem = 1; + else + sum->used.mem = 1; + + /* Find the regs used in memory address computation: */ + summarize_insn (XEXP (x, 0), sum, 0); + break; + + case CONST_INT: case CONST_DOUBLE: + case SYMBOL_REF: case LABEL_REF: case CONST: + break; + + /* Handle common unary and binary ops for efficiency. */ + case COMPARE: case PLUS: case MINUS: case MULT: case DIV: + case MOD: case UDIV: case UMOD: case AND: case IOR: + case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT: + case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX: + case NE: case EQ: case GE: case GT: case LE: + case LT: case GEU: case GTU: case LEU: case LTU: + summarize_insn (XEXP (x, 0), sum, 0); + summarize_insn (XEXP (x, 1), sum, 0); + break; + + case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND: + case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT: + case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS: + case SQRT: case FFS: + summarize_insn (XEXP (x, 0), sum, 0); + break; + + default: + format_ptr = GET_RTX_FORMAT (GET_CODE (x)); + for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) + switch (format_ptr[i]) + { + case 'e': + summarize_insn (XEXP (x, i), sum, 0); + break; + + case 'E': + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + summarize_insn (XVECEXP (x, i, j), sum, 0); + break; + + case 'i': + break; + + default: + abort (); + } + } +} + +/* Ensure a sufficient number of `trapb' insns are in the code when + the user requests code with a trap precision of functions or + instructions. + + In naive mode, when the user requests a trap-precision of + "instruction", a trapb is needed after every instruction that may + generate a trap. This ensures that the code is resumption safe but + it is also slow. + + When optimizations are turned on, we delay issuing a trapb as long + as possible. In this context, a trap shadow is the sequence of + instructions that starts with a (potentially) trap generating + instruction and extends to the next trapb or call_pal instruction + (but GCC never generates call_pal by itself). We can delay (and + therefore sometimes omit) a trapb subject to the following + conditions: + + (a) On entry to the trap shadow, if any Alpha register or memory + location contains a value that is used as an operand value by some + instruction in the trap shadow (live on entry), then no instruction + in the trap shadow may modify the register or memory location. + + (b) Within the trap shadow, the computation of the base register + for a memory load or store instruction may not involve using the + result of an instruction that might generate an UNPREDICTABLE + result. + + (c) Within the trap shadow, no register may be used more than once + as a destination register. (This is to make life easier for the + trap-handler.) + + (d) The trap shadow may not include any branch instructions. */ + +static void +alpha_handle_trap_shadows (insns) + rtx insns; +{ + struct shadow_summary shadow; + int trap_pending, exception_nesting; + rtx i; + + if (alpha_tp == ALPHA_TP_PROG && !flag_exceptions) + return; + + trap_pending = 0; + exception_nesting = 0; + shadow.used.i = 0; + shadow.used.fp = 0; + shadow.used.mem = 0; + shadow.defd = shadow.used; + + for (i = insns; i ; i = NEXT_INSN (i)) + { + if (GET_CODE (i) == NOTE) + { + switch (NOTE_LINE_NUMBER (i)) + { + case NOTE_INSN_EH_REGION_BEG: + exception_nesting++; + if (trap_pending) + goto close_shadow; + break; + + case NOTE_INSN_EH_REGION_END: + exception_nesting--; + if (trap_pending) + goto close_shadow; + break; + + case NOTE_INSN_EPILOGUE_BEG: + if (trap_pending && alpha_tp >= ALPHA_TP_FUNC) + goto close_shadow; + break; + } + } + else if (trap_pending) + { + if (alpha_tp == ALPHA_TP_FUNC) + { + if (GET_CODE (i) == JUMP_INSN + && GET_CODE (PATTERN (i)) == RETURN) + goto close_shadow; + } + else if (alpha_tp == ALPHA_TP_INSN) + { + if (optimize > 0) + { + struct shadow_summary sum; + + sum.used.i = 0; + sum.used.fp = 0; + sum.used.mem = 0; + sum.defd = sum.used; + + switch (GET_CODE (i)) + { + case INSN: + /* Annoyingly, get_attr_trap will abort on these. */ + if (GET_CODE (PATTERN (i)) == USE + || GET_CODE (PATTERN (i)) == CLOBBER) + break; + + summarize_insn (PATTERN (i), &sum, 0); + + if ((sum.defd.i & shadow.defd.i) + || (sum.defd.fp & shadow.defd.fp)) + { + /* (c) would be violated */ + goto close_shadow; + } + + /* Combine shadow with summary of current insn: */ + shadow.used.i |= sum.used.i; + shadow.used.fp |= sum.used.fp; + shadow.used.mem |= sum.used.mem; + shadow.defd.i |= sum.defd.i; + shadow.defd.fp |= sum.defd.fp; + shadow.defd.mem |= sum.defd.mem; + + if ((sum.defd.i & shadow.used.i) + || (sum.defd.fp & shadow.used.fp) + || (sum.defd.mem & shadow.used.mem)) + { + /* (a) would be violated (also takes care of (b)) */ + if (get_attr_trap (i) == TRAP_YES + && ((sum.defd.i & sum.used.i) + || (sum.defd.fp & sum.used.fp))) + abort (); + + goto close_shadow; + } + break; + + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + goto close_shadow; + + default: + abort (); + } + } + else + { + close_shadow: + emit_insn_before (gen_trapb (), i); + trap_pending = 0; + shadow.used.i = 0; + shadow.used.fp = 0; + shadow.used.mem = 0; + shadow.defd = shadow.used; + } + } + } + + if ((exception_nesting > 0 || alpha_tp >= ALPHA_TP_FUNC) + && GET_CODE (i) == INSN + && GET_CODE (PATTERN (i)) != USE + && GET_CODE (PATTERN (i)) != CLOBBER + && get_attr_trap (i) == TRAP_YES) + { + if (optimize && !trap_pending) + summarize_insn (PATTERN (i), &shadow, 0); + trap_pending = 1; + } + } +} + +/* Machine dependant reorg pass. */ + +void +alpha_reorg (insns) + rtx insns; +{ + alpha_handle_trap_shadows (insns); +} + + +/* Check a floating-point value for validity for a particular machine mode. */ + +static char * const float_strings[] = +{ + /* These are for FLOAT_VAX. */ + "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */ + "-1.70141173319264430e+38", + "2.93873587705571877e-39", /* 2^-128 */ + "-2.93873587705571877e-39", + /* These are for the default broken IEEE mode, which traps + on infinity or denormal numbers. */ + "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */ + "-3.402823466385288598117e+38", + "1.1754943508222875079687e-38", /* 2^-126 */ + "-1.1754943508222875079687e-38", +}; + +static REAL_VALUE_TYPE float_values[8]; +static int inited_float_values = 0; + +int +check_float_value (mode, d, overflow) + enum machine_mode mode; + REAL_VALUE_TYPE *d; + int overflow ATTRIBUTE_UNUSED; +{ + + if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT) + return 0; + + if (inited_float_values == 0) + { + int i; + for (i = 0; i < 8; i++) + float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode); + + inited_float_values = 1; + } + + if (mode == SFmode) + { + REAL_VALUE_TYPE r; + REAL_VALUE_TYPE *fvptr; + + if (TARGET_FLOAT_VAX) + fvptr = &float_values[0]; + else + fvptr = &float_values[4]; + + bcopy ((char *) d, (char *) &r, sizeof (REAL_VALUE_TYPE)); + if (REAL_VALUES_LESS (fvptr[0], r)) + { + bcopy ((char *) &fvptr[0], (char *) d, + sizeof (REAL_VALUE_TYPE)); + return 1; + } + else if (REAL_VALUES_LESS (r, fvptr[1])) + { + bcopy ((char *) &fvptr[1], (char *) d, + sizeof (REAL_VALUE_TYPE)); + return 1; + } + else if (REAL_VALUES_LESS (dconst0, r) + && REAL_VALUES_LESS (r, fvptr[2])) + { + bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE)); + return 1; + } + else if (REAL_VALUES_LESS (r, dconst0) + && REAL_VALUES_LESS (fvptr[3], r)) + { + bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE)); + return 1; + } + } + + return 0; +} + +#if OPEN_VMS + +/* Return the VMS argument type corresponding to MODE. */ + +enum avms_arg_type +alpha_arg_type (mode) + enum machine_mode mode; +{ + switch (mode) + { + case SFmode: + return TARGET_FLOAT_VAX ? FF : FS; + case DFmode: + return TARGET_FLOAT_VAX ? FD : FT; + default: + return I64; + } +} + +/* Return an rtx for an integer representing the VMS Argument Information + register value. */ + +struct rtx_def * +alpha_arg_info_reg_val (cum) + CUMULATIVE_ARGS cum; +{ + unsigned HOST_WIDE_INT regval = cum.num_args; + int i; + + for (i = 0; i < 6; i++) + regval |= ((int) cum.atypes[i]) << (i * 3 + 8); + + return GEN_INT (regval); +} + +/* Structure to collect function names for final output + in link section. */ + +enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; + + +struct alpha_links { + struct alpha_links *next; + char *name; + enum links_kind kind; +}; + +static struct alpha_links *alpha_links_base = 0; + +/* 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. */ + +void +alpha_need_linkage (name, is_local) + char *name; + int is_local; +{ + rtx x; + struct alpha_links *lptr, *nptr; + + if (name[0] == '*') + name++; + + /* Is this name already defined ? */ + + for (lptr = alpha_links_base; lptr; lptr = lptr->next) + if (strcmp (lptr->name, name) == 0) + { + if (is_local) + { + /* Defined here but external assumed. */ + if (lptr->kind == KIND_EXTERN) + lptr->kind = KIND_LOCAL; + } + else + { + /* Used here but unused assumed. */ + if (lptr->kind == KIND_UNUSED) + lptr->kind = KIND_LOCAL; + } + return; + } + + nptr = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); + nptr->next = alpha_links_base; + nptr->name = xstrdup (name); + + /* Assume external if no definition. */ + nptr->kind = (is_local ? KIND_UNUSED : KIND_EXTERN); + + /* Ensure we have an IDENTIFIER so assemble_name can mark is used. */ + get_identifier (name); + + alpha_links_base = nptr; + + return; +} + + +void +alpha_write_linkage (stream) + FILE *stream; +{ + struct alpha_links *lptr, *nptr; + + readonly_section (); + + fprintf (stream, "\t.align 3\n"); + + for (lptr = alpha_links_base; lptr; lptr = nptr) + { + nptr = lptr->next; + + if (lptr->kind == KIND_UNUSED + || ! TREE_SYMBOL_REFERENCED (get_identifier (lptr->name))) + continue; + + fprintf (stream, "$%s..lk:\n", lptr->name); + if (lptr->kind == KIND_LOCAL) + { + /* Local and used, build linkage pair. */ + fprintf (stream, "\t.quad %s..en\n", lptr->name); + fprintf (stream, "\t.quad %s\n", lptr->name); + } + else + /* External and used, request linkage pair. */ + fprintf (stream, "\t.linkage %s\n", lptr->name); + } +} + +#else + +void +alpha_need_linkage (name, is_local) + char *name ATTRIBUTE_UNUSED; + int is_local ATTRIBUTE_UNUSED; +{ +} + +#endif /* OPEN_VMS */ diff --git a/contrib/gcc/config/alpha/alpha.h b/contrib/gcc/config/alpha/alpha.h index 9504c09..43b0dee 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, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -20,21 +20,21 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "\ --Dunix -D__osf__ -D__alpha -D__alpha__ -D_LONGLONG -DSYSTYPE_BSD \ --D_SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4) -Acpu(alpha) -Amachine(alpha)" - /* Write out the correct language type definition for the header files. Unless we have assembler language, write out the symbols for C. */ #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}" +%{!undef:\ +%{.S:-D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY }}\ +%{.cc|.cxx|.C:-D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus }\ +%{.m:-D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C }\ +%{!.S:%{!.cc:%{!.cxx:%{!.C:%{!.m:-D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C }}}}}}\ +%{mieee:-D_IEEE_FP }\ +%{mieee-with-inexact:-D_IEEE_FP -D_IEEE_FP_INEXACT }}\ +%(cpp_cpu) %(cpp_subtarget)" + +#ifndef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "" +#endif /* Set the spec to use for signed char. The default tests the above macro but DEC's compiler can't handle the conditional in a "constant" @@ -42,18 +42,6 @@ Boston, MA 02111-1307, USA. */ #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" -/* Under OSF/1, -p and -pg require -lprof1. */ - -#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} %{a:-lprof2} -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 - -call_shared as appropriate. Also pass -pg. */ -#define LINK_SPEC \ - "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \ - %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \ - %{rpath*}" - #define WORD_SWITCH_TAKES_ARG(STR) \ (!strcmp (STR, "rpath") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ @@ -61,62 +49,296 @@ Boston, MA 02111-1307, USA. */ || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ || !strcmp (STR, "isystem")) -#define STARTFILE_SPEC \ - "%{!shared:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}" - /* Print subsidiary information on the compiler version in use. */ #define TARGET_VERSION -/* Default this to not be compiling for Windows/NT. */ -#ifndef WINDOWS_NT -#define WINDOWS_NT 0 -#endif - -/* Define the location for the startup file on OSF/1 for Alpha. */ - -#define MD_STARTFILE_PREFIX "/usr/lib/cmplrs/cc/" - /* Run-time compilation parameters selecting different hardware subsets. */ +/* Which processor to schedule for. The cpu attribute defines a list that + mirrors this list, so changes to alpha.md must be made at the same time. */ + +enum processor_type + {PROCESSOR_EV4, /* 2106[46]{a,} */ + PROCESSOR_EV5, /* 21164{a,pc,} */ + PROCESSOR_EV6}; /* 21264 */ + +extern enum processor_type alpha_cpu; + +enum alpha_trap_precision +{ + ALPHA_TP_PROG, /* No precision (default). */ + ALPHA_TP_FUNC, /* Trap contained within originating function. */ + ALPHA_TP_INSN /* Instruction accuracy and code is resumption safe. */ +}; + +enum alpha_fp_rounding_mode +{ + ALPHA_FPRM_NORM, /* Normal rounding mode. */ + ALPHA_FPRM_MINF, /* Round towards minus-infinity. */ + ALPHA_FPRM_CHOP, /* Chopped rounding mode (towards 0). */ + ALPHA_FPRM_DYN /* Dynamic rounding mode. */ +}; + +enum alpha_fp_trap_mode +{ + ALPHA_FPTM_N, /* Normal trap mode. */ + ALPHA_FPTM_U, /* Underflow traps enabled. */ + ALPHA_FPTM_SU, /* Software completion, w/underflow traps */ + ALPHA_FPTM_SUI /* Software completion, w/underflow & inexact traps */ +}; + extern int target_flags; +extern enum alpha_trap_precision alpha_tp; +extern enum alpha_fp_rounding_mode alpha_fprm; +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 TARGET_FP (target_flags & 1) +#define MASK_FP 1 +#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 TARGET_FPREGS (target_flags & 2) +#define MASK_FPREGS 2 +#define TARGET_FPREGS (target_flags & MASK_FPREGS) /* This means that gas is used to process the assembler file. */ #define MASK_GAS 4 #define TARGET_GAS (target_flags & MASK_GAS) +/* This means that we should mark procedures as IEEE conformant. */ + +#define MASK_IEEE_CONFORMANT 8 +#define TARGET_IEEE_CONFORMANT (target_flags & MASK_IEEE_CONFORMANT) + +/* This means we should be IEEE-compliant except for inexact. */ + +#define MASK_IEEE 16 +#define TARGET_IEEE (target_flags & MASK_IEEE) + +/* This means we should be fully IEEE-compliant. */ + +#define MASK_IEEE_WITH_INEXACT 32 +#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 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 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 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 TARGET_MAX (target_flags & MASK_MAX) + +/* This means that the processor is an EV5, EV56, or PCA56. This is defined + only in TARGET_CPU_DEFAULT. */ +#define MASK_CPU_EV5 8192 + +/* Likewise for EV6. */ +#define MASK_CPU_EV6 16384 + +/* This means we support the .arch directive in the assembler. Only + defined in TARGET_CPU_DEFAULT. */ +#define MASK_SUPPORT_ARCH 32768 +#define TARGET_SUPPORT_ARCH (target_flags & MASK_SUPPORT_ARCH) + +/* These are for target os support and cannot be changed at runtime. */ +#ifndef TARGET_WINDOWS_NT +#define TARGET_WINDOWS_NT 0 +#endif +#ifndef TARGET_OPEN_VMS +#define TARGET_OPEN_VMS 0 +#endif + +#ifndef TARGET_AS_CAN_SUBTRACT_LABELS +#define TARGET_AS_CAN_SUBTRACT_LABELS TARGET_GAS +#endif +#ifndef TARGET_CAN_FAULT_IN_PROLOGUE +#define TARGET_CAN_FAULT_IN_PROLOGUE 0 +#endif + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, each pair being { "NAME", VALUE } where VALUE is the bits to set or minus the bits to clear. An empty string NAME is used to identify the default VALUE. */ -#define TARGET_SWITCHES \ - { {"no-soft-float", 1}, \ - {"soft-float", -1}, \ - {"fp-regs", 2}, \ - {"no-fp-regs", -3}, \ - {"alpha-as", -MASK_GAS}, \ - {"gas", MASK_GAS}, \ +#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_DEFAULT 3 +#define TARGET_DEFAULT MASK_FP|MASK_FPREGS #ifndef TARGET_CPU_DEFAULT #define TARGET_CPU_DEFAULT 0 #endif +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an initializer + with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the fixed + part of the option name, and the address of a variable. The + variable, type `char *', is set to the variable part of the given + option if the fixed part matches. The actual option name is made + by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the + given option is `-mshort-data-512', the variable `m88k_short_data' + will be set to the string `"512"'. + + 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}, \ +} + +/* Attempt to describe CPU characteristics to the preprocessor. */ + +/* 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_CIX_SPEC "-D__alpha_cix__ -Acpu(cix)" + +/* Corresponding to implver... */ +#define CPP_IM_EV4_SPEC "-D__alpha_ev4__ -Acpu(ev4)" +#define CPP_IM_EV5_SPEC "-D__alpha_ev5__ -Acpu(ev5)" +#define CPP_IM_EV6_SPEC "-D__alpha_ev6__ -Acpu(ev6)" + +/* Common combinations. */ +#define CPP_CPU_EV4_SPEC "%(cpp_im_ev4)" +#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)" + +#ifndef CPP_CPU_DEFAULT_SPEC +# if TARGET_CPU_DEFAULT & MASK_CPU_EV6 +# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV6_SPEC +# else +# if TARGET_CPU_DEFAULT & MASK_CPU_EV5 +# if TARGET_CPU_DEFAULT & MASK_MAX +# define CPP_CPU_DEFAULT_SPEC CPP_CPU_PCA56_SPEC +# else +# if TARGET_CPU_DEFAULT & MASK_BWX +# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV56_SPEC +# else +# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV5_SPEC +# endif +# endif +# else +# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV4_SPEC +# endif +# endif +#endif /* CPP_CPU_DEFAULT_SPEC */ + +#ifndef CPP_CPU_SPEC +#define CPP_CPU_SPEC "\ +%{!undef:-Acpu(alpha) -Amachine(alpha) -D__alpha -D__alpha__ \ +%{mcpu=ev4|mcpu=21064:%(cpp_cpu_ev4) }\ +%{mcpu=ev5|mcpu=21164:%(cpp_cpu_ev5) }\ +%{mcpu=ev56|mcpu=21164a:%(cpp_cpu_ev56) }\ +%{mcpu=pca56|mcpu=21164pc|mcpu=21164PC:%(cpp_cpu_pca56) }\ +%{mcpu=ev6|mcpu=21264:%(cpp_cpu_ev6) }\ +%{!mcpu*:%(cpp_cpu_default) }}" +#endif + +/* 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. */ + +#ifndef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS +#endif + +#define EXTRA_SPECS \ + { "cpp_am_bwx", CPP_AM_BWX_SPEC }, \ + { "cpp_am_max", CPP_AM_MAX_SPEC }, \ + { "cpp_am_cix", CPP_AM_CIX_SPEC }, \ + { "cpp_im_ev4", CPP_IM_EV4_SPEC }, \ + { "cpp_im_ev5", CPP_IM_EV5_SPEC }, \ + { "cpp_im_ev6", CPP_IM_EV6_SPEC }, \ + { "cpp_cpu_ev4", CPP_CPU_EV4_SPEC }, \ + { "cpp_cpu_ev5", CPP_CPU_EV5_SPEC }, \ + { "cpp_cpu_ev56", CPP_CPU_EV56_SPEC }, \ + { "cpp_cpu_pca56", CPP_CPU_PCA56_SPEC }, \ + { "cpp_cpu_ev6", CPP_CPU_EV6_SPEC }, \ + { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \ + { "cpp_cpu", CPP_CPU_SPEC }, \ + { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \ + SUBTARGET_EXTRA_SPECS + + +/* Sometimes certain combinations of command options do not make sense + on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + On the Alpha, it is used to translate target-option strings into + numeric values. */ + +extern void override_options (); +#define OVERRIDE_OPTIONS override_options () + + /* Define this macro to change register usage conditional on target flags. On the Alpha, we use this to disable the floating-point registers when @@ -135,6 +357,23 @@ extern int target_flags; /* Define to enable software floating point emulation. */ #define REAL_ARITHMETIC +/* The following #defines are used when compiling the routines in + libgcc1.c. Since the Alpha calling conventions require single + precision floats to be passed in the floating-point registers + (rather than in the general registers) we have to build the + libgcc1.c routines in such a way that they know the actual types + of their formal arguments and the actual types of their return + values. Otherwise, gcc will generate calls to the libgcc1.c + routines, passing arguments in the floating-point registers, + but the libgcc1.c routines will expect their arguments on the + stack (where the Alpha calling conventions require structs & + unions to be passed). */ + +#define FLOAT_VALUE_TYPE double +#define INTIFY(FLOATVAL) (FLOATVAL) +#define FLOATIFY(INTVAL) (INTVAL) +#define FLOAT_ARG_TYPE double + /* Define the size of `int'. The default is the same as the word size. */ #define INT_TYPE_SIZE 32 @@ -149,8 +388,8 @@ extern int target_flags; #define DOUBLE_TYPE_SIZE 64 #define LONG_DOUBLE_TYPE_SIZE 64 -#define WCHAR_TYPE "short unsigned int" -#define WCHAR_TYPE_SIZE 16 +#define WCHAR_TYPE "unsigned int" +#define WCHAR_TYPE_SIZE 32 /* Define this macro if it is advisable to hold scalars in registers in a wider mode than that declared by the program. In such cases, @@ -220,7 +459,7 @@ extern int target_flags; #define STACK_BOUNDARY 64 /* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 64 +#define FUNCTION_BOUNDARY 256 /* Alignment of field after `int : 0' in a structure. */ #define EMPTY_FIELD_BOUNDARY 64 @@ -237,31 +476,31 @@ extern int target_flags; we don't optimize and also if we are writing ECOFF symbols to work around a bug in DEC's assembler. */ -#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ - if (optimize > 0 && write_symbols != SDB_DEBUG) \ - ASM_OUTPUT_ALIGN (FILE, 5) +#define LOOP_ALIGN(LABEL) \ + (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0) -/* This is how to align an instruction for optimal branching. - On Alpha we'll get better performance by aligning on a quadword +/* This is how to align an instruction for optimal branching. On + Alpha we'll get better performance by aligning on an octaword boundary. */ -#define ASM_OUTPUT_ALIGN_CODE(FILE) \ - if (optimize > 0 && write_symbols != SDB_DEBUG) \ - ASM_OUTPUT_ALIGN ((FILE), 4) +#define ALIGN_LABEL_AFTER_BARRIER(FILE) \ + (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0) /* No data type wants to be aligned rounder than this. */ #define BIGGEST_ALIGNMENT 64 -/* Make strings word-aligned so strcpy from constants will be faster. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - (TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* Make arrays of chars word-aligned for the same reasons. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) +/* For atomic access to objects, must have at least 32-bit alignment + unless the machine has byte operations. */ +#define MINIMUM_ATOMIC_ALIGNMENT (TARGET_BWX ? 8 : 32) + +/* Align all constants and variables to at least a word boundary so + we can pick up pieces of them faster. */ +/* ??? Only if block-move stuff knows about different source/destination + alignment. */ +#if 0 +#define CONSTANT_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD) +#define DATA_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD) +#endif /* Set this non-zero if move instructions will actually fail to work when given unaligned data. @@ -325,11 +564,11 @@ extern int target_flags; listed once, even those in FIXED_REGISTERS. We allocate in the following order: - $f1 (nonsaved floating-point register) - $f10-$f15 (likewise) + $f10-$f15 (nonsaved floating-point register) $f22-$f30 (likewise) $f21-$f16 (likewise, but input args) $f0 (nonsaved, but return value) + $f1 (nonsaved, but immediate before saved) $f2-$f9 (saved floating-point registers) $1-$8 (nonsaved integer registers) $22-$25 (likewise) @@ -344,11 +583,10 @@ extern int target_flags; $30, $31, $f31 (stack pointer and always zero/ap & fp) */ #define REG_ALLOC_ORDER \ - {33, \ - 42, 43, 44, 45, 46, 47, \ + {42, 43, 44, 45, 46, 47, \ 54, 55, 56, 57, 58, 59, 60, 61, 62, \ 53, 52, 51, 50, 49, 48, \ - 32, \ + 32, 33, \ 34, 35, 36, 37, 38, 39, 40, 41, \ 1, 2, 3, 4, 5, 6, 7, 8, \ 22, 23, 24, 25, \ @@ -373,18 +611,20 @@ extern int target_flags; /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. On Alpha, the integer registers can hold any mode. The floating-point registers can hold 32-bit and 64-bit integers as well, but not 16-bit - or 8-bit values. If we only allowed the larger integers into FP registers, - we'd have to say that QImode and SImode aren't tiable, which is a - pain. So say all registers can hold everything and see how that works. */ + or 8-bit values. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) 1 +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((REGNO) < 32 || ((MODE) != QImode && (MODE) != HImode)) /* 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. */ -#define MODES_TIEABLE_P(MODE1, MODE2) 1 +#define MODES_TIEABLE_P(MODE1, MODE2) \ + ((MODE1) == QImode || (MODE1) == HImode \ + ? (MODE2) == QImode || (MODE2) == HImode \ + : 1) /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -499,9 +739,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, : (C) == 'J' ? (VALUE) == 0 \ : (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \ : (C) == 'L' ? (((VALUE) & 0xffff) == 0 \ - && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0) \ - && ((HOST_BITS_PER_WIDE_INT == 64 \ - || (unsigned) (VALUE) != 0x80000000U))) \ + && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \ : (C) == 'M' ? zap_mask (VALUE) \ : (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \ : (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \ @@ -526,12 +764,17 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, For the Alpha, `Q' means that this is a memory operand but not a reference to an unaligned location. + `R' is a SYMBOL_REF that has SYMBOL_REF_FLAG set or is the current - function. */ + function. + + '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) == 'R' ? current_file_function_operand (OP, Pmode) \ + ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) != AND \ + : (C) == 'R' ? current_file_function_operand (OP, Pmode) \ + : (C) == 'S' ? (GET_CODE (OP) == CONST_INT \ + && (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \ : 0) /* Given an rtx X being reloaded into a reg required to be @@ -544,12 +787,13 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, #define PREFERRED_RELOAD_CLASS(X, CLASS) \ (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \ - ? ((CLASS) == FLOAT_REGS ? NO_REGS : GENERAL_REGS) \ + ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS)\ : (CLASS)) /* Loading and storing HImode or QImode values to and from memory usually requires a scratch register. The exceptions are loading - QImode and HImode from an aligned address to a general register. + QImode and HImode from an aligned address to a general register + unless byte instructions are permitted. We also cannot load an unaligned address or a paradoxical SUBREG into an FP register. */ @@ -563,7 +807,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) \ - && unaligned_memory_operand (IN, MODE)))) \ + && ! TARGET_BWX && unaligned_memory_operand (IN, MODE)))) \ ? GENERAL_REGS \ : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == MEM \ && GET_CODE (XEXP (IN, 0)) == AND) ? GENERAL_REGS \ @@ -579,8 +823,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, && (GET_CODE (SUBREG_REG (OUT)) == MEM \ || (GET_CODE (SUBREG_REG (OUT)) == REG \ && REGNO (SUBREG_REG (OUT)) >= FIRST_PSEUDO_REGISTER)))) \ - && (((MODE) == HImode || (MODE) == QImode \ - || ((MODE) == SImode && (CLASS) == FLOAT_REGS)))) \ + && ((((MODE) == HImode || (MODE) == QImode) \ + && (! TARGET_BWX || (CLASS) == FLOAT_REGS)) \ + || ((MODE) == SImode && (CLASS) == FLOAT_REGS))) \ ? GENERAL_REGS \ : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == MEM \ && GET_CODE (XEXP (OUT, 0)) == AND) ? GENERAL_REGS \ @@ -590,9 +835,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. */ + location unless the CIX extension is available. */ -#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) ((CLASS1) != (CLASS2)) +#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \ + (! TARGET_CIX && (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, @@ -622,15 +868,18 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, reduce the impact of not being able to allocate a pseudo to a hard register. */ -#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ - (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) ? 2 : 20) +#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ + (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) \ + ? 2 \ + : TARGET_CIX ? 3 : 4+2*alpha_memory_latency) /* A C expressions returning the cost of moving data of MODE from a register to or from memory. On the Alpha, bump this up a bit. */ -#define MEMORY_MOVE_COST(MODE) 6 +extern int alpha_memory_latency; +#define MEMORY_MOVE_COST(MODE,CLASS,IN) (2*alpha_memory_latency) /* Provide the cost of a branch. Exact meaning under development. */ #define BRANCH_COST 5 @@ -664,6 +913,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, On Alpha, don't define this because there are no push insns. */ /* #define PUSH_ROUNDING(BYTES) */ +/* Define this to be nonzero if stack checking is built into the ABI. */ +#define STACK_CHECK_BUILTIN 1 + /* Define this if the maximum size of all the outgoing args is to be accumulated and pushed during the prologue. The amount can be found in the variable current_function_outgoing_args_size. */ @@ -738,18 +990,25 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, $f0 for floating-point functions. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, \ - (INTEGRAL_MODE_P (TYPE_MODE (VALTYPE)) \ - && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ - ? word_mode : TYPE_MODE (VALTYPE), \ - TARGET_FPREGS && TREE_CODE (VALTYPE) == REAL_TYPE ? 32 : 0) + 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 ? 32 : 0) + 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. @@ -764,7 +1023,8 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, /* 1 if N is a possible register number for a function value as seen by the caller. */ -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 32) +#define FUNCTION_VALUE_REGNO_P(N) \ + ((N) == 0 || (N) == 1 || (N) == 32 || (N) == 33) /* 1 if N is a possible register number for function argument passing. On Alpha, these are $16-$21 and $f16-$f21. */ @@ -788,7 +1048,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) (CUM) = 0 +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) (CUM) = 0 /* Define intermediate macro to compute the size (in registers) of an argument for the Alpha. */ @@ -894,6 +1154,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, plus_constant (virtual_incoming_args_rtx, \ (CUM) * UNITS_PER_WORD)), \ 6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \ + emit_insn (gen_blockage ()); \ } \ PRETEND_SIZE = 12 * UNITS_PER_WORD; \ } \ @@ -905,6 +1166,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, emitted. If it would take more than N insns, zero is returned and no insns and emitted. */ extern struct rtx_def *alpha_emit_set_const (); +extern struct rtx_def *alpha_emit_set_long_const (); +extern struct rtx_def *alpha_emit_conditional_branch (); +extern struct rtx_def *alpha_emit_conditional_move (); /* Generate necessary RTL for __builtin_saveregs(). ARGLIST is the argument list; see expr.c. */ @@ -918,25 +1182,34 @@ extern struct rtx_def *alpha_builtin_saveregs (); extern struct rtx_def *alpha_compare_op0, *alpha_compare_op1; extern int alpha_compare_fp_p; -/* This macro produces the initial definition of a function name. On the - Alpha, we need to save the function name for the prologue and epilogue. */ +/* 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 (); -extern char *alpha_function_name; +/* This macro defines the start of an assembly comment. */ -#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ -{ \ - alpha_function_name = NAME; \ -} +#define ASM_COMMENT_START " #" + +/* This macro produces the initial definition of a function. */ + +#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ + alpha_start_function(FILE,NAME,DECL); +extern void alpha_start_function (); + +/* This macro closes up a function definition for the assembler. */ + +#define ASM_DECLARE_FUNCTION_SIZE(FILE,NAME,DECL) \ + alpha_end_function(FILE,NAME,DECL) +extern void alpha_end_function (); -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - Refer to the array `regs_ever_live' to determine which registers - to save; `regs_ever_live[I]' is nonzero if register number I - is ever used in the function. This macro is responsible for - knowing which registers should not be saved even if used. */ +/* This macro notes the end of the prologue. */ -#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE) +#define FUNCTION_END_PROLOGUE(FILE) output_end_prologue (FILE) +extern void output_end_prologue (); + +/* Output any profiling code before the prologue. */ + +#define PROFILE_BEFORE_PROLOGUE 1 /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. Under OSF/1, profiling is enabled @@ -986,19 +1259,6 @@ extern char *alpha_function_name; No definition is equivalent to always zero. */ #define EXIT_IGNORE_STACK 1 - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE) - /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. @@ -1010,13 +1270,13 @@ extern char *alpha_function_name; aligned to FUNCTION_BOUNDARY, which is 64 bits. */ #define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ +do { \ fprintf (FILE, "\tldq $1,24($27)\n"); \ fprintf (FILE, "\tldq $27,16($27)\n"); \ fprintf (FILE, "\tjmp $31,($27),0\n"); \ fprintf (FILE, "\tnop\n"); \ fprintf (FILE, "\t.quad 0,0\n"); \ -} +} while (0) /* Section in which to place the trampoline. On Alpha, instructions may only be placed in a text segment. */ @@ -1029,76 +1289,24 @@ extern char *alpha_function_name; /* 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. We assume - here that a function will be called many more times than its address - is taken (e.g., it might be passed to qsort), so we take the trouble - to initialize the "hint" field in the JMP insn. Note that the hint - field is PC (new) + 4 * bits 13:0. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - rtx _temp, _temp1, _addr; \ - \ - _addr = memory_address (Pmode, plus_constant ((TRAMP), 16)); \ - emit_move_insn (gen_rtx (MEM, Pmode, _addr), (FNADDR)); \ - _addr = memory_address (Pmode, plus_constant ((TRAMP), 24)); \ - emit_move_insn (gen_rtx (MEM, Pmode, _addr), (CXT)); \ - \ - _temp = force_operand (plus_constant ((TRAMP), 12), NULL_RTX); \ - _temp = expand_binop (DImode, sub_optab, (FNADDR), _temp, _temp, 1, \ - OPTAB_WIDEN); \ - _temp = expand_shift (RSHIFT_EXPR, Pmode, _temp, \ - build_int_2 (2, 0), NULL_RTX, 1); \ - _temp = expand_and (gen_lowpart (SImode, _temp), \ - GEN_INT (0x3fff), 0); \ - \ - _addr = memory_address (SImode, plus_constant ((TRAMP), 8)); \ - _temp1 = force_reg (SImode, gen_rtx (MEM, SImode, _addr)); \ - _temp1 = expand_and (_temp1, GEN_INT (0xffffc000), NULL_RTX); \ - _temp1 = expand_binop (SImode, ior_optab, _temp1, _temp, _temp1, 1, \ - OPTAB_WIDEN); \ - \ - emit_move_insn (gen_rtx (MEM, SImode, _addr), _temp1); \ - \ - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \ - "__enable_execute_stack"), \ - 0, VOIDmode, 1,_addr, Pmode); \ - \ - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, \ - gen_rtvec (1, const0_rtx), 0)); \ -} + CXT is an RTX for the static chain value for the function. */ -/* Attempt to turn on access permissions for the stack. */ - -#define TRANSFER_FROM_TRAMPOLINE \ - \ -void \ -__enable_execute_stack (addr) \ - void *addr; \ -{ \ - 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"); \ -} +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ + alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 16, 24, 8) /* A C expression whose value is RTL representing the value of the return address for the frame COUNT steps up from the current frame. FRAMEADDR is the frame pointer of the COUNT frame, or the frame pointer of - the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME} is defined. + the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME is defined. */ + +#define RETURN_ADDR_RTX alpha_return_addr +extern struct rtx_def *alpha_return_addr (); - This definition for Alpha is broken, but is put in at the request of - Mike Stump. */ +/* Initialize data used by insn expanders. This is called from insn_emit, + once for every function before code is generated. */ -#define RETURN_ADDR_RTX(COUNT, FRAME) \ -((COUNT == 0 && alpha_sa_size () == 0 && 0 /* not right. */) \ - ? gen_rtx (REG, Pmode, 26) \ - : gen_rtx (MEM, Pmode, \ - memory_address (Pmode, FRAME))) +#define INIT_EXPANDERS alpha_init_expanders () +extern void alpha_init_expanders (); /* Addressing modes, and classification of registers for them. */ @@ -1284,6 +1492,58 @@ __enable_execute_stack (addr) \ } \ } +/* 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 the Alpha, we wish to handle large displacements off a base + register by splitting the addend across an ldah and the mem insn. + This cuts number of extra insns needed from 3 to 1. */ + +#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ +do { \ + /* We must recognize output that we have already generated ourselves. */ \ + if (GET_CODE (X) == PLUS \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \ + && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ + && GET_CODE (XEXP (X, 1)) == CONST_INT) \ + { \ + 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; \ + } \ + if (GET_CODE (X) == PLUS \ + && GET_CODE (XEXP (X, 0)) == REG \ + && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \ + && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \ + && GET_CODE (XEXP (X, 1)) == CONST_INT) \ + { \ + HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \ + HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; \ + HOST_WIDE_INT high \ + = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000; \ + \ + /* Check for 32-bit overflow. */ \ + if (high + low != val) \ + break; \ + \ + /* Reload the high part into a base reg; leave the low part \ + in the mem directly. */ \ + \ + X = gen_rtx_PLUS (GET_MODE (X), \ + gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \ + GEN_INT (high)), \ + GEN_INT (low)); \ + \ + 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; \ + } \ +} 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 Alpha this is true only for the unaligned modes. We can @@ -1297,22 +1557,22 @@ __enable_execute_stack (addr) \ #define ADDRESS_COST(X) 0 -/* Define this if some processing needs to be done immediately before - emitting code for an insn. */ - -/* #define FINAL_PRESCAN_INSN(INSN,OPERANDS,NOPERANDS) */ +/* Machine-dependent reorg pass. */ +#define MACHINE_DEPENDENT_REORG(X) alpha_reorg(X) /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ #define CASE_VECTOR_MODE SImode -/* Define this if the tablejump instruction expects the table - to contain offsets from the address of the table. +/* Define as C expression which evaluates to nonzero if the tablejump + instruction expects the table to contain offsets from the address of the + table. + Do not define this if the table should contain absolute addresses. On the Alpha, the table is really GP-relative, not relative to the PC of the table, but we pretend that it is PC-relative; this should be OK, but we should try to find some better way sometime. */ -#define CASE_VECTOR_PC_RELATIVE +#define CASE_VECTOR_PC_RELATIVE 1 /* Specify the tree operation to be used to convert reals to integers. */ #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR @@ -1336,6 +1596,12 @@ __enable_execute_stack (addr) \ #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. */ + +#define MOVE_RATIO (TARGET_BWX ? 7 : 2) + /* Largest number of bytes of an object that can be placed in a register. On the Alpha we have plenty of registers, so use TImode. */ #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode) @@ -1357,7 +1623,7 @@ __enable_execute_stack (addr) \ will either zero-extend or sign-extend. The value of this macro should be the code that says which one of the two operations is implicitly done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND +#define LOAD_EXTEND_OP(MODE) ((MODE) == SImode ? SIGN_EXTEND : ZERO_EXTEND) /* Define if loading short immediate values into registers sign extends. */ #define SHORT_IMMEDIATES_SIGN_EXTEND @@ -1373,7 +1639,7 @@ __enable_execute_stack (addr) \ /* Define the value returned by a floating-point comparison instruction. */ -#define FLOAT_STORE_FLAG_VALUE 0.5 +#define FLOAT_STORE_FLAG_VALUE (TARGET_FLOAT_VAX ? 0.5 : 2.0) /* Canonicalize a comparison from one we don't have to one we do have. */ @@ -1424,6 +1690,9 @@ __enable_execute_stack (addr) \ our own exit function. */ #define HAVE_ATEXIT +/* The EV4 is dual issue; EV5/EV6 are quad issue. */ +#define ISSUE_RATE (alpha_cpu == PROCESSOR_EV4 ? 2 : 4) + /* 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, @@ -1440,7 +1709,9 @@ __enable_execute_stack (addr) \ if (INTVAL (RTX) >= 0 && INTVAL (RTX) < 256) \ return 0; \ case CONST_DOUBLE: \ - if (((OUTER_CODE) == PLUS && add_operand (RTX, VOIDmode)) \ + if ((RTX) == CONST0_RTX (GET_MODE (RTX))) \ + return 0; \ + else if (((OUTER_CODE) == PLUS && add_operand (RTX, VOIDmode)) \ || ((OUTER_CODE) == AND && and_operand (RTX, VOIDmode))) \ return 0; \ else if (add_operand (RTX, VOIDmode) || and_operand (RTX, VOIDmode)) \ @@ -1450,7 +1721,15 @@ __enable_execute_stack (addr) \ case CONST: \ case SYMBOL_REF: \ case LABEL_REF: \ - return COSTS_N_INSNS (3); + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + return COSTS_N_INSNS (3); \ + case PROCESSOR_EV5: \ + case PROCESSOR_EV6: \ + return COSTS_N_INSNS (2); \ + default: abort(); \ + } /* Provide the costs of a rtl expression. This is in the body of a switch on CODE. */ @@ -1458,52 +1737,128 @@ __enable_execute_stack (addr) \ #define RTX_COSTS(X,CODE,OUTER_CODE) \ case PLUS: case MINUS: \ if (FLOAT_MODE_P (GET_MODE (X))) \ - return COSTS_N_INSNS (6); \ + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + return COSTS_N_INSNS (6); \ + case PROCESSOR_EV5: \ + case PROCESSOR_EV6: \ + return COSTS_N_INSNS (4); \ + default: abort(); \ + } \ else if (GET_CODE (XEXP (X, 0)) == MULT \ && const48_operand (XEXP (XEXP (X, 0), 1), VOIDmode)) \ return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \ + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ break; \ case MULT: \ - if (FLOAT_MODE_P (GET_MODE (X))) \ - return COSTS_N_INSNS (6); \ - return COSTS_N_INSNS (23); \ + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + if (FLOAT_MODE_P (GET_MODE (X))) \ + return COSTS_N_INSNS (6); \ + return COSTS_N_INSNS (23); \ + case PROCESSOR_EV5: \ + if (FLOAT_MODE_P (GET_MODE (X))) \ + return COSTS_N_INSNS (4); \ + else if (GET_MODE (X) == DImode) \ + return COSTS_N_INSNS (12); \ + else \ + return COSTS_N_INSNS (8); \ + case PROCESSOR_EV6: \ + if (FLOAT_MODE_P (GET_MODE (X))) \ + return COSTS_N_INSNS (4); \ + else \ + return COSTS_N_INSNS (7); \ + default: abort(); \ + } \ case ASHIFT: \ if (GET_CODE (XEXP (X, 1)) == CONST_INT \ && INTVAL (XEXP (X, 1)) <= 3) \ break; \ /* ... fall through ... */ \ - case ASHIFTRT: case LSHIFTRT: case IF_THEN_ELSE: \ - return COSTS_N_INSNS (2); \ + case ASHIFTRT: case LSHIFTRT: \ + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + return COSTS_N_INSNS (2); \ + case PROCESSOR_EV5: \ + case PROCESSOR_EV6: \ + return COSTS_N_INSNS (1); \ + default: abort(); \ + } \ + case IF_THEN_ELSE: \ + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + case PROCESSOR_EV6: \ + return COSTS_N_INSNS (2); \ + case PROCESSOR_EV5: \ + return COSTS_N_INSNS (1); \ + default: abort(); \ + } \ case DIV: case UDIV: case MOD: case UMOD: \ - if (GET_MODE (X) == SFmode) \ - return COSTS_N_INSNS (34); \ - else if (GET_MODE (X) == DFmode) \ - return COSTS_N_INSNS (63); \ - else \ - return COSTS_N_INSNS (70); \ + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + if (GET_MODE (X) == SFmode) \ + return COSTS_N_INSNS (34); \ + else if (GET_MODE (X) == DFmode) \ + return COSTS_N_INSNS (63); \ + else \ + return COSTS_N_INSNS (70); \ + case PROCESSOR_EV5: \ + if (GET_MODE (X) == SFmode) \ + return COSTS_N_INSNS (15); \ + else if (GET_MODE (X) == DFmode) \ + return COSTS_N_INSNS (22); \ + else \ + return COSTS_N_INSNS (70); /* ??? */ \ + case PROCESSOR_EV6: \ + if (GET_MODE (X) == SFmode) \ + return COSTS_N_INSNS (12); \ + else if (GET_MODE (X) == DFmode) \ + return COSTS_N_INSNS (15); \ + else \ + return COSTS_N_INSNS (70); /* ??? */ \ + default: abort(); \ + } \ case MEM: \ - return COSTS_N_INSNS (3); \ + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + case PROCESSOR_EV6: \ + return COSTS_N_INSNS (3); \ + case PROCESSOR_EV5: \ + return COSTS_N_INSNS (2); \ + default: abort(); \ + } \ + case NEG: case ABS: \ + if (! FLOAT_MODE_P (GET_MODE (X))) \ + break; \ + /* ... fall through ... */ \ case FLOAT: case UNSIGNED_FLOAT: case FIX: case UNSIGNED_FIX: \ case FLOAT_EXTEND: case FLOAT_TRUNCATE: \ - return COSTS_N_INSNS (6); \ - case NEG: case ABS: \ - if (FLOAT_MODE_P (GET_MODE (X))) \ - return COSTS_N_INSNS (6); \ - break; + switch (alpha_cpu) \ + { \ + case PROCESSOR_EV4: \ + return COSTS_N_INSNS (6); \ + case PROCESSOR_EV5: \ + case PROCESSOR_EV6: \ + return COSTS_N_INSNS (4); \ + default: abort(); \ + } /* Control the assembler format that we output. */ -/* Output at beginning of assembler file. */ - -#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"); \ - ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ -} +/* We don't emit these labels, so as to avoid getting linker errors about + missing exception handling info. If we emit a gcc_compiled. label into + text, and the file has no code, then the DEC assembler gives us a zero + sized text section with no associated exception handling info. The + DEC linker sees this text section, and gives a warning saying that + the exception handling info is missing. */ +#define ASM_IDENTIFY_GCC(x) +#define ASM_IDENTIFY_LANGUAGE(x) /* Output to assembler file text saying following lines may contain character constants, extra white space, comments, etc. */ @@ -1592,20 +1947,15 @@ literal_section () \ #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ do { fputs ("\t.globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) -/* This is how to output a reference to a user-level label named NAME. - `assemble_name' uses this. */ +/* The prefix to add to user-visible assembler symbols. */ -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf (FILE, "%s", NAME) +#define USER_LABEL_PREFIX "" /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. */ #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - if ((PREFIX)[0] == 'L') \ - fprintf (FILE, "$%s%d:\n", & (PREFIX)[1], NUM + 32); \ - else \ - fprintf (FILE, "%s%d:\n", PREFIX, NUM); + fprintf (FILE, "$%s%d:\n", PREFIX, NUM) /* This is how to output a label for a jump table. Arguments are the same as for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is @@ -1620,10 +1970,12 @@ literal_section () \ This is suitable for output with `assemble_name'. */ #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - if ((PREFIX)[0] == 'L') \ - sprintf (LABEL, "*$%s%d", & (PREFIX)[1], NUM + 32); \ - else \ - sprintf (LABEL, "*%s%d", PREFIX, NUM) + sprintf (LABEL, "*$%s%d", PREFIX, NUM) + +/* Check a floating-point value for validity for a particular machine mode. */ + +#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \ + ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW)) /* This is how to output an assembler line defining a `double' constant. */ @@ -1642,29 +1994,18 @@ literal_section () \ { \ char str[30]; \ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ - fprintf (FILE, "\t.t_floating %s\n", str); \ + fprintf (FILE, "\t.%c_floating %s\n", (TARGET_FLOAT_VAX)?'g':'t', str); \ } \ } /* This is how to output an assembler line defining a `float' constant. */ -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.s_floating %s\n", str); \ - } \ - } +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + do { \ + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ +} while (0) /* This is how to output an assembler line defining an `int' constant. */ @@ -1684,12 +2025,12 @@ literal_section () \ #define ASM_OUTPUT_SHORT(FILE,VALUE) \ fprintf (FILE, "\t.word %d\n", \ - (GET_CODE (VALUE) == CONST_INT \ + (int)(GET_CODE (VALUE) == CONST_INT \ ? INTVAL (VALUE) & 0xffff : (abort (), 0))) #define ASM_OUTPUT_CHAR(FILE,VALUE) \ fprintf (FILE, "\t.byte %d\n", \ - (GET_CODE (VALUE) == CONST_INT \ + (int)(GET_CODE (VALUE) == CONST_INT \ ? INTVAL (VALUE) & 0xff : (abort (), 0))) /* We use the default ASCII-output routine, except that we don't write more @@ -1756,7 +2097,7 @@ literal_section () \ /* This is how to output an assembler line for a numeric constant byte. */ #define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf (FILE, "\t.byte 0x%x\n", (VALUE) & 0xff) + fprintf (FILE, "\t.byte 0x%x\n", (int) ((VALUE) & 0xff)) /* This is how to output an element of a case-vector that is absolute. (Alpha does not use such vectors, but we must define this macro anyway.) */ @@ -1765,13 +2106,9 @@ literal_section () \ /* This is how to output an element of a case-vector that is relative. */ -#if WINDOWS_NT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ - fprintf (FILE, "\t.long $%d\n", (VALUE) + 32) -#else -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ - fprintf (FILE, "\t.gprel32 $%d\n", (VALUE) + 32) -#endif +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.%s $L%d\n", TARGET_WINDOWS_NT ? "long" : "gprel32", \ + (VALUE)) /* This is how to output an assembler line that says to advance the location counter @@ -1816,6 +2153,36 @@ literal_section () \ #define ASM_OPEN_PAREN "(" #define ASM_CLOSE_PAREN ")" +/* Output code to add DELTA to the first argument, and then jump to FUNCTION. + Used for C++ multiple inheritance. */ + +#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ +do { \ + char *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); \ + \ + if (current_file_function_operand (XEXP (DECL_RTL (FUNCTION), 0))) \ + { \ + fprintf (FILE, "\tbr $31,$"); \ + assemble_name (FILE, fn_name); \ + fprintf (FILE, "..ng\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tjmp $31,"); \ + assemble_name (FILE, fn_name); \ + fputc ('\n', FILE); \ + } \ +} while (0) + + /* Define results of standard character escape sequences. */ #define TARGET_BELL 007 #define TARGET_BS 010 @@ -1832,9 +2199,41 @@ literal_section () \ #define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) /* Determine which codes are valid without a following integer. These must - not be alphabetic. */ + not be alphabetic (the characters are chosen so that + PRINT_OPERAND_PUNCT_VALID_P translates into a simple range change when + using ASCII). + + & Generates fp-rounding mode suffix: nothing for normal, 'c' for + chopped, 'm' for minus-infinity, and 'd' for dynamic rounding + mode. alpha_fprm controls which suffix is generated. + + ' Generates trap-mode suffix for instructions that accept the + su suffix only (cmpt et al). + + ` Generates trap-mode suffix for instructions that accept the + v and sv suffix. The only instruction that needs this is cvtql. + + ( Generates trap-mode suffix for instructions that accept the + v, sv, and svi suffix. The only instruction that needs this + is cvttq. -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) 0 + ) Generates trap-mode suffix for instructions that accept the + u, su, and sui suffix. This is the bulk of the IEEE floating + point instructions (addt et al). + + + Generates trap-mode suffix for instructions that accept the + sui suffix (cvtqt and cvtqs). + + , Generates single precision suffix for floating point + instructions (s for IEEE, f for VAX) + + - Generates double precision suffix for floating point + instructions (t for IEEE, g for VAX) + */ + +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ + ((CODE) == '&' || (CODE) == '`' || (CODE) == '\'' || (CODE) == '(' \ + || (CODE) == ')' || (CODE) == '+' || (CODE) == ',' || (CODE) == '-') /* Print a memory address as an operand to reference that memory location. */ @@ -1857,38 +2256,42 @@ literal_section () \ else \ abort (); \ \ - fprintf (FILE, "%d($%d)", offset, basereg); \ + fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, offset); \ + fprintf (FILE, "($%d)", basereg); \ } /* 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}}, \ - {"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}}, \ - {"or_operand", {SUBREG, REG, CONST_INT}}, \ - {"mode_mask_operand", {CONST_INT}}, \ - {"mul8_operand", {CONST_INT}}, \ - {"mode_width_operand", {CONST_INT}}, \ - {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \ - {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \ - {"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \ - {"fp0_operand", {CONST_DOUBLE}}, \ - {"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}}, \ - {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ - {"aligned_memory_operand", {MEM}}, \ - {"unaligned_memory_operand", {MEM}}, \ - {"any_memory_operand", {MEM}}, +#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}}, \ + {"const48_operand", {CONST_INT}}, \ + {"and_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \ + {"or_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \ + {"mode_mask_operand", {CONST_INT}}, \ + {"mul8_operand", {CONST_INT}}, \ + {"mode_width_operand", {CONST_INT}}, \ + {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \ + {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \ + {"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}}, \ + {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \ + {"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \ + {"fp0_operand", {CONST_DOUBLE}}, \ + {"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}}, \ + {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ + SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}}, \ + {"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}}, /* Tell collect that the object format is ECOFF. */ #define OBJECT_FORMAT_COFF @@ -1904,8 +2307,7 @@ literal_section () \ #define MIPS_DEBUGGING_INFO /* MIPS specific debugging info */ #ifndef PREFERRED_DEBUGGING_TYPE /* assume SDB_DEBUGGING_INFO */ -#define PREFERRED_DEBUGGING_TYPE \ - ((len > 1 && !strncmp (str, "ggdb", len)) ? DBX_DEBUG : SDB_DEBUG) +#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG #endif @@ -1937,13 +2339,17 @@ extern void alpha_output_lineno (); alpha_output_filename (STREAM, NAME) extern void alpha_output_filename (); - -/* mips-tfile.c limits us to strings of one page. */ -#define DBX_CONTIN_LENGTH 4000 +/* mips-tfile.c limits us to strings of one page. We must underestimate this + number, because the real length runs past this up to the next + continuation point. This is really a dbxout.c bug. */ +#define DBX_CONTIN_LENGTH 3000 /* By default, turn on GDB extensions. */ #define DEFAULT_GDB_EXTENSIONS 1 +/* Stabs-in-ECOFF can't handle dbxout_function_end(). */ +#define NO_DBX_FUNCTION_END 1 + /* If we are smuggling stabs through the ALPHA ECOFF object format, put a comment in front of the .stab operation so that the ALPHA assembler does not choke. The mips-tfile program @@ -2011,47 +2417,7 @@ do { \ #define PUT_SDB_FUNCTION_END(LINE) -#define PUT_SDB_EPILOGUE_END(NAME) - -/* No point in running CPP on our assembler output. */ -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 -/* Don't pass -g to GNU as, because some versions don't accept this option. */ -#define ASM_SPEC "%{malpha-as:-g} -nocpp %{pg}" -#else -/* In OSF/1 v3.2c, the assembler by default does not output file names which - causes mips-tfile to fail. Passing -g to the assembler fixes this problem. - ??? Stricly speaking, we only need -g if the user specifies -g. Passing - it always means that we get slightly larger than necessary object files - if the user does not specify -g. If we don't pass -g, then mips-tfile - will need to be fixed to work in this case. */ -#define ASM_SPEC "%{!mgas:-g} -nocpp %{pg}" -#endif - -/* Specify to run a post-processor, mips-tfile after the assembler - has run to stuff the ecoff debug information into the object file. - This is needed because the Alpha assembler provides no way - of specifying such information in the assembly file. */ - -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 - -#define ASM_FINAL_SPEC "\ -%{malpha-as: %{!mno-mips-tfile: \ - \n mips-tfile %{v*: -v} \ - %{K: -I %b.o~} \ - %{!K: %{save-temps: -I %b.o~}} \ - %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ - %{.s:%i} %{!.s:%g.s}}}" - -#else -#define ASM_FINAL_SPEC "\ -%{!mgas: %{!mno-mips-tfile: \ - \n mips-tfile %{v*: -v} \ - %{K: -I %b.o~} \ - %{!K: %{save-temps: -I %b.o~}} \ - %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ - %{.s:%i} %{!.s:%g.s}}}" - -#endif +#define PUT_SDB_EPILOGUE_END(NAME) ((void)(NAME)) /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for mips-tdump.c to print them out. @@ -2073,16 +2439,55 @@ do { \ #define ALIGN_SYMTABLE_OFFSET(OFFSET) (((OFFSET) + 7) & ~7) -/* The system headers under OSF/1 are C++-aware. */ -#define NO_IMPLICIT_EXTERN_C - -/* Also define __LANGUAGE_C__ when running fix-header. */ -#define FIXPROTO_INIT(CPPFILE) cpp_define (CPPFILE, "__LANGUAGE_C__") - /* The linker will stick __main into the .init section. */ #define HAS_INIT_SECTION #define LD_INIT_SWITCH "-init" #define LD_FINI_SWITCH "-fini" -/* We do want to link in libgcc when building shared libraries under OSF/1. */ -#define LIBGCC_SPEC "-lgcc" +/* The system headers under Alpha systems are generally C++-aware. */ +#define NO_IMPLICIT_EXTERN_C + +/* Prototypes for alpha.c functions used in the md file & elsewhere. */ +extern struct rtx_def *get_unaligned_address (); +extern void alpha_write_verstamp (); +extern void alpha_reorg (); +extern int check_float_value (); +extern int direct_return (); +extern int const48_operand (); +extern int add_operand (); +extern int and_operand (); +extern int unaligned_memory_operand (); +extern int zap_mask (); +extern int current_file_function_operand (); +extern int alpha_sa_size (); +extern int alpha_adjust_cost (); +extern void print_operand (); +extern int reg_or_0_operand (); +extern int reg_or_8bit_operand (); +extern int mul8_operand (); +extern int reg_or_6bit_operand (); +extern int alpha_comparison_operator (); +extern int alpha_swapped_comparison_operator (); +extern int sext_add_operand (); +extern int cint8_operand (); +extern int mode_mask_operand (); +extern int or_operand (); +extern int mode_width_operand (); +extern int reg_or_fp0_operand (); +extern int signed_comparison_operator (); +extern int fp0_operand (); +extern int some_operand (); +extern int input_operand (); +extern int divmod_operator (); +extern int call_operand (); +extern int reg_or_cint_operand (); +extern int hard_fp_register_operand (); +extern void alpha_set_memflags (); +extern int aligned_memory_operand (); +extern void get_aligned_mem (); +extern void alpha_expand_unaligned_load (); +extern void alpha_expand_unaligned_store (); +extern int alpha_expand_block_move (); +extern int alpha_expand_block_clear (); +extern void alpha_expand_prologue (); +extern void alpha_expand_epilogue (); diff --git a/contrib/gcc/config/alpha/alpha.md b/contrib/gcc/config/alpha/alpha.md index 72c54ee..87ebf95 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, 1993, 1994, 1995 Free Software Foundation, Inc. +;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) ;; This file is part of GNU CC. @@ -20,71 +20,396 @@ ;; Boston, MA 02111-1307, USA. ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; Uses of UNSPEC in this file: +;; +;; 0 arg_home +;; 1 cttz +;; 2 insxh +;; 3 mskxh +;; 4 cvtlq +;; 5 cvtql +;; +;; UNSPEC_VOLATILE: +;; +;; 0 imb +;; 1 blockage +;; 2 builtin_setjmp_receiver +;; 3 builtin_longjmp +;; 4 trapb +;; 5 prologue_stack_probe_loop +;; Processor type -- this attribute must exactly match the processor_type +;; enumeration in alpha.h. + +(define_attr "cpu" "ev4,ev5,ev6" + (const (symbol_ref "alpha_cpu"))) + ;; Define an insn type attribute. This is used in function unit delay ;; computations, among other purposes. For the most part, we use the names ;; defined in the EV4 documentation, but add a few that we have to know about ;; separately. (define_attr "type" - "ld,st,ibr,fbr,jsr,iaddlog,shiftcm,icmp,imull,imulq,fpop,fdivs,fdivt,ldsym,isubr" - (const_string "shiftcm")) - -;; We include four function units: ABOX, which computes the address, -;; BBOX, used for branches, EBOX, used for integer operations, and FBOX, -;; used for FP operations. -;; -;; We assume that we have been successful in getting double issues and -;; hence multiply all costs by two insns per cycle. The minimum time in -;; a function unit is 2 cycle, which will tend to produce the double -;; issues. - -;; Memory delivers its result in three cycles. -(define_function_unit "abox" 1 0 (eq_attr "type" "ld,ldsym,st") 6 2) - -;; Branches have no delay cost, but do tie up the unit for two cycles. -(define_function_unit "bbox" 1 1 (eq_attr "type" "ibr,fbr,jsr") 4 4) + "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof" + (const_string "iadd")) -;; Arithmetic insns are normally have their results available after two -;; cycles. There are a number of exceptions. They are encoded in -;; ADJUST_COST. Some of the other insns have similar exceptions. +;; Define the operand size an insn operates on. Used primarily by mul +;; and div operations that have size dependant timings. -(define_function_unit "ebox" 1 0 (eq_attr "type" "iaddlog,shiftcm,icmp") 4 2) +(define_attr "opsize" "si,di,udi" (const_string "di")) -;; These really don't take up the integer pipeline, but they do occupy -;; IBOX1; we approximate here. +;; The TRAP_TYPE attribute marks instructions that may generate traps +;; (which are imprecise and may need a trapb if software completion +;; is desired). -(define_function_unit "ebox" 1 0 (eq_attr "type" "imull") 42 2) -(define_function_unit "ebox" 1 0 (eq_attr "type" "imulq") 46 2) +(define_attr "trap" "no,yes" (const_string "no")) -(define_function_unit "imult" 1 0 (eq_attr "type" "imull") 42 38) -(define_function_unit "imult" 1 0 (eq_attr "type" "imulq") 46 42) +;; The length of an instruction sequence in bytes. -(define_function_unit "fbox" 1 0 (eq_attr "type" "fpop") 12 2) - -(define_function_unit "fbox" 1 0 (eq_attr "type" "fdivs") 68 0) -(define_function_unit "fbox" 1 0 (eq_attr "type" "fdivt") 126 0) +(define_attr "length" "" (const_int 4)) + +;; On EV4 there are two classes of resources to consider: resources needed +;; to issue, and resources needed to execute. IBUS[01] are in the first +;; category. ABOX, BBOX, EBOX, FBOX, IMUL & FDIV make up the second. +;; (There are a few other register-like resources, but ...) + +; First, describe all of the issue constraints with single cycle delays. +; All insns need a bus, but all except loads require one or the other. +(define_function_unit "ev4_ibus0" 1 0 + (and (eq_attr "cpu" "ev4") + (eq_attr "type" "fst,fbr,iadd,imul,ilog,shift,icmov,icmp")) + 1 1) + +(define_function_unit "ev4_ibus1" 1 0 + (and (eq_attr "cpu" "ev4") + (eq_attr "type" "ist,ibr,jsr,fadd,fcmov,fcpys,fmul,fdiv,misc")) + 1 1) + +; Memory delivers its result in three cycles. Actually return one and +; take care of this in adjust_cost, since we want to handle user-defined +; memory latencies. +(define_function_unit "ev4_abox" 1 0 + (and (eq_attr "cpu" "ev4") + (eq_attr "type" "ild,fld,ldsym,ist,fst")) + 1 1) + +; Branches have no delay cost, but do tie up the unit for two cycles. +(define_function_unit "ev4_bbox" 1 1 + (and (eq_attr "cpu" "ev4") + (eq_attr "type" "ibr,fbr,jsr")) + 2 2) + +; Arithmetic insns are normally have their results available after +; two cycles. There are a number of exceptions. They are encoded in +; ADJUST_COST. Some of the other insns have similar exceptions. +(define_function_unit "ev4_ebox" 1 0 + (and (eq_attr "cpu" "ev4") + (eq_attr "type" "iadd,ilog,shift,icmov,icmp,misc")) + 2 1) + +(define_function_unit "imul" 1 0 + (and (eq_attr "cpu" "ev4") + (and (eq_attr "type" "imul") + (eq_attr "opsize" "si"))) + 21 19) + +(define_function_unit "imul" 1 0 + (and (eq_attr "cpu" "ev4") + (and (eq_attr "type" "imul") + (eq_attr "opsize" "!si"))) + 23 21) + +(define_function_unit "ev4_fbox" 1 0 + (and (eq_attr "cpu" "ev4") + (eq_attr "type" "fadd,fmul,fcpys,fcmov")) + 6 1) + +(define_function_unit "fdiv" 1 0 + (and (eq_attr "cpu" "ev4") + (and (eq_attr "type" "fdiv") + (eq_attr "opsize" "si"))) + 34 30) + +(define_function_unit "fdiv" 1 0 + (and (eq_attr "cpu" "ev4") + (and (eq_attr "type" "fdiv") + (eq_attr "opsize" "di"))) + 63 59) + +;; EV5 scheduling. EV5 can issue 4 insns per clock. +;; +;; EV5 has two asymetric integer units. Model this with E0 & E1 along +;; with the combined resource EBOX. + +(define_function_unit "ev5_ebox" 2 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv")) + 1 1) + +; 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) + +; Stores, shifts, multiplies can only issue to E0 +(define_function_unit "ev5_e0" 1 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "ist,fst,shift,imul")) + 1 1) + +; Motion video insns also issue only to E0, and take two ticks. +(define_function_unit "ev5_e0" 1 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "mvi")) + 2 1) + +; Conditional moves always take 2 ticks. +(define_function_unit "ev5_ebox" 2 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "icmov")) + 2 1) + +; Branches can only issue to E1 +(define_function_unit "ev5_e1" 1 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "ibr,jsr")) + 1 1) + +; Multiplies also use the integer multiplier. +; ??? How to: "No instruction can be issued to pipe E0 exactly two +; cycles before an integer multiplication completes." +(define_function_unit "imul" 1 0 + (and (eq_attr "cpu" "ev5") + (and (eq_attr "type" "imul") + (eq_attr "opsize" "si"))) + 8 4) + +(define_function_unit "imul" 1 0 + (and (eq_attr "cpu" "ev5") + (and (eq_attr "type" "imul") + (eq_attr "opsize" "di"))) + 12 8) + +(define_function_unit "imul" 1 0 + (and (eq_attr "cpu" "ev5") + (and (eq_attr "type" "imul") + (eq_attr "opsize" "udi"))) + 14 8) + +;; Similarly for the FPU we have two asymetric units. But fcpys can issue +;; on either so we have to play the game again. + +(define_function_unit "ev5_fbox" 2 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "fadd,fcmov,fmul,fcpys,fbr,fdiv")) + 4 1) + +(define_function_unit "ev5_fm" 1 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "fmul")) + 4 1) + +; Add and cmov as you would expect; fbr never produces a result; +; fdiv issues through fa to the divider, +(define_function_unit "ev5_fa" 1 0 + (and (eq_attr "cpu" "ev5") + (eq_attr "type" "fadd,fcmov,fbr,fdiv")) + 4 1) + +; ??? How to: "No instruction can be issued to pipe FA exactly five +; cycles before a floating point divide completes." +(define_function_unit "fdiv" 1 0 + (and (eq_attr "cpu" "ev5") + (and (eq_attr "type" "fdiv") + (eq_attr "opsize" "si"))) + 15 15) ; 15 to 31 data dependant + +(define_function_unit "fdiv" 1 0 + (and (eq_attr "cpu" "ev5") + (and (eq_attr "type" "fdiv") + (eq_attr "opsize" "di"))) + 22 22) ; 22 to 60 data dependant + +;; EV6 scheduling. EV6 can issue 4 insns per clock. +;; +;; EV6 has two symmetric pairs ("clusters") of two asymetric integer units +;; ("upper" and "lower"), yielding pipe names U0, U1, L0, L1. + +;; Conditional moves decompose into two independant primitives, each +;; taking one cycle. Since ev6 is out-of-order, we can't see anything +;; but two cycles. +(define_function_unit "ev6_ebox" 4 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "icmov")) + 2 1) + +(define_function_unit "ev6_ebox" 4 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv,fsqrt")) + 1 1) + +;; Integer loads take at least 3 clocks, and only issue to lower units. +;; Return one from here and fix up with user-defined latencies in adjust_cost. +(define_function_unit "ev6_l" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "ild,ldsym,ist,fst")) + 1 1) + +;; FP loads take at least 4 clocks. Return two from here... +(define_function_unit "ev6_l" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "fld")) + 2 1) + +;; Motion video insns also issue only to U0, and take three ticks. +(define_function_unit "ev6_u0" 1 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "mvi")) + 3 1) + +(define_function_unit "ev6_u" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "mvi")) + 3 1) + +;; Shifts issue to either upper pipe. +(define_function_unit "ev6_u" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "shift")) + 1 1) + +;; Multiplies issue only to U1, and all take 7 ticks. +;; Rather than create a new function unit just for U1, reuse IMUL +(define_function_unit "imul" 1 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "imul")) + 7 1) + +(define_function_unit "ev6_u" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "imul")) + 7 1) + +;; Branches issue to either upper pipe +(define_function_unit "ev6_u" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "ibr")) + 3 1) + +;; Calls only issue to L0. +(define_function_unit "ev6_l0" 1 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "jsr")) + 1 1) + +(define_function_unit "ev6_l" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "jsr")) + 1 1) + +;; Ftoi/itof only issue to lower pipes +(define_function_unit "ev6_l" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "ftoi")) + 3 1) + +(define_function_unit "ev6_l" 2 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "itof")) + 4 1) + +;; For the FPU we are very similar to EV5, except there's no insn that +;; can issue to fm & fa, so we get to leave that out. + +(define_function_unit "ev6_fm" 1 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "fmul")) + 4 1) + +(define_function_unit "ev6_fa" 1 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "fadd,fcpys,fbr,fdiv,fsqrt")) + 4 1) + +(define_function_unit "ev6_fa" 1 0 + (and (eq_attr "cpu" "ev6") + (eq_attr "type" "fcmov")) + 8 1) + +(define_function_unit "fdiv" 1 0 + (and (eq_attr "cpu" "ev6") + (and (eq_attr "type" "fdiv") + (eq_attr "opsize" "si"))) + 12 10) + +(define_function_unit "fdiv" 1 0 + (and (eq_attr "cpu" "ev6") + (and (eq_attr "type" "fdiv") + (eq_attr "opsize" "di"))) + 15 13) + +(define_function_unit "fsqrt" 1 0 + (and (eq_attr "cpu" "ev6") + (and (eq_attr "type" "fsqrt") + (eq_attr "opsize" "si"))) + 16 14) + +(define_function_unit "fsqrt" 1 0 + (and (eq_attr "cpu" "ev6") + (and (eq_attr "type" "fsqrt") + (eq_attr "opsize" "di"))) + 32 30) + +; ??? The FPU communicates with memory and the integer register file +; via two fp store units. We need a slot in the fst immediately, and +; a slot in LOW after the operand data is ready. At which point the +; data may be moved either to the store queue or the integer register +; file and the insn retired. -(define_function_unit "divider" 1 0 (eq_attr "type" "fdivs") 68 60) -(define_function_unit "divider" 1 0 (eq_attr "type" "fdivt") 126 118) ;; First define the arithmetic insns. Note that the 32-bit forms also ;; sign-extend. -;; Note that we can do sign extensions in both FP and integer registers. -;; However, the result must be in the same type of register as the input. -;; The register preferencing code can't handle this case very well, so, for -;; now, don't let the FP case show up here for preferencing. Also, -;; sign-extends in FP registers take two instructions. +;; Handle 32-64 bit extension from memory to a floating point register +;; specially, since this ocurrs frequently in int->double conversions. +;; This is done with a define_split after reload converting the plain +;; sign-extension into a load+unspec, which of course results in lds+cvtlq. +;; +;; Note that while we must retain the =f case in the insn for reload's +;; benefit, it should be eliminated after reload, so we should never emit +;; code for that case. But we don't reject the possibility. + (define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r,*f") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,*f")))] + [(set (match_operand:DI 0 "register_operand" "=r,r,?f") + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,m")))] "" "@ addl %1,$31,%0 ldl %0,%1 - cvtql %1,%0\;cvtlq %0,%0" - [(set_attr "type" "iaddlog,ld,fpop")]) + lds %0,%1\;cvtlq %0,%0" + [(set_attr "type" "iadd,ild,fld") + (set_attr "length" "*,*,8")]) + +;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here. +(define_split + [(set (match_operand:DI 0 "hard_fp_register_operand" "") + (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))] + "reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (unspec:DI [(match_dup 2)] 4))] + "operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=f") + (unspec:DI [(match_operand:SI 1 "register_operand" "f")] 4))] + "" + "cvtlq %1,%0" + [(set_attr "type" "fadd")]) ;; Do addsi3 the way expand_binop would do if we didn't have one. This ;; generates better code. We have the anonymous addsi3 pattern below in @@ -95,10 +420,10 @@ (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])))); +{ 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; } ") @@ -111,8 +436,7 @@ addl %r1,%2,%0 subl %r1,%n2,%0 lda %0,%2(%r1) - ldah %0,%h2(%r1)" - [(set_attr "type" "iaddlog")]) + ldah %0,%h2(%r1)") (define_split [(set (match_operand:SI 0 "register_operand" "") @@ -139,8 +463,7 @@ "" "@ addl %r1,%2,%0 - subl %r1,%n2,%0" - [(set_attr "type" "iaddlog")]) + subl %r1,%n2,%0") (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -179,8 +502,8 @@ (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 7) (match_dup 4))))] " { - operands[6] = gen_rtx (GET_CODE (operands[1]), DImode, - operands[2], operands[3]); + operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode, + operands[2], operands[3]); operands[7] = gen_lowpart (SImode, operands[5]); }") @@ -193,8 +516,7 @@ addq %r1,%2,%0 subq %r1,%n2,%0 lda %0,%2(%r1) - ldah %0,%h2(%r1)" - [(set_attr "type" "iaddlog")]) + ldah %0,%h2(%r1)") ;; Don't do this if we are adjusting SP since we don't want to do ;; it in two steps. @@ -224,8 +546,7 @@ "" "@ s%2addl %r1,%3,%0 - s%2subl %r1,%n3,%0" - [(set_attr "type" "iaddlog")]) + s%2subl %r1,%n3,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -236,8 +557,7 @@ "" "@ s%2addl %r1,%3,%0 - s%2subl %r1,%n3,%0" - [(set_attr "type" "iaddlog")]) + s%2subl %r1,%n3,%0") (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -255,8 +575,8 @@ (match_dup 5))))] " { - operands[7] = gen_rtx (GET_CODE (operands[1]), DImode, - operands[2], operands[3]); + operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode, + operands[2], operands[3]); operands[8] = gen_lowpart (SImode, operands[6]); }") @@ -268,8 +588,7 @@ "" "@ s%2addq %r1,%3,%0 - s%2subq %1,%n3,%0" - [(set_attr "type" "iaddlog")]) + s%2subq %1,%n3,%0") ;; These variants of the above insns can occur if the third operand ;; is the frame pointer. This is a kludge, but there doesn't @@ -281,8 +600,7 @@ (match_operand:DI 2 "some_operand" "r")) (match_operand:DI 3 "some_operand" "rIOKL")))] "reload_in_progress" - "#" - [(set_attr "type" "iaddlog")]) + "#") (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -301,8 +619,7 @@ (match_operand:SI 3 "some_operand" "r")) (match_operand:SI 4 "some_operand" "rIOKL")))] "reload_in_progress" - "#" - [(set_attr "type" "iaddlog")]) + "#") (define_split [(set (match_operand:SI 0 "register_operand" "r") @@ -325,8 +642,7 @@ (match_operand:SI 3 "some_operand" "r")) (match_operand:SI 4 "some_operand" "rIOKL"))))] "reload_in_progress" - "#" - [(set_attr "type" "iaddlog")]) + "#") (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -351,8 +667,7 @@ (match_operand:DI 3 "some_operand" "r")) (match_operand:DI 4 "some_operand" "rIOKL")))] "reload_in_progress" - "#" - [(set_attr "type" "iaddlog")]) + "#") (define_split [(set (match_operand:DI 0 "register_operand" "=") @@ -370,23 +685,20 @@ [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))] "" - "subl $31,%1,%0" - [(set_attr "type" "iaddlog")]) + "subl $31,%1,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI"))))] "" - "subl $31,%1,%0" - [(set_attr "type" "iaddlog")]) + "subl $31,%1,%0") (define_insn "negdi2" [(set (match_operand:DI 0 "register_operand" "=r") (neg:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] "" - "subq $31,%1,%0" - [(set_attr "type" "iaddlog")]) + "subq $31,%1,%0") (define_expand "subsi3" [(set (match_operand:SI 0 "register_operand" "") @@ -394,12 +706,11 @@ (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])))); +{ 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; - } ") (define_insn "" @@ -407,24 +718,21 @@ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] "" - "subl %r1,%2,%0" - [(set_attr "type" "iaddlog")]) + "subl %r1,%2,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] "" - "subl %r1,%2,%0" - [(set_attr "type" "iaddlog")]) + "subl %r1,%2,%0") (define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] "" - "subq %r1,%2,%0" - [(set_attr "type" "iaddlog")]) + "subq %r1,%2,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -432,8 +740,7 @@ (match_operand:SI 2 "const48_operand" "I")) (match_operand:SI 3 "reg_or_8bit_operand" "rI")))] "" - "s%2subl %r1,%3,%0" - [(set_attr "type" "iaddlog")]) + "s%2subl %r1,%3,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -442,8 +749,7 @@ (match_operand:SI 2 "const48_operand" "I")) (match_operand:SI 3 "reg_or_8bit_operand" "rI"))))] "" - "s%2subl %r1,%3,%0" - [(set_attr "type" "iaddlog")]) + "s%2subl %r1,%3,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -451,8 +757,7 @@ (match_operand:DI 2 "const48_operand" "I")) (match_operand:DI 3 "reg_or_8bit_operand" "rI")))] "" - "s%2subq %r1,%3,%0" - [(set_attr "type" "iaddlog")]) + "s%2subq %r1,%3,%0") (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") @@ -460,7 +765,8 @@ (match_operand:SI 2 "reg_or_0_operand" "rJ")))] "" "mull %r1,%r2,%0" - [(set_attr "type" "imull")]) + [(set_attr "type" "imul") + (set_attr "opsize" "si")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -468,7 +774,8 @@ (match_operand:SI 2 "reg_or_0_operand" "rJ"))))] "" "mull %r1,%r2,%0" - [(set_attr "type" "imull")]) + [(set_attr "type" "imul") + (set_attr "opsize" "si")]) (define_insn "muldi3" [(set (match_operand:DI 0 "register_operand" "=r") @@ -476,7 +783,7 @@ (match_operand:DI 2 "reg_or_0_operand" "rJ")))] "" "mulq %r1,%r2,%0" - [(set_attr "type" "imulq")]) + [(set_attr "type" "imul")]) (define_insn "umuldi3_highpart" [(set (match_operand:DI 0 "register_operand" "=r") @@ -487,7 +794,8 @@ (const_int 64))))] "" "umulh %1,%2,%0" - [(set_attr "type" "imulq")]) + [(set_attr "type" "imul") + (set_attr "opsize" "udi")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -498,61 +806,71 @@ (const_int 64))))] "" "umulh %1,%2,%0" - [(set_attr "type" "imulq")]) + [(set_attr "type" "imul") + (set_attr "opsize" "udi")]) ;; The divide and remainder operations always take their inputs from ;; r24 and r25, put their output in r27, and clobber r23 and r28. +;; ??? Force sign-extension here because some versions of OSF/1 don't +;; 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? + (define_expand "divsi3" - [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) - (parallel [(set (reg:SI 27) - (div:SI (reg:SI 24) - (reg:SI 25))) + [(set (reg:DI 24) + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) + (set (reg:DI 25) + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) + (parallel [(set (reg:DI 27) + (sign_extend:DI (div:SI (reg:DI 24) (reg:DI 25)))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") - (reg:SI 27))] - "" + (subreg:SI (reg:DI 27) 0))] + "!TARGET_OPEN_VMS" "") (define_expand "udivsi3" - [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) - (parallel [(set (reg:SI 27) - (udiv:SI (reg:SI 24) - (reg:SI 25))) + [(set (reg:DI 24) + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) + (set (reg:DI 25) + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) + (parallel [(set (reg:DI 27) + (sign_extend:DI (udiv:SI (reg:DI 24) (reg:DI 25)))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") - (reg:SI 27))] - "" + (subreg:SI (reg:DI 27) 0))] + "!TARGET_OPEN_VMS" "") (define_expand "modsi3" - [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) - (parallel [(set (reg:SI 27) - (mod:SI (reg:SI 24) - (reg:SI 25))) + [(set (reg:DI 24) + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) + (set (reg:DI 25) + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) + (parallel [(set (reg:DI 27) + (sign_extend:DI (mod:SI (reg:DI 24) (reg:DI 25)))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") - (reg:SI 27))] - "" + (subreg:SI (reg:DI 27) 0))] + "!TARGET_OPEN_VMS" "") (define_expand "umodsi3" - [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) - (parallel [(set (reg:SI 27) - (umod:SI (reg:SI 24) - (reg:SI 25))) + [(set (reg:DI 24) + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) + (set (reg:DI 25) + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) + (parallel [(set (reg:DI 27) + (sign_extend:DI (umod:SI (reg:DI 24) (reg:DI 25)))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") - (reg:SI 27))] - "" + (subreg:SI (reg:DI 27) 0))] + "!TARGET_OPEN_VMS" "") (define_expand "divdi3" @@ -565,7 +883,7 @@ (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] - "" + "!TARGET_OPEN_VMS" "") (define_expand "udivdi3" @@ -578,7 +896,7 @@ (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] - "" + "!TARGET_OPEN_VMS" "") (define_expand "moddi3" @@ -591,7 +909,7 @@ (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] - "" + "!TARGET_OPEN_VMS" "") (define_expand "umoddi3" @@ -604,18 +922,21 @@ (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] - "" + "!TARGET_OPEN_VMS" "") +;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as +;; expanded by the assembler. (define_insn "" - [(set (reg:SI 27) - (match_operator:SI 1 "divmod_operator" - [(reg:SI 24) (reg:SI 25)])) + [(set (reg:DI 27) + (sign_extend:DI (match_operator:SI 1 "divmod_operator" + [(reg:DI 24) (reg:DI 25)]))) (clobber (reg:DI 23)) (clobber (reg:DI 28))] - "" + "!TARGET_OPEN_VMS" "%E1 $24,$25,$27" - [(set_attr "type" "isubr")]) + [(set_attr "type" "jsr") + (set_attr "length" "8")]) (define_insn "" [(set (reg:DI 27) @@ -623,9 +944,10 @@ [(reg:DI 24) (reg:DI 25)])) (clobber (reg:DI 23)) (clobber (reg:DI 28))] - "" + "!TARGET_OPEN_VMS" "%E1 $24,$25,$27" - [(set_attr "type" "isubr")]) + [(set_attr "type" "jsr") + (set_attr "length" "8")]) ;; Next are the basic logical operations. These only exist in DImode. @@ -638,12 +960,12 @@ and %r1,%2,%0 bic %r1,%N2,%0 zapnot %r1,%m2,%0" - [(set_attr "type" "iaddlog,iaddlog,shiftcm")]) + [(set_attr "type" "ilog,ilog,shift")]) -;; There are times when we can split and AND into two AND insns. This occurs +;; There are times when we can split an AND into two AND insns. This occurs ;; when we can first clear any bytes and then clear anything else. For ;; example "I & 0xffff07" is "(I & 0xffffff) & 0xffffffffffffff07". -;; Only to this when running on 64-bit host since the computations are +;; Only do this when running on 64-bit host since the computations are ;; too messy otherwise. (define_split @@ -675,43 +997,103 @@ [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" - "zapnot %1,1,%0" - [(set_attr "type" "iaddlog")]) + "and %1,0xff,%0" + [(set_attr "type" "ilog")]) -(define_insn "zero_extendqisi2" +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + "TARGET_BWX" + "@ + and %1,0xff,%0 + ldbu %0,%1" + [(set_attr "type" "ilog,ild")]) + +(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))] + "! TARGET_BWX" + "and %1,0xff,%0" + [(set_attr "type" "ilog")]) + +(define_expand "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] "" - "zapnot %1,1,%0" - [(set_attr "type" "iaddlog")]) + "") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + "TARGET_BWX" + "@ + and %1,0xff,%0 + ldbu %0,%1" + [(set_attr "type" "ilog,ild")]) -(define_insn "zero_extendqidi2" +(define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))] + "! TARGET_BWX" + "and %1,0xff,%0" + [(set_attr "type" "ilog")]) + +(define_expand "zero_extendqidi2" + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI (match_operand:QI 1 "register_operand" "")))] "" - "zapnot %1,1,%0" - [(set_attr "type" "iaddlog")]) + "") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + "TARGET_BWX" + "@ + zapnot %1,3,%0 + ldwu %0,%1" + [(set_attr "type" "shift,ild")]) -(define_insn "zero_extendhisi2" +(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))] - "" + "! TARGET_BWX" "zapnot %1,3,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "shift")]) -(define_insn "zero_extendhidi2" +(define_expand "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] + "" + "") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + "TARGET_BWX" + "@ + zapnot %1,3,%0 + ldwu %0,%1" + [(set_attr "type" "shift,ild")]) + +(define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))] "" "zapnot %1,3,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "shift")]) + +(define_expand "zero_extendhidi2" + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI (match_operand:HI 1 "register_operand" "")))] + "" + "") (define_insn "zero_extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))] "" "zapnot %1,15,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "shift")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -719,7 +1101,7 @@ (match_operand:DI 2 "reg_or_0_operand" "rJ")))] "" "bic %r2,%1,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "ilog")]) (define_insn "iordi3" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -729,14 +1111,14 @@ "@ bis %r1,%2,%0 ornot %r1,%N2,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "ilog")]) (define_insn "one_cmpldi2" [(set (match_operand:DI 0 "register_operand" "=r") (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] "" "ornot $31,%1,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "ilog")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -744,7 +1126,7 @@ (match_operand:DI 2 "reg_or_0_operand" "rJ")))] "" "ornot %r2,%1,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "ilog")]) (define_insn "xordi3" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -754,7 +1136,7 @@ "@ xor %r1,%2,%0 eqv %r1,%N2,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "ilog")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -762,14 +1144,40 @@ (match_operand:DI 2 "register_operand" "rI"))))] "" "eqv %r1,%2,%0" - [(set_attr "type" "iaddlog")]) + [(set_attr "type" "ilog")]) + +;; Handle the FFS insn if we support CIX. + +(define_expand "ffsdi2" + [(set (match_dup 2) + (unspec [(match_operand:DI 1 "register_operand" "")] 1)) + (set (match_dup 3) + (plus:DI (match_dup 2) (const_int 1))) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (eq (match_dup 1) (const_int 0)) + (const_int 0) (match_dup 3)))] + "TARGET_CIX" + " +{ + operands[2] = gen_reg_rtx (DImode); + operands[3] = gen_reg_rtx (DImode); +}") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (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 + ; reuse the existing type name. + [(set_attr "type" "mvi")]) ;; Next come the shifts and the various extract and insert operations. (define_insn "ashldi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") - (match_operand:DI 2 "reg_or_6bit_operand" "P,rI")))] + (match_operand:DI 2 "reg_or_6bit_operand" "P,rS")))] "" "* { @@ -782,9 +1190,11 @@ return \"s%P2addq %r1,0,%0\"; case 1: return \"sll %r1,%2,%0\"; + default: + abort(); } }" - [(set_attr "type" "iaddlog,shiftcm")]) + [(set_attr "type" "iadd,shift")]) ;; ??? The following pattern is made by combine, but earlier phases ;; (specifically flow) can't handle it. This occurs in jump.c. Deal @@ -803,224 +1213,469 @@ ;; else ;; return \"s%P2addl %r1,0,%0\"; ;; }" -;; [(set_attr "type" "iaddlog")]) +;; [(set_attr "type" "iadd")]) (define_insn "lshrdi3" [(set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_6bit_operand" "rI")))] + (match_operand:DI 2 "reg_or_6bit_operand" "rS")))] "" - "srl %r1,%2,%0") + "srl %r1,%2,%0" + [(set_attr "type" "shift")]) (define_insn "ashrdi3" [(set (match_operand:DI 0 "register_operand" "=r") (ashiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_6bit_operand" "rI")))] + (match_operand:DI 2 "reg_or_6bit_operand" "rS")))] "" - "sra %r1,%2,%0") + "sra %r1,%2,%0" + [(set_attr "type" "shift")]) (define_expand "extendqihi2" [(set (match_dup 2) - (ashift:DI (match_operand:QI 1 "register_operand" "") + (ashift:DI (match_operand:QI 1 "some_operand" "") (const_int 56))) (set (match_operand:HI 0 "register_operand" "") (ashiftrt:DI (match_dup 2) (const_int 56)))] "" " -{ operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, operands[1]); +{ + if (TARGET_BWX) + { + emit_insn (gen_extendqihi2x (operands[0], + force_reg (QImode, operands[1]))); + DONE; + } + + /* If we have an unaligned MEM, extend to DImode (which we do + specially) and then copy to the result. */ + if (unaligned_memory_operand (operands[1], HImode)) + { + rtx temp = gen_reg_rtx (DImode); + + emit_insn (gen_extendqidi2 (temp, operands[1])); + emit_move_insn (operands[0], gen_lowpart (HImode, temp)); + DONE; + } + + operands[0] = gen_lowpart (DImode, operands[0]); + operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); operands[2] = gen_reg_rtx (DImode); }") +(define_insn "extendqidi2x" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (match_operand:QI 1 "register_operand" "r")))] + "TARGET_BWX" + "sextb %1,%0" + [(set_attr "type" "shift")]) + +(define_insn "extendhidi2x" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (match_operand:HI 1 "register_operand" "r")))] + "TARGET_BWX" + "sextw %1,%0" + [(set_attr "type" "shift")]) + +(define_insn "extendqisi2x" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] + "TARGET_BWX" + "sextb %1,%0" + [(set_attr "type" "shift")]) + +(define_insn "extendhisi2x" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] + "TARGET_BWX" + "sextw %1,%0" + [(set_attr "type" "shift")]) + +(define_insn "extendqihi2x" + [(set (match_operand:HI 0 "register_operand" "=r") + (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] + "TARGET_BWX" + "sextb %1,%0" + [(set_attr "type" "shift")]) + (define_expand "extendqisi2" [(set (match_dup 2) - (ashift:DI (match_operand:QI 1 "register_operand" "") + (ashift:DI (match_operand:QI 1 "some_operand" "") (const_int 56))) (set (match_operand:SI 0 "register_operand" "") (ashiftrt:DI (match_dup 2) (const_int 56)))] "" " -{ operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, operands[1]); +{ + if (TARGET_BWX) + { + emit_insn (gen_extendqisi2x (operands[0], + force_reg (QImode, operands[1]))); + DONE; + } + + /* If we have an unaligned MEM, extend to a DImode form of + the result (which we do specially). */ + if (unaligned_memory_operand (operands[1], QImode)) + { + rtx temp = gen_reg_rtx (DImode); + + emit_insn (gen_extendqidi2 (temp, operands[1])); + emit_move_insn (operands[0], gen_lowpart (SImode, temp)); + DONE; + } + + operands[0] = gen_lowpart (DImode, operands[0]); + operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); operands[2] = gen_reg_rtx (DImode); }") (define_expand "extendqidi2" [(set (match_dup 2) - (ashift:DI (match_operand:QI 1 "register_operand" "") + (ashift:DI (match_operand:QI 1 "some_operand" "") (const_int 56))) (set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_dup 2) (const_int 56)))] "" " -{ operands[1] = gen_lowpart (DImode, operands[1]); +{ + if (TARGET_BWX) + { + emit_insn (gen_extendqidi2x (operands[0], + force_reg (QImode, operands[1]))); + DONE; + } + + if (unaligned_memory_operand (operands[1], QImode)) + { + rtx seq + = gen_unaligned_extendqidi (operands[0], + get_unaligned_address (operands[1], 1)); + + alpha_set_memflags (seq, operands[1]); + emit_insn (seq); + DONE; + } + + operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); operands[2] = gen_reg_rtx (DImode); }") (define_expand "extendhisi2" [(set (match_dup 2) - (ashift:DI (match_operand:HI 1 "register_operand" "") + (ashift:DI (match_operand:HI 1 "some_operand" "") (const_int 48))) (set (match_operand:SI 0 "register_operand" "") (ashiftrt:DI (match_dup 2) (const_int 48)))] "" " -{ operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, operands[1]); +{ + if (TARGET_BWX) + { + emit_insn (gen_extendhisi2x (operands[0], + force_reg (HImode, operands[1]))); + DONE; + } + + /* If we have an unaligned MEM, extend to a DImode form of + the result (which we do specially). */ + if (unaligned_memory_operand (operands[1], HImode)) + { + rtx temp = gen_reg_rtx (DImode); + + emit_insn (gen_extendhidi2 (temp, operands[1])); + emit_move_insn (operands[0], gen_lowpart (SImode, temp)); + DONE; + } + + operands[0] = gen_lowpart (DImode, operands[0]); + operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1])); operands[2] = gen_reg_rtx (DImode); }") (define_expand "extendhidi2" [(set (match_dup 2) - (ashift:DI (match_operand:HI 1 "register_operand" "") + (ashift:DI (match_operand:HI 1 "some_operand" "") (const_int 48))) (set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_dup 2) (const_int 48)))] "" " -{ operands[1] = gen_lowpart (DImode, operands[1]); +{ + if (TARGET_BWX) + { + emit_insn (gen_extendhidi2x (operands[0], + force_reg (HImode, operands[1]))); + DONE; + } + + if (unaligned_memory_operand (operands[1], HImode)) + { + rtx seq + = gen_unaligned_extendhidi (operands[0], + get_unaligned_address (operands[1], 2)); + + alpha_set_memflags (seq, operands[1]); + emit_insn (seq); + DONE; + } + + operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1])); operands[2] = gen_reg_rtx (DImode); }") +;; Here's how we sign extend an unaligned byte and halfword. Doing this +;; as a pattern saves one instruction. The code is similar to that for +;; the unaligned loads (see below). +;; +;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result. +(define_expand "unaligned_extendqidi" + [(set (match_dup 2) (match_operand:DI 1 "address_operand" "")) + (set (match_dup 3) + (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1)) + (const_int -8)))) + (set (match_dup 4) + (ashift:DI (match_dup 3) + (minus:DI (const_int 56) + (ashift:DI + (and:DI (plus:DI (match_dup 2) (const_int -1)) + (const_int 7)) + (const_int 3))))) + (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) + (ashiftrt:DI (match_dup 4) (const_int 56)))] + "" + " +{ operands[2] = gen_reg_rtx (DImode); + operands[3] = gen_reg_rtx (DImode); + operands[4] = gen_reg_rtx (DImode); +}") + +(define_expand "unaligned_extendhidi" + [(set (match_dup 2) (match_operand:DI 1 "address_operand" "")) + (set (match_dup 3) + (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2)) + (const_int -8)))) + (set (match_dup 4) + (ashift:DI (match_dup 3) + (minus:DI (const_int 56) + (ashift:DI + (and:DI (plus:DI (match_dup 2) (const_int -1)) + (const_int 7)) + (const_int 3))))) + (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) + (ashiftrt:DI (match_dup 4) (const_int 48)))] + "" + " +{ operands[2] = gen_reg_rtx (DImode); + operands[3] = gen_reg_rtx (DImode); + operands[4] = gen_reg_rtx (DImode); +}") + (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") (match_operand:DI 2 "mode_width_operand" "n") (match_operand:DI 3 "mul8_operand" "I")))] "" - "ext%M2l %r1,%s3,%0") + "ext%M2l %r1,%s3,%0" + [(set_attr "type" "shift")]) -(define_insn "" +(define_insn "extxl" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") (match_operand:DI 2 "mode_width_operand" "n") (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI") (const_int 3))))] "" - "ext%M2l %r1,%3,%0") + "ext%M2l %r1,%3,%0" + [(set_attr "type" "shift")]) -(define_insn "" +(define_insn "extqh" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI - (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 8) - (ashift:DI - (plus:DI - (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int -1)) - (const_int 3))) - (const_int 56)))] - "" - "extqh %r1,%2,%0") - -(define_insn "" + (match_operand:DI 1 "reg_or_0_operand" "rJ") + (minus:DI (const_int 56) + (ashift:DI + (and:DI + (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) + (const_int 7)) + (const_int 3)))))] + "" + "extqh %r1,%2,%0" + [(set_attr "type" "shift")]) + +(define_insn "extlh" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI - (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 16) - (ashift:DI - (plus:DI - (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int -2)) - (const_int 3))) - (const_int 48)))] - "" - "extwh %r1,%2,%0") - -(define_insn "" + (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 2147483647)) + (minus:DI (const_int 56) + (ashift:DI + (and:DI + (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) + (const_int 7)) + (const_int 3)))))] + "" + "extlh %r1,%2,%0" + [(set_attr "type" "shift")]) + +(define_insn "extwh" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI - (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 32) - (ashift:DI - (plus:DI - (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int -4)) - (const_int 3))) - (const_int 32)))] - "" - "extlh %r1,%2,%0") + (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 65535)) + (minus:DI (const_int 56) + (ashift:DI + (and:DI + (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) + (const_int 7)) + (const_int 3)))))] + "" + "extwh %r1,%2,%0" + [(set_attr "type" "shift")]) ;; This converts an extXl into an extXh with an appropriate adjustment ;; to the address calculation. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "mode_width_operand" "") - (ashift:DI (match_operand:DI 3 "" "") - (const_int 3))) - (match_operand:DI 4 "const_int_operand" ""))) - (clobber (match_operand:DI 5 "register_operand" ""))] - "INTVAL (operands[4]) == 64 - INTVAL (operands[2])" - [(set (match_dup 5) (match_dup 6)) - (set (match_dup 0) - (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2) - (ashift:DI (plus:DI (match_dup 5) - (match_dup 7)) - (const_int 3))) - (match_dup 4)))] - " -{ - operands[6] = plus_constant (operands[3], - INTVAL (operands[2]) / BITS_PER_UNIT); - operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT); -}") +;;(define_split +;; [(set (match_operand:DI 0 "register_operand" "") +;; (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "") +;; (match_operand:DI 2 "mode_width_operand" "") +;; (ashift:DI (match_operand:DI 3 "" "") +;; (const_int 3))) +;; (match_operand:DI 4 "const_int_operand" ""))) +;; (clobber (match_operand:DI 5 "register_operand" ""))] +;; "INTVAL (operands[4]) == 64 - INTVAL (operands[2])" +;; [(set (match_dup 5) (match_dup 6)) +;; (set (match_dup 0) +;; (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2) +;; (ashift:DI (plus:DI (match_dup 5) +;; (match_dup 7)) +;; (const_int 3))) +;; (match_dup 4)))] +;; " +;;{ +;; operands[6] = plus_constant (operands[3], +;; INTVAL (operands[2]) / BITS_PER_UNIT); +;; operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT); +;;}") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) (match_operand:DI 2 "mul8_operand" "I")))] "" - "insbl %1,%s2,%0") + "insbl %1,%s2,%0" + [(set_attr "type" "shift")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) (match_operand:DI 2 "mul8_operand" "I")))] "" - "inswl %1,%s2,%0") + "inswl %1,%s2,%0" + [(set_attr "type" "shift")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (match_operand:DI 2 "mul8_operand" "I")))] "" - "insll %1,%s2,%0") + "insll %1,%s2,%0" + [(set_attr "type" "shift")]) -(define_insn "" +(define_insn "insbl" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") (const_int 3))))] "" - "insbl %1,%2,%0") + "insbl %1,%2,%0" + [(set_attr "type" "shift")]) -(define_insn "" +(define_insn "inswl" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") (const_int 3))))] "" - "inswl %1,%2,%0") + "inswl %1,%2,%0" + [(set_attr "type" "shift")]) -(define_insn "" +(define_insn "insll" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") (const_int 3))))] "" - "insll %1,%2,%0") + "insll %1,%2,%0" + [(set_attr "type" "shift")]) + +(define_insn "insql" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (match_operand:DI 1 "register_operand" "r") + (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int 3))))] + "" + "insql %1,%2,%0" + [(set_attr "type" "shift")]) + +;; Combine has this sometimes habit of moving the and outside of the +;; shift, making life more interesting. + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "mul8_operand" "I")) + (match_operand:DI 3 "immediate_operand" "i")))] + "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) 0xffff << INTVAL (operands[2]) + == INTVAL (operands[3])) + || ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2]) + == INTVAL (operands[3])))" + "* +{ +#if HOST_BITS_PER_WIDE_INT == 64 + if ((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2]) + == INTVAL (operands[3])) + return \"insbl %1,%s2,%0\"; + if ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2]) + == INTVAL (operands[3])) + return \"inswl %1,%s2,%0\"; + if ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2]) + == INTVAL (operands[3])) + return \"insll %1,%s2,%0\"; +#endif + abort(); +}" + [(set_attr "type" "shift")]) ;; We do not include the insXh insns because they are complex to express ;; and it does not appear that we would ever want to generate them. +;; +;; Since we need them for block moves, though, cop out and use unspec. -(define_insn "" +(define_insn "insxh" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "mode_width_operand" "n") + (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 2))] + "" + "ins%M2h %1,%3,%0" + [(set_attr "type" "shift")]) + +(define_insn "mskxl" [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (not:DI (ashift:DI (match_operand:DI 2 "mode_mask_operand" "n") @@ -1029,10 +1684,22 @@ (const_int 3)))) (match_operand:DI 1 "reg_or_0_operand" "rJ")))] "" - "msk%U2l %r1,%3,%0") + "msk%U2l %r1,%3,%0" + [(set_attr "type" "shift")]) -;; We do not include the mskXh insns because it does not appear we would ever -;; generate one. +;; We do not include the mskXh insns because it does not appear we would +;; ever generate one. +;; +;; Again, we do for block moves and we use unspec again. + +(define_insn "mskxh" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "mode_width_operand" "n") + (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 3))] + "" + "msk%M2h %1,%3,%0" + [(set_attr "type" "shift")]) ;; Floating-point operations. All the double-precision insns can extend ;; from single, so indicate that. The exception are the ones that simply @@ -1043,53 +1710,74 @@ (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "cpys $f31,%R1,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcpys")]) (define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "cpys $f31,%R1,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcpys")]) (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "cpysn %R1,%R1,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fadd")]) (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "cpysn %R1,%R1,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fadd")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=&f") + (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "add%,%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f") (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "adds %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "add%,%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "add%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f") (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "addt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "add%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (plus:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "addt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "add%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -1097,120 +1785,344 @@ (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "add%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +;; Define conversion operators between DFmode and SImode, using the cvtql +;; 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. + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" ""))) + (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))] + "") + +;; 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" "")))] + "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]));") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=f") + (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))] "TARGET_FP" - "addt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "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"))] + "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")))] + "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") + (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cvt%-q%(c %R1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "fix_truncdfdi2" [(set (match_operand:DI 0 "register_operand" "=f") (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "cvttqc %R1,%0" - [(set_attr "type" "fpop")]) + "cvt%-q%(c %R1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +;; 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 ""))] + "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))] + "") + +;; 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" ""))))] + "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"))] + "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"))))] + "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") + (fix:DI (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cvt%-q%(c %R1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "fix_truncsfdi2" [(set (match_operand:DI 0 "register_operand" "=f") (fix:DI (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] "TARGET_FP" - "cvttqc %R1,%0" - [(set_attr "type" "fpop")]) + "cvt%-q%(c %R1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=&f") + (float:SF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cvtq%,%+%& %1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "floatdisf2" [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:DI 1 "register_operand" "f")))] "TARGET_FP" - "cvtqs %1,%0" - [(set_attr "type" "fpop")]) + "cvtq%,%+%& %1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (float:DF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cvtq%-%+%& %1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "floatdidf2" [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:DI 1 "register_operand" "f")))] "TARGET_FP" - "cvtqt %1,%0" - [(set_attr "type" "fpop")]) + "cvtq%-%+%& %1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m")))] +(define_expand "extendsfdf2" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:SF 1 "nonimmediate_operand" ""))] "TARGET_FP" +" +{ + if (alpha_tp == ALPHA_TP_INSN) + emit_insn (gen_extendsfdf2_tp (operands[0], + force_reg (SFmode, operands[1]))); + else + emit_insn (gen_extendsfdf2_no_tp (operands[0], operands[1])); + + DONE; +}") +;; FIXME +(define_insn "extendsfdf2_tp" + [(set (match_operand:DF 0 "register_operand" "=&f") + (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cvtsts %1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "extendsfdf2_no_tp" + [(set (match_operand:DF 0 "register_operand" "=f,f,m") + (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))] + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" "@ - addt $f31,%1,%0 - lds %0,%1" - [(set_attr "type" "fpop,ld")]) + cpys %1,%1,%0 + ld%, %0,%1 + st%- %1,%0" + [(set_attr "type" "fcpys,fld,fst") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=&f") + (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cvt%-%,%)%& %R1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "cvtts %R1,%0" - [(set_attr "type" "fpop")]) + "cvt%-%,%)%& %R1,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=&f") + (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "div%,%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "opsize" "si") + (set_attr "trap" "yes")]) (define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f") (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "divs %R1,%R2,%0" - [(set_attr "type" "fdivs")]) + "div%,%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "opsize" "si") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "div%-%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "trap" "yes")]) (define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "divt %R1,%R2,%0" - [(set_attr "type" "fdivt")]) + "div%-%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "divt %R1,%R2,%0" - [(set_attr "type" "fdivt")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "div%-%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP" - "divt %R1,%R2,%0" - [(set_attr "type" "fdivt")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "div%-%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP" - "divt %R1,%R2,%0" - [(set_attr "type" "fdivt")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "div%-%)%& %R1,%R2,%0" + [(set_attr "type" "fdiv") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=&f") + (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "mul%,%)%& %R1,%R2,%0" + [(set_attr "type" "fmul") + (set_attr "trap" "yes")]) (define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "muls %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "mul%,%)%& %R1,%R2,%0" + [(set_attr "type" "fmul") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "mul%-%)%& %R1,%R2,%0" + [(set_attr "type" "fmul") + (set_attr "trap" "yes")]) (define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "mult %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "mul%-%)%& %R1,%R2,%0" + [(set_attr "type" "fmul") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (mult:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "mult %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "mul%-%)%& %R1,%R2,%0" + [(set_attr "type" "fmul") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -1218,43 +2130,66 @@ (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP" - "mult %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "mul%-%)%& %R1,%R2,%0" + [(set_attr "type" "fmul") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=&f") + (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "sub%,%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f") (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "subs %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "sub%,%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "sub%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "subt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "sub%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "subt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "sub%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP" - "subt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "sub%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -1262,9 +2197,44 @@ (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP" - "subt %R1,%R2,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "sub%-%)%& %R1,%R2,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(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" + "sqrt%,%)%& %R1,%0" + [(set_attr "type" "fsqrt") + (set_attr "opsize" "si") + (set_attr "trap" "yes")]) + +(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" + "sqrt%,%)%& %R1,%0" + [(set_attr "type" "fsqrt") + (set_attr "opsize" "si") + (set_attr "trap" "yes")]) + +(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" + "sqrt%-%)%& %R1,%0" + [(set_attr "type" "fsqrt") + (set_attr "trap" "yes")]) + +(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" + "sqrt%-%)%& %1,%0" + [(set_attr "type" "fsqrt") + (set_attr "trap" "yes")]) ;; Next are all the integer comparisons, and conditional moves and branches ;; and some of the related define_expand's and define_split's. @@ -1278,31 +2248,13 @@ "cmp%C1 %r2,%3,%0" [(set_attr "type" "icmp")]) -;; There are three important special-case that don't fit the above pattern -;; but which we want to handle here. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ne:DI (match_operand:DI 1 "register_operand" "r") - (const_int 0)))] - "" - "cmpult $31,%1,%0" - [(set_attr "type" "icmp")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt:DI (match_operand:DI 1 "register_operand" "r") - (const_int 0)))] - "" - "cmplt $31,%1,%0" - [(set_attr "type" "icmp")]) - (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") - (ge:DI (match_operand:DI 1 "register_operand" "r") - (const_int 0)))] + (match_operator:DI 1 "alpha_swapped_comparison_operator" + [(match_operand:DI 2 "reg_or_8bit_operand" "rI") + (match_operand:DI 3 "reg_or_0_operand" "rJ")]))] "" - "cmple $31,%1,%0" + "cmp%c1 %r3,%2,%0" [(set_attr "type" "icmp")]) ;; This pattern exists so conditional moves of SImode values are handled. @@ -1321,7 +2273,8 @@ cmov%C2 %r3,%1,%0 cmov%D2 %r3,%5,%0 cmov%c2 %r4,%1,%0 - cmov%d2 %r4,%5,%0") + cmov%d2 %r4,%5,%0" + [(set_attr "type" "icmov")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") @@ -1336,7 +2289,8 @@ cmov%C2 %r3,%1,%0 cmov%D2 %r3,%5,%0 cmov%c2 %r4,%1,%0 - cmov%d2 %r4,%5,%0") + cmov%d2 %r4,%5,%0" + [(set_attr "type" "icmov")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -1350,7 +2304,8 @@ "" "@ cmovlbc %r2,%1,%0 - cmovlbs %r2,%3,%0") + cmovlbs %r2,%3,%0" + [(set_attr "type" "icmov")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -1364,7 +2319,8 @@ "" "@ cmovlbs %r2,%1,%0 - cmovlbc %r2,%3,%0") + 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 @@ -1382,7 +2338,9 @@ (match_dup 0))) (clobber (match_scratch:DI 4 "=&r"))] "" - "addq %0,%1,%4\;cmov%C2 %r3,%4,%0") + "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" "") @@ -1500,6 +2458,70 @@ (match_dup 0) (match_dup 1)))] "") +(define_insn "sminqi3" + [(set (match_operand:QI 0 "register_operand" "=r") + (smin:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ") + (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "minsb8 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "uminqi3" + [(set (match_operand:QI 0 "register_operand" "=r") + (umin:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ") + (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "minub8 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "smaxqi3" + [(set (match_operand:QI 0 "register_operand" "=r") + (smax:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ") + (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "maxsb8 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "umaxqi3" + [(set (match_operand:QI 0 "register_operand" "=r") + (umax:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ") + (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "maxub8 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "sminhi3" + [(set (match_operand:HI 0 "register_operand" "=r") + (smin:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ") + (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "minsw4 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "uminhi3" + [(set (match_operand:HI 0 "register_operand" "=r") + (umin:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ") + (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "minuw4 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "smaxhi3" + [(set (match_operand:HI 0 "register_operand" "=r") + (smax:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ") + (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "maxsw4 %r1,%2,%0" + [(set_attr "type" "mvi")]) + +(define_insn "umaxhi3" + [(set (match_operand:HI 0 "register_operand" "=r") + (umax:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ") + (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] + "TARGET_MAX" + "maxuw4 %r1,%2,%0" + [(set_attr "type" "shift")]) + (define_expand "smaxdi3" [(set (match_dup 3) (le:DI (match_operand:DI 1 "reg_or_0_operand" "") @@ -1528,7 +2550,8 @@ (smax:DI (match_operand:DI 1 "register_operand" "0") (const_int 0)))] "" - "cmovlt %0,0,%0") + "cmovlt %0,0,%0" + [(set_attr "type" "icmov")]) (define_expand "smindi3" [(set (match_dup 3) @@ -1558,7 +2581,8 @@ (smin:DI (match_operand:DI 1 "register_operand" "0") (const_int 0)))] "" - "cmovgt %0,0,%0") + "cmovgt %0,0,%0" + [(set_attr "type" "icmov")]) (define_expand "umaxdi3" [(set (match_dup 3) @@ -1621,6 +2645,18 @@ (define_insn "" [(set (pc) (if_then_else + (match_operator 1 "signed_comparison_operator" + [(const_int 0) + (match_operand:DI 2 "register_operand" "r")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "b%c1 %2,%0" + [(set_attr "type" "ibr")]) + +(define_insn "" + [(set (pc) + (if_then_else (ne (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") (const_int 1) (const_int 0)) @@ -1674,13 +2710,35 @@ ;; to DFmode. (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (match_operator:DF 1 "alpha_comparison_operator" + [(match_operand:DF 2 "reg_or_fp0_operand" "fG") + (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (match_operator:DF 1 "alpha_comparison_operator" [(match_operand:DF 2 "reg_or_fp0_operand" "fG") (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] - "TARGET_FP" - "cmpt%C1 %R2,%R3,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (match_operator:DF 1 "alpha_comparison_operator" + [(float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG")) + (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -1688,9 +2746,21 @@ [(float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG")) (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] - "TARGET_FP" - "cmpt%C1 %R2,%R3,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (match_operator:DF 1 "alpha_comparison_operator" + [(match_operand:DF 2 "reg_or_fp0_operand" "fG") + (float_extend:DF + (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -1698,9 +2768,22 @@ [(match_operand:DF 2 "reg_or_fp0_operand" "fG") (float_extend:DF (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] - "TARGET_FP" - "cmpt%C1 %R2,%R3,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=&f") + (match_operator:DF 1 "alpha_comparison_operator" + [(float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG")) + (float_extend:DF + (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] + "TARGET_FP && alpha_tp == ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -1709,9 +2792,10 @@ (match_operand:SF 2 "reg_or_fp0_operand" "fG")) (float_extend:DF (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] - "TARGET_FP" - "cmpt%C1 %R2,%R3,%0" - [(set_attr "type" "fpop")]) + "TARGET_FP && alpha_tp != ALPHA_TP_INSN" + "cmp%-%C1%' %R2,%R3,%0" + [(set_attr "type" "fadd") + (set_attr "trap" "yes")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") @@ -1725,7 +2809,7 @@ "@ fcmov%C3 %R4,%R1,%0 fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcmov")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") @@ -1739,21 +2823,21 @@ "@ fcmov%C3 %R4,%R1,%0 fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcmov")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF (match_operator 3 "signed_comparison_operator" - [(match_operand:DF 1 "reg_or_fp0_operand" "fG,fG") + [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") (match_operand:DF 2 "fp0_operand" "G,G")]) - (float_extend:DF (match_operand:SF 4 "reg_or_fp0_operand" "fG,0")) + (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")) (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] "TARGET_FP" "@ fcmov%C3 %R4,%R1,%0 fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcmov")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") @@ -1768,7 +2852,7 @@ "@ fcmov%C3 %R4,%R1,%0 fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcmov")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") @@ -1783,7 +2867,7 @@ "@ fcmov%C3 %R4,%R1,%0 fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcmov")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") @@ -1798,7 +2882,7 @@ "@ fcmov%C3 %R4,%R1,%0 fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fpop")]) + [(set_attr "type" "fcmov")]) (define_expand "maxdf3" [(set (match_dup 3) @@ -1905,198 +2989,84 @@ }") (define_expand "beq" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - enum machine_mode mode; - enum rtx_code compare_code, branch_code; - - if (alpha_compare_fp_p) - mode = DFmode, compare_code = EQ, branch_code = NE; - else - { - mode = DImode, compare_code = MINUS, branch_code = EQ; - if (GET_CODE (alpha_compare_op1) == CONST_INT) - { - compare_code = PLUS; - alpha_compare_op1 = GEN_INT (- INTVAL (alpha_compare_op1)); - } - } - - operands[1] = gen_reg_rtx (mode); - operands[2] = gen_rtx (compare_code, mode, - alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (branch_code, VOIDmode, - operands[1], CONST0_RTX (mode)); -}") + "{ operands[1] = alpha_emit_conditional_branch (EQ); }") (define_expand "bne" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - enum machine_mode mode; - enum rtx_code compare_code, branch_code; - - if (alpha_compare_fp_p) - mode = DFmode, compare_code = EQ, branch_code = EQ; - else - { - mode = DImode, compare_code = MINUS, branch_code = NE; - if (GET_CODE (alpha_compare_op1) == CONST_INT) - { - compare_code = PLUS; - alpha_compare_op1 = GEN_INT (- INTVAL (alpha_compare_op1)); - } - } - - operands[1] = gen_reg_rtx (mode); - operands[2] = gen_rtx (compare_code, mode, - alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (branch_code, VOIDmode, - operands[1], CONST0_RTX (mode)); -}") + "{ operands[1] = alpha_emit_conditional_branch (NE); }") (define_expand "blt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode; - operands[1] = gen_reg_rtx (mode); - operands[2] = gen_rtx (LT, mode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode)); -}") + "{ operands[1] = alpha_emit_conditional_branch (LT); }") (define_expand "ble" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode; - operands[1] = gen_reg_rtx (mode); - operands[2] = gen_rtx (LE, mode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode)); -}") + "{ operands[1] = alpha_emit_conditional_branch (LE); }") (define_expand "bgt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - if (alpha_compare_fp_p) - { - operands[1] = gen_reg_rtx (DFmode); - operands[2] = gen_rtx (LT, DFmode, alpha_compare_op1, alpha_compare_op0); - operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (DFmode)); - } - else - { - operands[1] = gen_reg_rtx (DImode); - operands[2] = gen_rtx (LE, DImode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); - } -}") + "{ operands[1] = alpha_emit_conditional_branch (GT); }") (define_expand "bge" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - if (alpha_compare_fp_p) - { - operands[1] = gen_reg_rtx (DFmode); - operands[2] = gen_rtx (LE, DFmode, alpha_compare_op1, alpha_compare_op0); - operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (DFmode)); - } - else - { - operands[1] = gen_reg_rtx (DImode); - operands[2] = gen_rtx (LT, DImode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); - } -}") + "{ operands[1] = alpha_emit_conditional_branch (GE); }") (define_expand "bltu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - operands[1] = gen_reg_rtx (DImode); - operands[2] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (NE, VOIDmode, operands[1], const0_rtx); -}") + "{ operands[1] = alpha_emit_conditional_branch (LTU); }") (define_expand "bleu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - operands[1] = gen_reg_rtx (DImode); - operands[2] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (NE, VOIDmode, operands[1], const0_rtx); -}") + "{ operands[1] = alpha_emit_conditional_branch (LEU); }") (define_expand "bgtu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - operands[1] = gen_reg_rtx (DImode); - operands[2] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); -}") + "{ operands[1] = alpha_emit_conditional_branch (GTU); }") (define_expand "bgeu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) + [(set (pc) + (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" - " -{ - operands[1] = gen_reg_rtx (DImode); - operands[2] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1); - operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); -}") + "{ operands[1] = alpha_emit_conditional_branch (GEU); }") (define_expand "seq" [(set (match_operand:DI 0 "register_operand" "") @@ -2107,7 +3077,7 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (EQ, DImode, alpha_compare_op0, alpha_compare_op1); + operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1); }") (define_expand "sne" @@ -2120,7 +3090,7 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (EQ, DImode, alpha_compare_op0, alpha_compare_op1); + operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1); }") (define_expand "slt" @@ -2132,7 +3102,7 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LT, DImode, alpha_compare_op0, alpha_compare_op1); + operands[1] = gen_rtx_LT (DImode, alpha_compare_op0, alpha_compare_op1); }") (define_expand "sle" @@ -2144,7 +3114,7 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LE, DImode, alpha_compare_op0, alpha_compare_op1); + operands[1] = gen_rtx_LE (DImode, alpha_compare_op0, alpha_compare_op1); }") (define_expand "sgt" @@ -2156,8 +3126,8 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LT, DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); + operands[1] = gen_rtx_LT (DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); }") (define_expand "sge" @@ -2169,8 +3139,8 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LE, DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); + operands[1] = gen_rtx_LE (DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); }") (define_expand "sltu" @@ -2182,7 +3152,7 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1); + operands[1] = gen_rtx_LTU (DImode, alpha_compare_op0, alpha_compare_op1); }") (define_expand "sleu" @@ -2194,7 +3164,7 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1); + operands[1] = gen_rtx_LEU (DImode, alpha_compare_op0, alpha_compare_op1); }") (define_expand "sgtu" @@ -2206,8 +3176,8 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LTU, DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); + operands[1] = gen_rtx_LTU (DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); }") (define_expand "sgeu" @@ -2219,184 +3189,58 @@ if (alpha_compare_fp_p) FAIL; - operands[1] = gen_rtx (LEU, DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); + operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); }") ;; These are the main define_expand's used to make conditional moves. (define_expand "movsicc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:SI 0 "register_operand" "") - (if_then_else:DI (match_dup 5) + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:DI (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "reg_or_8bit_operand" "") (match_operand:SI 3 "reg_or_8bit_operand" "")))] "" " { - rtx op0,op1; - enum rtx_code code = GET_CODE (operands[1]), code2 = NE; - - if (alpha_compare_fp_p) + if ((operands[1] = alpha_emit_conditional_move (operands[1], SImode)) == 0) FAIL; - switch (code) - { - case EQ: case LE: case LT: - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case NE: - code = code2 = EQ; - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case GE: - code = LE; - op0 = force_reg (DImode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - case GT: - code = LT; - op0 = force_reg (DImode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - default: - FAIL; - } - operands[1] = gen_rtx (code, DImode, op0, op1); - operands[4] = gen_reg_rtx (DImode); - operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DImode)); }") (define_expand "movdicc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_dup 5) + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (match_operand 1 "comparison_operator" "") (match_operand:DI 2 "reg_or_8bit_operand" "") (match_operand:DI 3 "reg_or_8bit_operand" "")))] "" " { - rtx op0,op1; - enum rtx_code code = GET_CODE (operands[1]), code2 = NE; - - if (alpha_compare_fp_p) + if ((operands[1] = alpha_emit_conditional_move (operands[1], DImode)) == 0) FAIL; - switch (code) - { - case EQ: case LE: case LT: - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case NE: - code = code2 = EQ; - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case GE: - code = LE; - op0 = force_reg (DImode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - case GT: - code = LT; - op0 = force_reg (DImode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - default: - FAIL; - } - operands[1] = gen_rtx (code, DImode, op0, op1); - operands[4] = gen_reg_rtx (DImode); - operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DImode)); }") (define_expand "movsfcc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_dup 5) - (match_operand:SF 2 "reg_or_fp0_operand" "") - (match_operand:SF 3 "reg_or_fp0_operand" "")))] + [(set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "reg_or_8bit_operand" "") + (match_operand:SF 3 "reg_or_8bit_operand" "")))] "" " { - rtx op0,op1; - enum rtx_code code = GET_CODE (operands[1]), code2 = NE; - - if (!alpha_compare_fp_p) + if ((operands[1] = alpha_emit_conditional_move (operands[1], SFmode)) == 0) FAIL; - switch (code) - { - case EQ: case LE: case LT: - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case NE: - /* There isn't a cmptne insn. */ - code = code2 = EQ; - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case GE: - code = LE; - op0 = force_reg (DFmode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - case GT: - code = LT; - op0 = force_reg (DFmode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - default: - FAIL; - } - operands[1] = gen_rtx (code, DFmode, op0, op1); - operands[4] = gen_reg_rtx (DFmode); - operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DFmode)); }") (define_expand "movdfcc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_dup 5) - (match_operand:DF 2 "reg_or_fp0_operand" "") - (match_operand:DF 3 "reg_or_fp0_operand" "")))] + [(set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (match_operand 1 "comparison_operator" "") + (match_operand:DF 2 "reg_or_8bit_operand" "") + (match_operand:DF 3 "reg_or_8bit_operand" "")))] "" " { - rtx op0,op1; - enum rtx_code code = GET_CODE (operands[1]), code2 = NE; - - if (!alpha_compare_fp_p) + if ((operands[1] = alpha_emit_conditional_move (operands[1], DFmode)) == 0) FAIL; - switch (code) - { - case EQ: case LE: case LT: - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case NE: - /* There isn't a cmptne insn. */ - code = code2 = EQ; - op0 = alpha_compare_op0; - op1 = alpha_compare_op1; - break; - case GE: - code = LE; - op0 = force_reg (DFmode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - case GT: - code = LT; - op0 = force_reg (DFmode, alpha_compare_op1); - op1 = alpha_compare_op0; - break; - default: - FAIL; - } - operands[1] = gen_rtx (code, DFmode, op0, op1); - operands[4] = gen_reg_rtx (DFmode); - operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DFmode)); }") ;; These define_split definitions are used in cases when comparisons have @@ -2451,25 +3295,25 @@ && extended_count (operands[3], DImode, unsignedp) >= 1)) { if (GET_CODE (operands[3]) == CONST_INT) - operands[7] = gen_rtx (PLUS, DImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); + operands[7] = gen_rtx_PLUS (DImode, operands[2], + GEN_INT (- INTVAL (operands[3]))); else - operands[7] = gen_rtx (MINUS, DImode, operands[2], operands[3]); + operands[7] = gen_rtx_MINUS (DImode, operands[2], operands[3]); - operands[8] = gen_rtx (code, VOIDmode, operands[6], const0_rtx); + operands[8] = gen_rtx_fmt_ee (code, VOIDmode, operands[6], const0_rtx); } else if (code == EQ || code == LE || code == LT || code == LEU || code == LTU) { - operands[7] = gen_rtx (code, DImode, operands[2], operands[3]); - operands[8] = gen_rtx (NE, VOIDmode, operands[6], const0_rtx); + operands[7] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]); + operands[8] = gen_rtx_NE (VOIDmode, operands[6], const0_rtx); } else { - operands[7] = gen_rtx (reverse_condition (code), DImode, operands[2], - operands[3]); - operands[8] = gen_rtx (EQ, VOIDmode, operands[6], const0_rtx); + operands[7] = gen_rtx_fmt_ee (reverse_condition (code), DImode, + operands[2], operands[3]); + operands[8] = gen_rtx_EQ (VOIDmode, operands[6], const0_rtx); } }") @@ -2498,14 +3342,14 @@ FAIL; if (GET_CODE (operands[3]) == CONST_INT) - tem = gen_rtx (PLUS, SImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); + tem = gen_rtx_PLUS (SImode, operands[2], + GEN_INT (- INTVAL (operands[3]))); else - tem = gen_rtx (MINUS, SImode, operands[2], operands[3]); + tem = gen_rtx_MINUS (SImode, operands[2], operands[3]); - operands[7] = gen_rtx (SIGN_EXTEND, DImode, tem); - operands[8] = gen_rtx (GET_CODE (operands[1]), VOIDmode, operands[6], - const0_rtx); + operands[7] = gen_rtx_SIGN_EXTEND (DImode, tem); + operands[8] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, + operands[6], const0_rtx); }") (define_split @@ -2529,25 +3373,25 @@ && extended_count (operands[3], DImode, unsignedp) >= 1)) { if (GET_CODE (operands[3]) == CONST_INT) - operands[5] = gen_rtx (PLUS, DImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); + operands[5] = gen_rtx_PLUS (DImode, operands[2], + GEN_INT (- INTVAL (operands[3]))); else - operands[5] = gen_rtx (MINUS, DImode, operands[2], operands[3]); + operands[5] = gen_rtx_MINUS (DImode, operands[2], operands[3]); - operands[6] = gen_rtx (code, VOIDmode, operands[4], const0_rtx); + operands[6] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); } else if (code == EQ || code == LE || code == LT || code == LEU || code == LTU) { - operands[5] = gen_rtx (code, DImode, operands[2], operands[3]); - operands[6] = gen_rtx (NE, VOIDmode, operands[4], const0_rtx); + operands[5] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]); + operands[6] = gen_rtx_NE (VOIDmode, operands[4], const0_rtx); } else { - operands[5] = gen_rtx (reverse_condition (code), DImode, operands[2], - operands[3]); - operands[6] = gen_rtx (EQ, VOIDmode, operands[4], const0_rtx); + operands[5] = gen_rtx_fmt_ee (reverse_condition (code), DImode, + operands[2], operands[3]); + operands[6] = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx); } }") @@ -2568,14 +3412,14 @@ { rtx tem; if (GET_CODE (operands[3]) == CONST_INT) - tem = gen_rtx (PLUS, SImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); + tem = gen_rtx_PLUS (SImode, operands[2], + GEN_INT (- INTVAL (operands[3]))); else - tem = gen_rtx (MINUS, SImode, operands[2], operands[3]); + tem = gen_rtx_MINUS (SImode, operands[2], operands[3]); - operands[5] = gen_rtx (SIGN_EXTEND, DImode, tem); - operands[6] = gen_rtx (GET_CODE (operands[1]), VOIDmode, - operands[4], const0_rtx); + operands[5] = gen_rtx_SIGN_EXTEND (DImode, tem); + operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, + operands[4], const0_rtx); }") ;; We can convert such things as "a > 0xffff" to "t = a & ~ 0xffff; t != 0". @@ -2597,10 +3441,10 @@ " { operands[5] = GEN_INT (~ INTVAL (operands[3])); - operands[6] = gen_rtx (((GET_CODE (operands[1]) == GTU - || GET_CODE (operands[1]) == GT) - ? NE : EQ), - DImode, operands[4], const0_rtx); + operands[6] = gen_rtx_fmt_ee (((GET_CODE (operands[1]) == GTU + || GET_CODE (operands[1]) == GT) + ? NE : EQ), + DImode, operands[4], const0_rtx); }") ;; Here are the CALL and unconditional branch insns. Calls on NT and OSF @@ -2608,11 +3452,15 @@ (define_expand "call" [(use (match_operand:DI 0 "" "")) - (use (match_operand 1 "" ""))] + (use (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" ""))] "" " -{ if (WINDOWS_NT) +{ if (TARGET_WINDOWS_NT) emit_call_insn (gen_call_nt (operands[0], operands[1])); + else if (TARGET_OPEN_VMS) + emit_call_insn (gen_call_vms (operands[0], operands[2])); else emit_call_insn (gen_call_osf (operands[0], operands[1])); @@ -2634,39 +3482,95 @@ if (GET_CODE (operands[0]) != SYMBOL_REF && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27)) { - rtx tem = gen_rtx (REG, DImode, 27); + rtx tem = gen_rtx_REG (DImode, 27); emit_move_insn (tem, operands[0]); operands[0] = tem; } }") (define_expand "call_nt" - [(parallel [(call (mem:DI (match_operand:DI 0 "" "")) + [(parallel [(call (mem:DI (match_operand 0 "" "")) (match_operand 1 "" "")) (clobber (reg:DI 26))])] "" " { if (GET_CODE (operands[0]) != MEM) abort (); + operands[0] = XEXP (operands[0], 0); + if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG) + operands[0] = force_reg (DImode, operands[0]); +}") - if (GET_CODE (operands[1]) != SYMBOL_REF - && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) +;; +;; call openvms/alpha +;; op 0: symbol ref for called function +;; op 1: next_arg_reg (argument information value for R25) +;; +(define_expand "call_vms" + [(parallel [(call (mem:DI (match_operand 0 "" "")) + (match_operand 1 "" "")) + (use (match_dup 2)) + (use (reg:DI 25)) + (use (reg:DI 26)) + (clobber (reg:DI 27))])] + "" + " +{ if (GET_CODE (operands[0]) != MEM) + abort (); + + operands[0] = XEXP (operands[0], 0); + + /* Always load AI with argument information, then handle symbolic and + indirect call differently. Load RA and set operands[2] to PV in + both cases. */ + + emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]); + if (GET_CODE (operands[0]) == SYMBOL_REF) { - rtx tem = gen_rtx (REG, DImode, 27); - emit_move_insn (tem, operands[1]); - operands[1] = tem; + extern char *savealloc (); + char *linksym, *symbol = XSTR (operands[0], 0); + rtx linkage; + + if (*symbol == '*') + symbol++; + linksym = savealloc (strlen (symbol) + 6); + + alpha_need_linkage (symbol, 0); + + linksym[0] = '$'; + strcpy (linksym+1, symbol); + strcat (linksym, \"..lk\"); + linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); + + emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); + + operands[2] + = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); + } + else + { + emit_move_insn (gen_rtx_REG (Pmode, 26), + gen_rtx_MEM (Pmode, plus_constant (operands[0], 8))); + + operands[2] = operands[0]; } + }") (define_expand "call_value" [(use (match_operand 0 "" "")) (use (match_operand:DI 1 "" "")) - (use (match_operand 2 "" ""))] + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) + (use (match_operand 4 "" ""))] "" " -{ if (WINDOWS_NT) +{ if (TARGET_WINDOWS_NT) emit_call_insn (gen_call_value_nt (operands[0], operands[1], operands[2])); + else if (TARGET_OPEN_VMS) + emit_call_insn (gen_call_value_vms (operands[0], operands[1], + operands[3])); else emit_call_insn (gen_call_value_osf (operands[0], operands[1], operands[2])); @@ -2689,7 +3593,7 @@ if (GET_CODE (operands[1]) != SYMBOL_REF && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) { - rtx tem = gen_rtx (REG, DImode, 27); + rtx tem = gen_rtx_REG (DImode, 27); emit_move_insn (tem, operands[1]); operands[1] = tem; } @@ -2697,7 +3601,7 @@ (define_expand "call_value_nt" [(parallel [(set (match_operand 0 "" "") - (call (mem:DI (match_operand:DI 1 "" "")) + (call (mem:DI (match_operand 1 "" "")) (match_operand 2 "" ""))) (clobber (reg:DI 26))])] "" @@ -2706,12 +3610,57 @@ abort (); operands[1] = XEXP (operands[1], 0); - if (GET_CODE (operands[1]) != SYMBOL_REF - && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) + if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG) + operands[1] = force_reg (DImode, operands[1]); +}") + +(define_expand "call_value_vms" + [(parallel [(set (match_operand 0 "" "") + (call (mem:DI (match_operand:DI 1 "" "")) + (match_operand 2 "" ""))) + (use (match_dup 3)) + (use (reg:DI 25)) + (use (reg:DI 26)) + (clobber (reg:DI 27))])] + "" + " +{ if (GET_CODE (operands[1]) != MEM) + abort (); + + operands[1] = XEXP (operands[1], 0); + + /* Always load AI with argument information, then handle symbolic and + indirect call differently. Load RA and set operands[3] to PV in + both cases. */ + + emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]); + if (GET_CODE (operands[1]) == SYMBOL_REF) { - rtx tem = gen_rtx (REG, DImode, 27); - emit_move_insn (tem, operands[1]); - operands[1] = tem; + extern char *savealloc (); + char *linksym, *symbol = XSTR (operands[1], 0); + rtx linkage; + + if (*symbol == '*') + symbol++; + linksym = savealloc (strlen (symbol) + 6); + + alpha_need_linkage (symbol, 0); + linksym[0] = '$'; + strcpy (linksym+1, symbol); + strcat (linksym, \"..lk\"); + linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); + + emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); + + operands[3] + = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); + } + else + { + emit_move_insn (gen_rtx_REG (Pmode, 26), + gen_rtx_MEM (Pmode, plus_constant (operands[1], 8))); + + operands[3] = operands[1]; } }") @@ -2720,46 +3669,81 @@ (match_operand 1 "" "")) (clobber (reg:DI 27)) (clobber (reg:DI 26))] - "! WINDOWS_NT" + "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS" "@ jsr $26,($27),0\;ldgp $29,0($26) - bsr $26,%0..ng + bsr $26,$%0..ng jsr $26,%0\;ldgp $29,0($26)" - [(set_attr "type" "jsr,jsr,ibr")]) + [(set_attr "type" "jsr") + (set_attr "length" "12,*,12")]) (define_insn "" - [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i")) + [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) (match_operand 1 "" "")) (clobber (reg:DI 26))] - "WINDOWS_NT" + "TARGET_WINDOWS_NT" "@ jsr $26,(%0) - bsr $26,%0" - [(set_attr "type" "jsr")]) + bsr $26,%0 + jsr $26,%0" + [(set_attr "type" "jsr") + (set_attr "length" "*,*,12")]) (define_insn "" + [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i")) + (match_operand 1 "" "")) + (use (match_operand:DI 2 "general_operand" "r,m")) + (use (reg:DI 25)) + (use (reg:DI 26)) + (clobber (reg:DI 27))] + "TARGET_OPEN_VMS" + "@ + bis %2,%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")]) + +(define_insn "" [(set (match_operand 0 "register_operand" "=rf,rf,rf") (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) (match_operand 2 "" ""))) (clobber (reg:DI 27)) (clobber (reg:DI 26))] - "! WINDOWS_NT" + "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS" "@ jsr $26,($27),0\;ldgp $29,0($26) - bsr $26,%1..ng + bsr $26,$%1..ng jsr $26,%1\;ldgp $29,0($26)" - [(set_attr "type" "jsr,jsr,ibr")]) + [(set_attr "type" "jsr") + (set_attr "length" "12,*,12")]) (define_insn "" - [(set (match_operand 0 "register_operand" "=rf,rf") - (call (mem:DI (match_operand:DI 1 "call_operand" "r,i")) + [(set (match_operand 0 "register_operand" "=rf,rf,rf") + (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) (match_operand 2 "" ""))) (clobber (reg:DI 26))] - "WINDOWS_NT" + "TARGET_WINDOWS_NT" "@ jsr $26,(%1) - bsr $26,%1" - [(set_attr "type" "jsr")]) + bsr $26,%1 + jsr $26,%1" + [(set_attr "type" "jsr") + (set_attr "length" "*,*,12")]) + +(define_insn "" + [(set (match_operand 0 "register_operand" "") + (call (mem:DI (match_operand:DI 1 "call_operand" "r,i")) + (match_operand 2 "" ""))) + (use (match_operand:DI 3 "general_operand" "r,m")) + (use (reg:DI 25)) + (use (reg:DI 26)) + (clobber (reg:DI 27))] + "TARGET_OPEN_VMS" + "@ + bis %3,%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")]) ;; Call subroutine returning any type. @@ -2796,7 +3780,8 @@ (define_insn "blockage" [(unspec_volatile [(const_int 0)] 1)] "" - "") + "" + [(set_attr "length" "0")]) (define_insn "jump" [(set (pc) @@ -2811,6 +3796,15 @@ "ret $31,($26),1" [(set_attr "type" "ibr")]) +;; Use a different pattern for functions which have non-trivial +;; epilogues so as not to confuse jump and reorg. +(define_insn "return_internal" + [(use (reg:DI 26)) + (return)] + "" + "ret $31,($26),1" + [(set_attr "type" "ibr")]) + (define_insn "indirect_jump" [(set (pc) (match_operand:DI 0 "register_operand" "r"))] "" @@ -2820,8 +3814,8 @@ (define_insn "nop" [(const_int 0)] "" - "bis $31,$31,$31" - [(set_attr "type" "iaddlog")]) + "nop" + [(set_attr "type" "ilog")]) (define_expand "tablejump" [(use (match_operand:SI 0 "register_operand" "")) @@ -2829,8 +3823,10 @@ "" " { - if (WINDOWS_NT) + if (TARGET_WINDOWS_NT) emit_jump_insn (gen_tablejump_nt (operands[0], operands[1])); + else if (TARGET_OPEN_VMS) + emit_jump_insn (gen_tablejump_vms (operands[0], operands[1])); else emit_jump_insn (gen_tablejump_osf (operands[0], operands[1])); @@ -2858,12 +3854,27 @@ " { operands[3] = gen_reg_rtx (DImode); }") +;; +;; tablejump, openVMS way +;; op 0: offset +;; op 1: label preceding jump-table +;; +(define_expand "tablejump_vms" + [(set (match_dup 2) + (match_operand:DI 0 "register_operand" "")) + (set (pc) + (plus:DI (match_dup 2) + (label_ref:DI (match_operand 1 "" ""))))] + "" + " +{ operands[2] = gen_reg_rtx (DImode); }") + (define_insn "" [(set (pc) (plus:DI (match_operand:DI 0 "register_operand" "r") (label_ref:DI (match_operand 1 "" "")))) (clobber (match_scratch:DI 2 "=r"))] - "! WINDOWS_NT && next_active_insn (insn) != 0 + "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && next_active_insn (insn) != 0 && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC && PREV_INSN (next_active_insn (insn)) == operands[1]" "* @@ -2900,13 +3911,14 @@ else return \"addq %0,$29,%2\;jmp $31,(%2),0\"; }" - [(set_attr "type" "ibr")]) + [(set_attr "type" "ibr") + (set_attr "length" "8")]) (define_insn "" [(set (pc) (match_operand:DI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] - "WINDOWS_NT && next_active_insn (insn) != 0 + "TARGET_WINDOWS_NT && next_active_insn (insn) != 0 && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC && PREV_INSN (next_active_insn (insn)) == operands[1]" "* @@ -2945,12 +3957,30 @@ }" [(set_attr "type" "ibr")]) +;; +;; op 0 is table offset +;; op 1 is table label +;; + +(define_insn "" + [(set (pc) + (plus:DI (match_operand 0 "register_operand" "r") + (label_ref (match_operand 1 "" ""))))] + "TARGET_OPEN_VMS" + "jmp $31,(%0),0" + [(set_attr "type" "ibr")]) + ;; Cache flush. Used by INITIALIZE_TRAMPOLINE. 0x86 is PAL_imb, but we don't ;; want to have to include pal.h in our .s file. -(define_insn "" +;; +;; Technically the type for call_pal is jsr, but we use that for determining +;; if we need a GP. Use ibr instead since it has the same EV5 scheduling +;; characteristics. +(define_insn "imb" [(unspec_volatile [(const_int 0)] 0)] "" - "call_pal 0x86") + "call_pal 0x86" + [(set_attr "type" "ibr")]) ;; Finally, we have the basic data motion insns. The byte and word insns ;; are done via define_expand. Start with the floating-point insns, since @@ -2959,32 +3989,70 @@ (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"))] - "register_operand (operands[0], SFmode) - || reg_or_fp0_operand (operands[1], SFmode)" + "! TARGET_CIX + && (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 + ld%, %0,%1 + st%, %R1,%0" + [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")]) + +(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 + && (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 - lds %0,%1 - sts %R1,%0" - [(set_attr "type" "iaddlog,ld,st,fpop,fpop,ld,st")]) + ld%, %0,%1 + st%, %R1,%0 + itofs %1,%0 + ftois %1,%0" + [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,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"))] - "register_operand (operands[0], DFmode) - || reg_or_fp0_operand (operands[1], DFmode)" + "! TARGET_CIX + && (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 - ldt %0,%1 - stt %R1,%0" - [(set_attr "type" "iaddlog,ld,st,fpop,fpop,ld,st")]) + ld%- %0,%1 + st%- %R1,%0" + [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")]) + +(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 + && (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 + ld%- %0,%1 + st%- %R1,%0 + itoft %1,%0 + ftoit %1,%0" + [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")]) (define_expand "movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "") @@ -3011,8 +4079,29 @@ (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"))] - "! WINDOWS_NT && (register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode))" + "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_CIX + && (register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode))" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%1 + ldah %0,%h1 + ldl %0,%1 + stl %r1,%0 + cpys %1,%1,%0 + cpys $f31,$f31,%0 + ld%, %0,%1 + st%, %R1,%0" + [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,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 + && (register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode))" "@ bis %1,%1,%0 bis $31,$31,%0 @@ -3023,15 +4112,18 @@ stl %r1,%0 cpys %1,%1,%0 cpys $f31,$f31,%0 - lds %0,%1 - sts %R1,%0" - [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ld,st,fpop,fpop,ld,st")]) + 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")]) (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"))] - "WINDOWS_NT && (register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode))" + "(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 @@ -3043,37 +4135,73 @@ stl %r1,%0 cpys %1,%1,%0 cpys $f31,$f31,%0 - lds %0,%1 - sts %R1,%0" - [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ldsym,ld,st,fpop,fpop,ld,st")]) + ld%, %0,%1 + st%, %R1,%0" + [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,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"))] - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)" + "! TARGET_BWX + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode))" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%L1 + cpys %1,%1,%0 + cpys $f31,$f31,%0" + [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,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"))] + "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 lda %0,%L1 + ldwu %0,%1 + stw %r1,%0 cpys %1,%1,%0 cpys $f31,$f31,%0" - [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,fpop,fpop")]) + [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,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"))] - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" + "! TARGET_BWX + && (register_operand (operands[0], QImode) + || register_operand (operands[1], QImode))" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%L1 + cpys %1,%1,%0 + cpys $f31,$f31,%0" + [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,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"))] + "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 lda %0,%L1 + ldbu %0,%1 + stb %r1,%0 cpys %1,%1,%0 cpys $f31,$f31,%0" - [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,fpop,fpop")]) + [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")]) ;; We do two major things here: handle mem->mem and construct long ;; constants. @@ -3121,8 +4249,9 @@ (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"))] - "register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode)" + "! TARGET_CIX + && (register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode))" "@ bis %1,%1,%0 bis $31,$31,%0 @@ -3136,7 +4265,30 @@ cpys $f31,$f31,%0 ldt %0,%1 stt %R1,%0" - [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ldsym,ld,st,fpop,fpop,ld,st")]) + [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,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 + && (register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode))" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%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 + 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")]) ;; We do three major things here: handle mem->mem, put 64-bit constants in ;; memory, and construct long 32-bit constants. @@ -3166,15 +4318,39 @@ } else if (CONSTANT_P (operands[1])) { - operands[1] = force_const_mem (DImode, operands[1]); - if (reload_in_progress) + if (TARGET_BUILD_CONSTANTS) { - emit_move_insn (operands[0], XEXP (operands[1], 0)); - operands[1] = copy_rtx (operands[1]); - XEXP (operands[1], 0) = operands[0]; +#if HOST_BITS_PER_WIDE_INT == 64 + HOST_WIDE_INT i; + + if (GET_CODE (operands[1]) == CONST_INT) + i = INTVAL (operands[1]); + else if (GET_CODE (operands[1]) == CONST_DOUBLE) + i = CONST_DOUBLE_LOW (operands[1]); + else + abort(); + + tem = alpha_emit_set_long_const (operands[0], i); + if (rtx_equal_p (tem, operands[0])) + DONE; + else + operands[1] = tem; +#else + abort(); +#endif } else - operands[1] = validize_mem (operands[1]); + { + operands[1] = force_const_mem (DImode, operands[1]); + if (reload_in_progress) + { + emit_move_insn (operands[0], XEXP (operands[1], 0)); + operands[1] = copy_rtx (operands[1]); + XEXP (operands[1], 0) = operands[0]; + } + else + operands[1] = validize_mem (operands[1]); + } } else abort (); @@ -3230,16 +4406,10 @@ "" "") -;; Similar for unaligned loads. For QImode, we use the sequence from the -;; Alpha Architecture manual. However, for HImode, we do not. HImode pointers -;; are normally aligned to the byte boundary, so an HImode object cannot -;; cross a longword boundary. We could use a sequence similar to that for -;; QImode, but that would fail if the pointer, was, in fact, not aligned. -;; Instead, we clear bit 1 in the address and do an ldl. If the low-order -;; bit was not aligned, this will trap and the trap handler will do what is -;; needed. +;; Similar for unaligned loads, where we use the sequence from the +;; Alpha Architecture manual. ;; -;; Here operand 1 is the address. Operands 2 and 3 are temporaries, where +;; Operand 1 is the address. Operands 2 and 3 are temporaries, where ;; operand 3 can overlap the input and output registers. (define_expand "unaligned_loadqi" @@ -3255,26 +4425,19 @@ "" "") -;; For this, the address must already be in a register. We also need two -;; DImode temporaries, neither of which may overlap the input (and hence the -;; output, since they might be the same register), but both of which may -;; be the same. - (define_expand "unaligned_loadhi" [(set (match_operand:DI 2 "register_operand" "") - (and:DI (match_operand:DI 1 "register_operand" "") - (const_int -7))) + (mem:DI (and:DI (match_operand:DI 1 "address_operand" "") + (const_int -8)))) (set (match_operand:DI 3 "register_operand" "") - (mem:DI (match_dup 2))) - (set (match_operand:DI 4 "register_operand" "") - (and:DI (match_dup 1) (const_int -2))) - (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0) - (zero_extract:DI (match_dup 3) + (match_dup 1)) + (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) + (zero_extract:DI (match_dup 2) (const_int 16) - (ashift:DI (match_dup 4) (const_int 3))))] + (ashift:DI (match_dup 3) (const_int 3))))] "" "") - + ;; Storing an aligned byte or word requires two temporaries. Operand 0 is the ;; aligned SImode MEM. Operand 1 is the register containing the ;; byte or word to store. Operand 2 is the number of bits within the word that @@ -3297,8 +4460,8 @@ << INTVAL (operands[2]))); }") -;; For the unaligned byte case, we use code similar to that in the -;; Architecture book, but reordered to lower the number of registers +;; For the unaligned byte and halfword cases, we use code similar to that +;; in the ;; Architecture book, but reordered to lower the number of registers ;; required. Operand 0 is the address. Operand 1 is the data to store. ;; Operands 2, 3, and 4 are DImode temporaries, where operands 2 and 4 may ;; be the same temporary, if desired. If the address is in a register, @@ -3323,42 +4486,22 @@ "" "") -;; This is the code for storing into an unaligned short. It uses the same -;; trick as loading from an unaligned short. It needs lots of temporaries. -;; However, during reload, we only have two registers available. So we -;; repeat code so that only two temporaries are available. During RTL -;; generation, we can use different pseudos for each temporary and CSE -;; will remove the redundancies. During reload, we have to settle with -;; what we get. Luckily, unaligned accesses of this kind produced during -;; reload are quite rare. -;; -;; Operand 0 is the address of the memory location. Operand 1 contains the -;; data to store. The rest of the operands are all temporaries, with -;; various overlap possibilities during reload. See reload_outhi for -;; details of this use. - (define_expand "unaligned_storehi" - [(set (match_operand:DI 2 "register_operand" "") - (match_operand:DI 0 "address_operand" "")) - (set (match_operand:DI 3 "register_operand" "") - (and:DI (match_dup 2) (const_int -7))) - (set (match_operand:DI 4 "register_operand" "") - (mem:DI (match_dup 3))) - (set (match_operand:DI 10 "register_operand" "") - (and:DI (match_dup 2) (const_int -2))) - (set (match_operand:DI 5 "register_operand" "") + [(set (match_operand:DI 3 "register_operand" "") + (mem:DI (and:DI (match_operand:DI 0 "address_operand" "") + (const_int -8)))) + (set (match_operand:DI 2 "register_operand" "") + (match_dup 0)) + (set (match_dup 3) (and:DI (not:DI (ashift:DI (const_int 65535) - (ashift:DI (match_dup 10) (const_int 3)))) - (match_dup 4))) - (set (match_operand:DI 6 "register_operand" "") + (ashift:DI (match_dup 2) (const_int 3)))) + (match_dup 3))) + (set (match_operand:DI 4 "register_operand" "") (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "")) - (ashift:DI (match_dup 10) (const_int 3)))) - (set (match_operand:DI 7 "register_operand" "") - (ior:DI (match_dup 5) (match_dup 6))) - (set (match_operand:DI 8 "register_operand" "") (match_dup 0)) - (set (match_operand:DI 9 "register_operand" "") - (and:DI (match_dup 8) (const_int -7))) - (set (mem:DI (match_dup 9)) (match_dup 7))] + (ashift:DI (match_dup 2) (const_int 3)))) + (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3))) + (set (mem:DI (and:DI (match_dup 0) (const_int -8))) + (match_dup 4))] "" "") @@ -3371,7 +4514,25 @@ (match_operand:QI 1 "general_operand" ""))] "" " -{ extern rtx get_unaligned_address (); +{ + if (TARGET_BWX) + { + if (GET_CODE (operands[0]) == MEM + && ! reg_or_0_operand (operands[1], QImode)) + operands[1] = force_reg (QImode, operands[1]); + + if (GET_CODE (operands[1]) == CONST_INT + && ! input_operand (operands[1], QImode)) + { + operands[1] = alpha_emit_set_const (operands[0], QImode, + INTVAL (operands[1]), 3); + + if (rtx_equal_p (operands[0], operands[1])) + DONE; + } + + goto def; + } /* If the output is not a register, the input must be. */ if (GET_CODE (operands[0]) == MEM) @@ -3394,7 +4555,7 @@ { rtx aligned_mem, bitnum; rtx scratch = (reload_in_progress - ? gen_rtx (REG, SImode, REGNO (operands[0])) + ? gen_rtx_REG (SImode, REGNO (operands[0])) : gen_reg_rtx (SImode)); get_aligned_mem (operands[1], &aligned_mem, &bitnum); @@ -3410,9 +4571,10 @@ rtx temp1 = gen_reg_rtx (DImode); rtx temp2 = gen_reg_rtx (DImode); - rtx seq = gen_unaligned_loadqi (operands[0], - get_unaligned_address (operands[1]), - temp1, temp2); + rtx seq + = gen_unaligned_loadqi (operands[0], + get_unaligned_address (operands[1], 0), + temp1, temp2); alpha_set_memflags (seq, operands[1]); emit_insn (seq); @@ -3446,7 +4608,8 @@ rtx temp1 = gen_reg_rtx (DImode); rtx temp2 = gen_reg_rtx (DImode); rtx temp3 = gen_reg_rtx (DImode); - rtx seq = gen_unaligned_storeqi (get_unaligned_address (operands[0]), + rtx seq + = gen_unaligned_storeqi (get_unaligned_address (operands[0], 0), operands[1], temp1, temp2, temp3); alpha_set_memflags (seq, operands[0]); @@ -3454,6 +4617,7 @@ } DONE; } + def:; }") (define_expand "movhi" @@ -3461,7 +4625,25 @@ (match_operand:HI 1 "general_operand" ""))] "" " -{ extern rtx get_unaligned_address (); +{ + if (TARGET_BWX) + { + if (GET_CODE (operands[0]) == MEM + && ! reg_or_0_operand (operands[1], HImode)) + operands[1] = force_reg (HImode, operands[1]); + + if (GET_CODE (operands[1]) == CONST_INT + && ! input_operand (operands[1], HImode)) + { + operands[1] = alpha_emit_set_const (operands[0], HImode, + INTVAL (operands[1]), 3); + + if (rtx_equal_p (operands[0], operands[1])) + DONE; + } + + goto def; + } /* If the output is not a register, the input must be. */ if (GET_CODE (operands[0]) == MEM) @@ -3484,7 +4666,7 @@ { rtx aligned_mem, bitnum; rtx scratch = (reload_in_progress - ? gen_rtx (REG, SImode, REGNO (operands[0])) + ? gen_rtx_REG (SImode, REGNO (operands[0])) : gen_reg_rtx (SImode)); get_aligned_mem (operands[1], &aligned_mem, &bitnum); @@ -3494,16 +4676,16 @@ } else { - rtx addr - = force_reg (DImode, - force_operand (get_unaligned_address (operands[1]), - NULL_RTX)); - rtx scratch1 = gen_reg_rtx (DImode); - rtx scratch2 = gen_reg_rtx (DImode); - rtx scratch3 = gen_reg_rtx (DImode); + /* Don't pass these as parameters since that makes the generated + code depend on parameter evaluation order which will cause + bootstrap failures. */ - rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch1, - scratch2, scratch3); + rtx temp1 = gen_reg_rtx (DImode); + rtx temp2 = gen_reg_rtx (DImode); + rtx seq + = gen_unaligned_loadhi (operands[0], + get_unaligned_address (operands[1], 0), + temp1, temp2); alpha_set_memflags (seq, operands[1]); emit_insn (seq); @@ -3537,17 +4719,9 @@ rtx temp1 = gen_reg_rtx (DImode); rtx temp2 = gen_reg_rtx (DImode); rtx temp3 = gen_reg_rtx (DImode); - rtx temp4 = gen_reg_rtx (DImode); - rtx temp5 = gen_reg_rtx (DImode); - rtx temp6 = gen_reg_rtx (DImode); - rtx temp7 = gen_reg_rtx (DImode); - rtx temp8 = gen_reg_rtx (DImode); - rtx temp9 = gen_reg_rtx (DImode); - - rtx seq = gen_unaligned_storehi (get_unaligned_address (operands[0]), - operands[1], temp1, temp2,temp3, - temp4, temp5, temp6,temp7, - temp8, temp9); + rtx seq + = gen_unaligned_storehi (get_unaligned_address (operands[0], 0), + operands[1], temp1, temp2, temp3); alpha_set_memflags (seq, operands[0]); emit_insn (seq); @@ -3555,6 +4729,7 @@ DONE; } + def:; }") ;; Here are the versions for reload. Note that in the unaligned cases @@ -3565,18 +4740,20 @@ [(parallel [(match_operand:QI 0 "register_operand" "=r") (match_operand:QI 1 "unaligned_memory_operand" "m") (match_operand:TI 2 "register_operand" "=&r")])] - "" + "! TARGET_BWX" " -{ extern rtx get_unaligned_address (); - rtx addr = get_unaligned_address (operands[1]); +{ + rtx addr = get_unaligned_address (operands[1], 0); + /* 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])); + rtx scratch = gen_rtx_REG (DImode, + REGNO (operands[0]) == REGNO (operands[2]) + ? REGNO (operands[2]) + 1 : REGNO (operands[2])); + rtx seq = gen_unaligned_loadqi (operands[0], addr, scratch, - gen_rtx (REG, DImode, REGNO (operands[0]))); + gen_rtx_REG (DImode, REGNO (operands[0]))); alpha_set_memflags (seq, operands[1]); emit_insn (seq); @@ -3587,21 +4764,21 @@ [(parallel [(match_operand:HI 0 "register_operand" "=r") (match_operand:HI 1 "unaligned_memory_operand" "m") (match_operand:TI 2 "register_operand" "=&r")])] - "" + "! TARGET_BWX" " -{ extern rtx get_unaligned_address (); - rtx addr = get_unaligned_address (operands[1]); - rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); - rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); - rtx seq; +{ + rtx addr = get_unaligned_address (operands[1], 0); + + /* 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])); + + rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch, + gen_rtx_REG (DImode, REGNO (operands[0]))); - if (GET_CODE (addr) != REG) - { - emit_insn (gen_rtx (SET, VOIDmode, scratch2, addr)); - addr = scratch2; - } - - seq = gen_unaligned_loadhi (operands[0], addr, scratch1, scratch1, scratch2); alpha_set_memflags (seq, operands[1]); emit_insn (seq); DONE; @@ -3611,10 +4788,9 @@ [(parallel [(match_operand:QI 0 "any_memory_operand" "=m") (match_operand:QI 1 "register_operand" "r") (match_operand:TI 2 "register_operand" "=&r")])] - "" + "! TARGET_BWX" " -{ extern rtx get_unaligned_address (); - +{ if (aligned_memory_operand (operands[0], QImode)) { rtx aligned_mem, bitnum; @@ -3622,15 +4798,15 @@ 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))); + gen_rtx_REG (SImode, REGNO (operands[2])), + gen_rtx_REG (SImode, + REGNO (operands[2]) + 1))); } else { - rtx addr = get_unaligned_address (operands[0]); - rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); - rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); + rtx addr = get_unaligned_address (operands[0], 0); + rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2])); + rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); rtx scratch3 = scratch1; rtx seq; @@ -3650,10 +4826,9 @@ [(parallel [(match_operand:HI 0 "any_memory_operand" "=m") (match_operand:HI 1 "register_operand" "r") (match_operand:TI 2 "register_operand" "=&r")])] - "" + "! TARGET_BWX" " -{ extern rtx get_unaligned_address (); - +{ if (aligned_memory_operand (operands[0], HImode)) { rtx aligned_mem, bitnum; @@ -3661,22 +4836,23 @@ 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))); + gen_rtx_REG (SImode, REGNO (operands[2])), + gen_rtx_REG (SImode, + REGNO (operands[2]) + 1))); } else { - rtx addr = get_unaligned_address (operands[0]); - rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); - rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); - rtx scratch_a = GET_CODE (addr) == REG ? addr : scratch1; + rtx addr = get_unaligned_address (operands[0], 0); + rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2])); + rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); + rtx scratch3 = scratch1; rtx seq; - seq = gen_unaligned_storehi (addr, operands[1], scratch_a, - scratch2, scratch2, scratch2, - scratch1, scratch2, scratch_a, - scratch1, scratch_a); + if (GET_CODE (addr) == REG) + scratch1 = addr; + + seq = gen_unaligned_storehi (addr, operands[1], scratch1, + scratch2, scratch3); alpha_set_memflags (seq, operands[0]); emit_insn (seq); } @@ -3684,14 +4860,133 @@ DONE; }") +;; Bit field extract patterns which use ext[wlq][lh] + +(define_expand "extv" + [(set (match_operand:DI 0 "register_operand" "") + (sign_extract:DI (match_operand:QI 1 "memory_operand" "") + (match_operand:DI 2 "immediate_operand" "") + (match_operand:DI 3 "immediate_operand" "")))] + "" + " +{ + /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */ + if (INTVAL (operands[3]) % 8 != 0 + || (INTVAL (operands[2]) != 16 + && INTVAL (operands[2]) != 32 + && INTVAL (operands[2]) != 64)) + FAIL; + + /* From mips.md: extract_bit_field doesn't verify that our source + matches the predicate, so we force it to be a MEM here. */ + if (GET_CODE (operands[1]) != MEM) + FAIL; + + alpha_expand_unaligned_load (operands[0], operands[1], + INTVAL (operands[2]) / 8, + INTVAL (operands[3]) / 8, 1); + DONE; +}") + +(define_expand "extzv" + [(set (match_operand:DI 0 "register_operand" "") + (zero_extract:DI (match_operand:DI 1 "general_operand" "") + (match_operand:DI 2 "immediate_operand" "") + (match_operand:DI 3 "immediate_operand" "")))] + "" + " +{ + /* We can do 8, 16, 32 and 64 bit fields, if aligned on byte boundaries. */ + if (INTVAL (operands[3]) % 8 != 0 + || (INTVAL (operands[2]) != 8 + && INTVAL (operands[2]) != 16 + && INTVAL (operands[2]) != 32 + && INTVAL (operands[2]) != 64)) + FAIL; + + if (GET_CODE (operands[1]) == MEM) + { + /* Fail 8 bit fields, falling back on a simple byte load. */ + if (INTVAL (operands[2]) == 8) + FAIL; + + alpha_expand_unaligned_load (operands[0], operands[1], + INTVAL (operands[2]) / 8, + INTVAL (operands[3]) / 8, 0); + DONE; + } +}") + +(define_expand "insv" + [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "") + (match_operand:DI 1 "immediate_operand" "") + (match_operand:DI 2 "immediate_operand" "")) + (match_operand:DI 3 "register_operand" ""))] + "" + " +{ + /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */ + if (INTVAL (operands[2]) % 8 != 0 + || (INTVAL (operands[1]) != 16 + && INTVAL (operands[1]) != 32 + && INTVAL (operands[1]) != 64)) + FAIL; + + /* From mips.md: store_bit_field doesn't verify that our source + matches the predicate, so we force it to be a MEM here. */ + if (GET_CODE (operands[0]) != MEM) + FAIL; + + alpha_expand_unaligned_store (operands[0], operands[3], + INTVAL (operands[1]) / 8, + INTVAL (operands[2]) / 8); + DONE; +}") + + + +;; Block move/clear, see alpha.c for more details. +;; Argument 0 is the destination +;; Argument 1 is the source +;; Argument 2 is the length +;; Argument 3 is the alignment + +(define_expand "movstrqi" + [(parallel [(set (match_operand:BLK 0 "general_operand" "") + (match_operand:BLK 1 "general_operand" "")) + (use (match_operand:DI 2 "immediate_operand" "")) + (use (match_operand:DI 3 "immediate_operand" ""))])] + "" + " +{ + if (alpha_expand_block_move (operands)) + DONE; + else + FAIL; +}") + +(define_expand "clrstrqi" + [(parallel [(set (match_operand:BLK 0 "general_operand" "") + (const_int 0)) + (use (match_operand:DI 1 "immediate_operand" "")) + (use (match_operand:DI 2 "immediate_operand" ""))])] + "" + " +{ + if (alpha_expand_block_clear (operands)) + DONE; + else + FAIL; +}") + ;; Subroutine of stack space allocation. Perform a stack probe. (define_expand "probe_stack" [(set (match_dup 1) (match_operand:DI 0 "const_int_operand" ""))] "" " { - operands[1] = gen_rtx (MEM, DImode, plus_constant (stack_pointer_rtx, - INTVAL (operands[0]))); + operands[1] = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, + INTVAL (operands[0]))); MEM_VOLATILE_P (operands[1]) = 1; operands[0] = const0_rtx; @@ -3706,14 +5001,16 @@ (define_expand "allocate_stack" [(set (reg:DI 30) (plus:DI (reg:DI 30) - (match_operand:DI 0 "reg_or_cint_operand" "")))] + (match_operand:DI 1 "reg_or_cint_operand" ""))) + (set (match_operand:DI 0 "register_operand" "=r") + (match_dup 2))] "" " { - if (GET_CODE (operands[0]) == CONST_INT - && INTVAL (operands[0]) < 32768) + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) < 32768) { - if (INTVAL (operands[0]) >= 4096) + if (INTVAL (operands[1]) >= 4096) { /* We do this the same way as in the prologue and generate explicit probes. Then we update the stack by the constant. */ @@ -3721,14 +5018,15 @@ int probed = 4096; emit_insn (gen_probe_stack (GEN_INT (- probed))); - while (probed + 8192 < INTVAL (operands[0])) + while (probed + 8192 < INTVAL (operands[1])) emit_insn (gen_probe_stack (GEN_INT (- (probed += 8192)))); - if (probed + 4096 < INTVAL (operands[0])) - emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[0])))); + if (probed + 4096 < INTVAL (operands[1])) + emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[1])))); } - operands[0] = GEN_INT (- INTVAL (operands[0])); + operands[1] = GEN_INT (- INTVAL (operands[1])); + operands[2] = virtual_stack_dynamic_rtx; } else { @@ -3739,10 +5037,10 @@ rtx memref; emit_insn (gen_subdi3 (want, stack_pointer_rtx, - force_reg (Pmode, operands[0]))); + force_reg (Pmode, operands[1]))); emit_insn (gen_adddi3 (tmp, stack_pointer_rtx, GEN_INT (-4096))); - if (GET_CODE (operands[0]) != CONST_INT) + if (GET_CODE (operands[1]) != CONST_INT) { out_label = gen_label_rtx (); emit_insn (gen_cmpdi (want, tmp)); @@ -3750,13 +5048,16 @@ } emit_label (loop_label); - memref = gen_rtx (MEM, DImode, tmp); + memref = gen_rtx_MEM (DImode, tmp); MEM_VOLATILE_P (memref) = 1; emit_move_insn (memref, const0_rtx); emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192))); emit_insn (gen_cmpdi (tmp, want)); emit_jump_insn (gen_bgtu (loop_label)); - memref = gen_rtx (MEM, DImode, want); + if (obey_regdecls) + gen_rtx_USE (VOIDmode, tmp); + + memref = gen_rtx_MEM (DImode, want); MEM_VOLATILE_P (memref) = 1; emit_move_insn (memref, const0_rtx); @@ -3764,7 +5065,160 @@ emit_label (out_label); emit_move_insn (stack_pointer_rtx, want); - + emit_move_insn (operands[0], virtual_stack_dynamic_rtx); DONE; } }") + +;; This is used by alpha_expand_prolog to do the same thing as above, +;; except we cannot at that time generate new basic blocks, so we hide +;; the loop in this one insn. + +(define_insn "prologue_stack_probe_loop" + [(unspec_volatile [(match_operand 0 "register_operand" "r") + (match_operand 1 "register_operand" "r")] 5)] + "" + "* +{ + 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 \"\"; +}" + [(set_attr "length" "16")]) + +(define_expand "prologue" + [(clobber (const_int 0))] + "" + "alpha_expand_prologue (); DONE;") + +(define_insn "init_fp" + [(set (match_operand:DI 0 "register_operand" "r") + (match_operand:DI 1 "register_operand" "r")) + (clobber (mem:BLK (match_operand:DI 2 "register_operand" "r")))] + "" + "bis %1,%1,%0") + +(define_expand "epilogue" + [(clobber (const_int 0))] + "" + "alpha_expand_epilogue (); DONE;") + +(define_expand "builtin_longjmp" + [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] + "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" + " +{ + /* The elements of the buffer are, in order: */ + rtx fp = gen_rtx_MEM (Pmode, operands[0]); + rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8)); + rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16)); + rtx pv = gen_rtx_REG (Pmode, 27); + + /* This bit is the same as expand_builtin_longjmp. */ + emit_move_insn (hard_frame_pointer_rtx, fp); + emit_move_insn (pv, lab); + emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); + emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); + emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); + + /* Load the label we are jumping through into $27 so that we know + where to look for it when we get back to setjmp's function for + restoring the gp. */ + emit_indirect_jump (pv); +}") + +(define_insn "builtin_setjmp_receiver" + [(unspec_volatile [(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")]) + +(define_insn "" + [(unspec_volatile [(match_operand 0 "" "")] 2)] + "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" + "br $27,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($27)" + [(set_attr "length" "12")]) + +(define_expand "nonlocal_goto_receiver" + [(unspec_volatile [(const_int 0)] 1) + (set (reg:DI 27) (mem:DI (reg:DI 29))) + (unspec_volatile [(const_int 0)] 1) + (use (reg:DI 27))] + "TARGET_OPEN_VMS" + "") + +(define_insn "arg_home" + [(unspec [(const_int 0)] 0) + (use (reg:DI 1)) + (use (reg:DI 25)) + (use (reg:DI 16)) + (use (reg:DI 17)) + (use (reg:DI 18)) + (use (reg:DI 19)) + (use (reg:DI 20)) + (use (reg:DI 21)) + (use (reg:DI 48)) + (use (reg:DI 49)) + (use (reg:DI 50)) + (use (reg:DI 51)) + (use (reg:DI 52)) + (use (reg:DI 53)) + (clobber (mem:BLK (const_int 0))) + (clobber (reg:DI 24)) + (clobber (reg:DI 25)) + (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")]) + +;; Close the trap shadow of preceeding instructions. This is generated +;; by alpha_reorg. + +(define_insn "trapb" + [(unspec_volatile [(const_int 0)] 4)] + "" + "trapb" + [(set_attr "type" "misc")]) + +;; Peepholes go at the end. + +;; Optimize sign-extension of SImode loads. This shows up in the wake of +;; reload when converting fp->int. +;; +;; ??? What to do now that we actually care about the packing and +;; alignment of instructions? Perhaps reload can be enlightened, or +;; the peephole pass moved up after reload but before sched2? +; +;(define_peephole +; [(set (match_operand:SI 0 "register_operand" "=r") +; (match_operand:SI 1 "memory_operand" "m")) +; (set (match_operand:DI 2 "register_operand" "=r") +; (sign_extend:DI (match_dup 0)))] +; "dead_or_set_p (insn, operands[0])" +; "ldl %2,%1") +; +;(define_peephole +; [(set (match_operand:SI 0 "register_operand" "=r") +; (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])" +; "ftois %1,%2") diff --git a/contrib/gcc/config/alpha/crtbegin.asm b/contrib/gcc/config/alpha/crtbegin.asm new file mode 100644 index 0000000..c28440d --- /dev/null +++ b/contrib/gcc/config/alpha/crtbegin.asm @@ -0,0 +1,111 @@ + # Copyright (C) 1996, 1998 Free Software Foundation, Inc. + # Contributed by Richard Henderson (rth@tamu.edu) + # + # 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, 59 Temple Place - Suite 330, + # Boston, MA 02111-1307, USA. + # + # As a special exception, if you link this library with files + # compiled with GCC to produce an executable, this does not 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. + + # + # Heads of the constructor/destructor lists. + # + + # The __*TOR_LIST__ symbols are not global because when this file is used + # in a shared library, we do not want the symbol to fall over to the + # application's lists. + +.section .ctors,"aw" + + .align 3 +__CTOR_LIST__: + .quad -1 + +.section .dtors,"aw" + + .align 3 +__DTOR_LIST__: + .quad -1 + + + # + # Fragment of the ELF _fini routine that invokes our dtor cleanup. + # + +.section .fini,"ax" + + # Since the bits of the _fini function are spread across many + # object files, each potentially with its own GP, we must + # assume we need to load ours. Further, our .fini section + # can easily be more than 4MB away from our .text bits so we + # can't use bsr. + + br $29,1f +1: ldgp $29,0($29) + jsr $26,__do_global_dtors_aux + + # Must match the alignment we got from crti.o else we get + # zero-filled holes in our _fini function and then SIGILL. + .align 3 + + # + # Invoke our destructors in order. + # + +.data + + # Support recursive calls to exit. +9: .quad __DTOR_LIST__ + +.text + + .align 3 + .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 + + lda $9,9b + br 1f +0: stq $1,0($9) + jsr $26,($27) +1: ldq $1,0($9) + ldq $27,8($1) + addq $1,8,$1 + bne $27,0b + + ldq $26,0($30) + ldq $9,8($30) + lda $30,16($30) + ret + + .end __do_global_dtors_aux diff --git a/contrib/gcc/config/alpha/crtend.asm b/contrib/gcc/config/alpha/crtend.asm new file mode 100644 index 0000000..36f11b9 --- /dev/null +++ b/contrib/gcc/config/alpha/crtend.asm @@ -0,0 +1,105 @@ + # Copyright (C) 1996 Free Software Foundation, Inc. + # Contributed by Richard Henderson (rth@tamu.edu) + # + # 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, 59 Temple Place - Suite 330, + # Boston, MA 02111-1307, USA. + # + # As a special exception, if you link this library with files + # compiled with GCC to produce an executable, this does not 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. + + # + # Tails of the constructor/destructor lists. + # + + # The __*TOR_END__ symbols are not global because when this file is used + # in a shared library, we do not want the symbol to fall over to the + # application's lists. + +.section .ctors,"aw" + + .align 3 +__CTOR_END__: + .quad 0 + +.section .dtors,"aw" + + .align 3 +__DTOR_END__: + .quad 0 + + + # + # Fragment of the ELF _init routine that invokes our ctor startup + # + +.section .init,"ax" + + # Since the bits of the _init function are spread across many + # object files, each potentially with its own GP, we must + # assume we need to load ours. Further, our .init section + # can easily be more than 4MB away from our .text bits so we + # can't use bsr. + + br $29,1f +1: ldgp $29,0($29) + jsr $26,__do_global_ctors_aux + + # Must match the alignment we got from crti.o else we get + # zero-filled holes in our _init function and thense SIGILL. + .align 3 + + # + # Invoke our destructors in order. + # + +.text + + .align 3 + .ent __do_global_ctors_aux + +__do_global_ctors_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 + + lda $9,__CTOR_END__ + br 1f +0: jsr $26,($27) +1: ldq $27,-8($9) + subq $9,8,$9 + not $27,$0 + bne $0,0b + + ldq $26,0($30) + ldq $9,8($30) + lda $30,16($30) + ret + + .end __do_global_ctors_aux diff --git a/contrib/gcc/config/alpha/elf.h b/contrib/gcc/config/alpha/elf.h index 82f0410..4f4703c 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 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. Contributed by Richard Henderson (rth@tamu.edu). This file is part of GNU CC. @@ -19,53 +19,49 @@ 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 used on Alpha platforms that use the ELF format. -Currently only Linux uses this. */ - -#if 0 -#include "alpha/linux.h" -#endif - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (Alpha Linux/ELF)"); - #undef OBJECT_FORMAT_COFF #undef EXTENDED_COFF #define OBJECT_FORMAT_ELF -#define SDB_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG #undef ASM_FINAL_SPEC -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "\ --D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \ --Asystem(linux) -Acpu(alpha) -Amachine(alpha) -D__ELF__" +#undef CC1_SPEC +#define CC1_SPEC "%{G*}" + +#undef ASM_SPEC +#define ASM_SPEC "%{G*} %{relax:-relax}" #undef LINK_SPEC -#define LINK_SPEC "-m elf64alpha -G 8 %{O*:-O3} %{!O*:-O1} \ +#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \ + %{O*:-O3} %{!O*:-O1} \ %{shared:-shared} \ %{!shared: \ %{!static: \ %{rdynamic:-export-dynamic} \ - %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \ + %{!dynamic-linker:-dynamic-linker %(elf_dynamic_linker)}} \ %{static:-static}}" /* 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); \ - fprintf (FILE, "\t.version\t\"01.01\"\n"); \ fprintf (FILE, "\t.set noat\n"); \ + fprintf (FILE, "\t.set noreorder\n"); \ + if (TARGET_BWX | TARGET_MAX | TARGET_CIX) \ + { \ + fprintf (FILE, "\t.arch %s\n", \ + (alpha_cpu == PROCESSOR_EV6 ? "ev6" \ + : TARGET_MAX ? "pca56" : "ev56")); \ + } \ } -#define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \ - alpha_output_lineno (STREAM, LINE) -extern void alpha_output_lineno (); - extern void output_file_directive (); /* Attach a special .ident directive to the end of the file to identify @@ -77,8 +73,8 @@ extern void output_file_directive (); #ifdef IDENTIFY_WITH_IDENT #define ASM_IDENTIFY_GCC(FILE) /* nothing */ -#define ASM_IDENTIFY_LANGUAGE(FILE) \ - fprintf(FILE, "\t%s \"GCC (%s) %s\"\n", IDENT_ASM_OP, \ +#define ASM_IDENTIFY_LANGUAGE(FILE) \ + fprintf(FILE, "\t%s \"GCC (%s) %s\"\n", IDENT_ASM_OP, \ lang_identify(), version_string) #else #define ASM_FILE_END(FILE) \ @@ -89,11 +85,9 @@ do { \ #endif /* Allow #sccs in preprocessor. */ - #define SCCS_DIRECTIVE /* Output #ident as a .ident. */ - #define ASM_OUTPUT_IDENT(FILE, NAME) \ fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); @@ -155,22 +149,46 @@ do { \ 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); \ + if ((SIZE) <= g_switch_value) \ + sbss_section(); \ + else \ + bss_section(); \ + fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ + putc ('\n', FILE); \ + if (!flag_inhibit_size_directive) \ + { \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", (SIZE)); \ + } \ + ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + ASM_OUTPUT_SKIP((FILE), (SIZE)); \ } while (0) /* This is the pseudo-op used to generate a 64-bit word of data with a - specific value in some section. */ + specific value in some section. */ #define INT_ASM_OP ".quad" +/* 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'. + + This value is really 2^63. Since gcc figures the alignment in bits, + we could only potentially get to 2^60 on suitible hosts. Due to other + considerations in varasm, we must restrict this to what fits in an int. */ + +#define MAX_OFILE_ALIGNMENT \ + (1 << (HOST_BITS_PER_INT < 64 ? HOST_BITS_PER_INT - 2 : 62)) + /* 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. */ @@ -208,6 +226,11 @@ do { \ #define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" #define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" +/* Handle the small data sections. */ +#define BSS_SECTION_ASM_OP ".section\t.bss" +#define SBSS_SECTION_ASM_OP ".section\t.sbss,\"aw\"" +#define SDATA_SECTION_ASM_OP ".section\t.sdata,\"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. @@ -217,17 +240,13 @@ do { \ #define INIT_SECTION_ASM_OP ".section\t.init" #define FINI_SECTION_ASM_OP ".section\t.fini" -/* Support non-common, uninitialized data in the .bss section. */ - -#define BSS_SECTION_ASM_OP ".section\t.bss" - /* 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, in_bss +#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_sbss, in_sdata /* A default list of extra section function definitions. For targets that use additional sections (e.g. .tdesc) you should override this @@ -236,9 +255,10 @@ do { \ #undef EXTRA_SECTION_FUNCTIONS #define EXTRA_SECTION_FUNCTIONS \ CONST_SECTION_FUNCTION \ - CTORS_SECTION_FUNCTION \ - DTORS_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION + SECTION_FUNCTION_TEMPLATE(ctors_section, in_ctors, CTORS_SECTION_ASM_OP) \ + SECTION_FUNCTION_TEMPLATE(dtors_section, in_dtors, DTORS_SECTION_ASM_OP) \ + SECTION_FUNCTION_TEMPLATE(sbss_section, in_sbss, SBSS_SECTION_ASM_OP) \ + SECTION_FUNCTION_TEMPLATE(sdata_section, in_sdata, SDATA_SECTION_ASM_OP) #undef READONLY_DATA_SECTION #define READONLY_DATA_SECTION() const_section () @@ -258,36 +278,13 @@ const_section () \ } \ } -#define CTORS_SECTION_FUNCTION \ -void \ -ctors_section () \ +#define SECTION_FUNCTION_TEMPLATE(FN, ENUM, OP) \ +void FN () \ { \ - if (in_section != in_ctors) \ + if (in_section != ENUM) \ { \ - 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 BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ + fprintf (asm_out_file, "%s\n", OP); \ + in_section = ENUM; \ } \ } @@ -297,10 +294,10 @@ bss_section () \ 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) \ +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ - (DECL) && TREE_READONLY (DECL) ? "a" : "aw") + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") /* A C statement (sans semicolon) to output an element in the table of @@ -344,11 +341,10 @@ bss_section () \ || !DECL_INITIAL (DECL) \ || (DECL_INITIAL (DECL) != error_mark_node \ && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ - { \ - if (DECL_COMMON (DECL) \ - && !DECL_INITIAL (DECL)) \ - /* || DECL_INITIAL (DECL) == error_mark_node)) */ \ - bss_section(); \ + { \ + int size = int_size_in_bytes (TREE_TYPE (DECL)); \ + if (size >= 0 && size <= g_switch_value) \ + sdata_section (); \ else \ data_section (); \ } \ @@ -486,39 +482,39 @@ do { \ 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. -*/ + should define this to zero. */ #define STRING_LIMIT ((unsigned) 256) - #define STRING_ASM_OP ".string" -/* - * We always use gas here, so we don't worry about ECOFF assembler problems. - */ +/* GAS is the only Alpha/ELF assembler. */ #undef TARGET_GAS #define TARGET_GAS (1) -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +/* Provide a STARTFILE_SPEC appropriate for ELF. Here we add the + (even more) magical crtbegin.o file which provides part of the + support for getting C++ file-scope static object constructed before + entering `main'. -/* Provide a STARTFILE_SPEC appropriate for Linux. Here we add - the Linux magical crtbegin.o file (see crtstuff.c) which - provides part of the support for getting C++ file-scope static - object constructed before entering `main'. */ + Don't bother seeing crtstuff.c -- there is absolutely no hope of + getting that file to understand multiple GPs. GNU Libc provides a + hand-coded version that is used on Linux; it could be copied here + if there is ever a need. */ #undef STARTFILE_SPEC #define STARTFILE_SPEC \ "%{!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}" + crti.o%s crtbegin.o%s" -/* Provide a ENDFILE_SPEC appropriate for Linux. Here we tack on - the Linux 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 - Linux "finalizer" file, `crtn.o'. */ +/* Provide a ENDFILE_SPEC appropriate for ELF. Here we tack on the + magical crtend.o file which provides part of the support for + getting C++ file-scope static object constructed before entering + `main', followed by a normal ELF "finalizer" file, `crtn.o'. */ #undef ENDFILE_SPEC #define ENDFILE_SPEC \ - "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + "crtend.o%s crtn.o%s" + +/* We support #pragma. */ +#define HANDLE_SYSV_PRAGMA diff --git a/contrib/gcc/config/alpha/linux-ecoff.h b/contrib/gcc/config/alpha/linux-ecoff.h new file mode 100644 index 0000000..a6cd5b2 --- /dev/null +++ b/contrib/gcc/config/alpha/linux-ecoff.h @@ -0,0 +1,36 @@ +/* Definitions of target machine for GNU compiler + for Alpha Linux-based GNU systems using ECOFF. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Bob Manson. + +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. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ECOFF)"); + +#undef SUB_CPP_PREDEFINES +#define SUB_CPP_PREDEFINES "-D__ECOFF__" + +#undef LINK_SPEC +#define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}" + +/* stabs get slurped by the assembler into a queer ecoff format. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* We support #pragma. */ +#define HANDLE_SYSV_PRAGMA diff --git a/contrib/gcc/config/alpha/linux-elf.h b/contrib/gcc/config/alpha/linux-elf.h new file mode 100644 index 0000000..90009f1 --- /dev/null +++ b/contrib/gcc/config/alpha/linux-elf.h @@ -0,0 +1,47 @@ +/* Definitions of target machine for GNU compiler + for Alpha Linux-based GNU systems using ELF. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Henderson. + +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. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ELF)"); + +#undef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS \ +{ "elf_dynamic_linker", ELF_DYNAMIC_LINKER }, + +#undef SUB_CPP_PREDEFINES +#define SUB_CPP_PREDEFINES "-D__ELF__" + +#ifdef USE_GNULIBC_1 +#define ELF_DYNAMIC_LINKER "/lib/ld.so.1" +#else +#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2" +#endif + +#ifndef USE_GNULIBC_1 +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 1 +#endif + +#ifndef USE_GNULIBC_1 +#undef LIB_SPEC +#define LIB_SPEC \ +"%{shared:-lc}%{!shared:%{pthread:-lpthread }%{profile:-lc_p}%{!profile:-lc}} " +#endif diff --git a/contrib/gcc/config/alpha/linux.h b/contrib/gcc/config/alpha/linux.h new file mode 100644 index 0000000..3791c89 --- /dev/null +++ b/contrib/gcc/config/alpha/linux.h @@ -0,0 +1,44 @@ +/* Definitions of target machine for GNU compiler, + for Alpha Linux-based GNU systems. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Richard Henderson. + +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. */ + +#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 + +#undef LIB_SPEC +#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}" + +/* Generate calls to memcpy, etc., not bcopy, etc. */ +#define TARGET_MEM_FUNCTIONS 1 + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fputs ("\tlda $28,_mcount\n\tjsr $28,($28),_mcount\n", (FILE)) + +/* Show that we need a GP when profiling. */ +#define TARGET_PROFILING_NEEDS_GP 1 + +/* Don't care about faults in the prologue. */ +#undef TARGET_CAN_FAULT_IN_PROLOGUE +#define TARGET_CAN_FAULT_IN_PROLOGUE 1 diff --git a/contrib/gcc/config/alpha/netbsd-elf.h b/contrib/gcc/config/alpha/netbsd-elf.h new file mode 100644 index 0000000..17d7bb0 --- /dev/null +++ b/contrib/gcc/config/alpha/netbsd-elf.h @@ -0,0 +1,31 @@ +/* Definitions of target machine for GNU compiler + for Alpha NetBSD systems using ELF. + 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (Alpha NetBSD/ELF)"); + +#undef SUB_CPP_PREDEFINES +#define SUB_CPP_PREDEFINES "-D__ELF__" + +#undef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS \ +{ "elf_dynamic_linker", ELF_DYNAMIC_LINKER }, + +#define ELF_DYNAMIC_LINKER "/usr/libexec/ld.elf_so" diff --git a/contrib/gcc/config/alpha/netbsd.h b/contrib/gcc/config/alpha/netbsd.h new file mode 100644 index 0000000..054e9e0 --- /dev/null +++ b/contrib/gcc/config/alpha/netbsd.h @@ -0,0 +1,38 @@ +/* Definitions of target machine for GNU compiler, + for Alpha NetBSD systems. + 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS) + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D_LONGLONG -Dnetbsd -Dunix " SUB_CPP_PREDEFINES + +#undef LIB_SPEC +#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}" + +/* Generate calls to memcpy, etc., not bcopy, etc. */ +#define TARGET_MEM_FUNCTIONS + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fputs ("\tlda $28,_mcount\n\tjsr $28,($28),_mcount\n", (FILE)) + +/* Show that we need a GP when profiling. */ +#define TARGET_PROFILING_NEEDS_GP diff --git a/contrib/gcc/config/alpha/openbsd.h b/contrib/gcc/config/alpha/openbsd.h new file mode 100644 index 0000000..60591d5 --- /dev/null +++ b/contrib/gcc/config/alpha/openbsd.h @@ -0,0 +1,126 @@ +/* Configuration file for an alpha OpenBSD target. + 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. */ + +/* We settle for little endian for now. */ +#define TARGET_ENDIAN_DEFAULT 0 + +#include + +#define OBSD_NO_DYNAMIC_LIBRARIES +#define OBSD_HAS_DECLARE_FUNCTION_NAME +#define OBSD_HAS_DECLARE_FUNCTION_SIZE +#define OBSD_HAS_DECLARE_OBJECT + +/* alpha ecoff supports only weak aliases, see below. */ +#define ASM_WEAKEN_LABEL(FILE,NAME) ASM_OUTPUT_WEAK_ALIAS (FILE,NAME,0) + +#include + +/* Controlling the compilation driver. */ + +/* alpha needs __start. */ +#undef LINK_SPEC +#define LINK_SPEC \ + "%{!nostdlib:%{!r*:%{!e*:-e __start}}} -dc -dp %{assert*}" + +/* run-time target specifications */ +#define CPP_PREDEFINES "-D__unix__ -D__ANSI_COMPAT -Asystem(unix) \ +-D__OpenBSD__ -D__alpha__ -D__alpha" + +/* Layout of source language data types. */ + +/* This must agree with */ +#undef SIZE_TYPE +#define SIZE_TYPE "long unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#define LOCAL_LABEL_PREFIX "." + +/* We don't have an init section yet. */ +#undef HAS_INIT_SECTION + +/* collect2 support (assembler format: macros for initialization). */ + +/* Don't tell collect2 we use COFF as we don't have (yet ?) a dynamic ld + library with the proper functions to handle this -> collect2 will + default to using nm. */ +#undef OBJECT_FORMAT_COFF +#undef EXTENDED_COFF + +/* Assembler format: exception region output. */ + +/* All configurations that don't use elf must be explicit about not using + dwarf unwind information. egcs doesn't try too hard to check internal + configuration files... */ +#ifdef INCOMING_RETURN_ADDR_RTX +#undef DWARF2_UNWIND_INFO +#define DWARF2_UNWIND_INFO 0 +#endif + +/* Assembler format: file framework. */ + +/* Taken from alpha/osf.h. This used to be common to all alpha + configurations, but elf has departed from it. + Check alpha/alpha.h, alpha/osf.h for it when egcs is upgraded. */ +#ifndef 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"); \ + if (TARGET_SUPPORT_ARCH) \ + fprintf (FILE, "\t.arch %s\n", \ + alpha_cpu == PROCESSOR_EV6 ? "ev6" \ + : (alpha_cpu == PROCESSOR_EV5 \ + ? (TARGET_MAX ? "pca56" : TARGET_BWX ? "ev56" : "ev5") \ + : "ev4")); \ + \ + ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ +} +#endif + +/* Assembler format: label output. */ + +#define ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,VALUE) \ + do { \ + fputs ("\t.weakext\t", FILE); \ + assemble_name (FILE, NAME); \ + if (VALUE) \ + { \ + fputs (" , ", FILE); \ + assemble_name (FILE, VALUE); \ + } \ + fputc ('\n', FILE); \ + } while (0) + + diff --git a/contrib/gcc/config/alpha/osf.h b/contrib/gcc/config/alpha/osf.h new file mode 100644 index 0000000..956961f --- /dev/null +++ b/contrib/gcc/config/alpha/osf.h @@ -0,0 +1,127 @@ +/* Definitions of target machine for GNU compiler, for DEC Alpha on OSF/1. + Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. + 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. */ + +/* As of OSF 4.0, as can subtract adjacent labels. */ + +#undef TARGET_AS_CAN_SUBTRACT_LABELS +#define TARGET_AS_CAN_SUBTRACT_LABELS 1 + +/* Names to predefine in the preprocessor for this target machine. */ + +#define CPP_PREDEFINES "\ +-Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD \ +-D_SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4)" + +/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */ + +#define LIB_SPEC "%{p:-lprof1 -lpdf} %{pg:-lprof1 -lpdf} %{a:-lprof2} -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 + -call_shared as appropriate. Also pass -pg. */ +#define LINK_SPEC \ + "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \ + %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \ + %{rpath*}" + +#define STARTFILE_SPEC \ + "%{!shared:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}" + +#define MD_STARTFILE_PREFIX "/usr/lib/cmplrs/cc/" + +#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"); \ + if (TARGET_SUPPORT_ARCH) \ + fprintf (FILE, "\t.arch %s\n", \ + alpha_cpu == PROCESSOR_EV6 ? "ev6" \ + : (alpha_cpu == PROCESSOR_EV5 \ + ? (TARGET_MAX ? "pca56" : TARGET_BWX ? "ev56" : "ev5") \ + : "ev4")); \ + \ + ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ +} + +/* No point in running CPP on our assembler output. */ +#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 +/* Don't pass -g to GNU as, because some versions don't accept this option. */ +#define ASM_SPEC "%{malpha-as:-g} -nocpp %{pg}" +#else +/* In OSF/1 v3.2c, the assembler by default does not output file names which + causes mips-tfile to fail. Passing -g to the assembler fixes this problem. + ??? Strictly speaking, we need -g only if the user specifies -g. Passing + it always means that we get slightly larger than necessary object files + if the user does not specify -g. If we don't pass -g, then mips-tfile + will need to be fixed to work in this case. Pass -O0 since some + optimization are broken and don't help us anyway. */ +#define ASM_SPEC "%{!mgas:-g} -nocpp %{pg} -O0" +#endif + +/* Specify to run a post-processor, mips-tfile after the assembler + has run to stuff the ecoff debug information into the object file. + This is needed because the Alpha assembler provides no way + of specifying such information in the assembly file. */ + +#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 + +#define ASM_FINAL_SPEC "\ +%{malpha-as: %{!mno-mips-tfile: \ + \n mips-tfile %{v*: -v} \ + %{K: -I %b.o~} \ + %{!K: %{save-temps: -I %b.o~}} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ + %{.s:%i} %{!.s:%g.s}}}" + +#else +#define ASM_FINAL_SPEC "\ +%{!mgas: %{!mno-mips-tfile: \ + \n mips-tfile %{v*: -v} \ + %{K: -I %b.o~} \ + %{!K: %{save-temps: -I %b.o~}} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ + %{.s:%i} %{!.s:%g.s}}}" + +#endif + +/* Indicate that we have a stamp.h to use. */ +#ifndef CROSS_COMPILE +#define HAVE_STAMP_H 1 +#endif + +/* Attempt to turn on access permissions for the stack. */ + +#define TRANSFER_FROM_TRAMPOLINE \ +void \ +__enable_execute_stack (addr) \ + void *addr; \ +{ \ + 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"); \ +} diff --git a/contrib/gcc/config/alpha/osf12.h b/contrib/gcc/config/alpha/osf12.h index fe9112c..87e2111 100644 --- a/contrib/gcc/config/alpha/osf12.h +++ b/contrib/gcc/config/alpha/osf12.h @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler, for DEC Alpha. - Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) This file is part of GNU CC. @@ -19,9 +19,6 @@ 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/alpha.h" - /* In OSF 1.2, there is a linker bug that prevents use of -O3 to the linker. */ @@ -29,3 +26,8 @@ Boston, MA 02111-1307, USA. */ #define LINK_SPEC \ "-G 8 -O1 %{static:-non_shared} %{rpath*} \ %{!static:%{shared:-shared} %{!shared:-call_shared}} %{taso}" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "short unsigned int" +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 16 diff --git a/contrib/gcc/config/alpha/osf2or3.h b/contrib/gcc/config/alpha/osf2or3.h new file mode 100644 index 0000000..5abdb0e --- /dev/null +++ b/contrib/gcc/config/alpha/osf2or3.h @@ -0,0 +1,30 @@ +/* Definitions of target machine for GNU compiler, for DEC Alpha, osf[23]. + Copyright (C) 1997 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. */ + +/* In OSF 2 or 3, linking with -lprof1 doesn't require -lpdf. */ + +#undef LIB_SPEC +#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} %{a:-lprof2} -lc" + +/* As of OSF 3.2, as still can't subtract adjacent labels. */ + +#undef TARGET_AS_CAN_SUBTRACT_LABELS +#define TARGET_AS_CAN_SUBTRACT_LABELS 0 + diff --git a/contrib/gcc/config/alpha/t-crtbe b/contrib/gcc/config/alpha/t-crtbe new file mode 100644 index 0000000..5e82b92 --- /dev/null +++ b/contrib/gcc/config/alpha/t-crtbe @@ -0,0 +1,9 @@ +# Effectively disable the crtbegin/end rules using crtstuff.c +T = disable + +# Assemble startup files. +crtbegin.o: $(srcdir)/config/alpha/crtbegin.asm $(GCC_PASSES) + $(GCC_FOR_TARGET) -c -o crtbegin.o -x assembler $(srcdir)/config/alpha/crtbegin.asm + +crtend.o: $(srcdir)/config/alpha/crtend.asm $(GCC_PASSES) + $(GCC_FOR_TARGET) -c -o crtend.o -x assembler $(srcdir)/config/alpha/crtend.asm diff --git a/contrib/gcc/config/alpha/t-vms b/contrib/gcc/config/alpha/t-vms new file mode 100644 index 0000000..12ac240 --- /dev/null +++ b/contrib/gcc/config/alpha/t-vms @@ -0,0 +1,6 @@ +# Do not build libgcc1. +LIBGCC1 = +CROSS_LIBGCC1 = + +LIB2FUNCS_EXTRA = tramp.s + diff --git a/contrib/gcc/config/alpha/va_list.h b/contrib/gcc/config/alpha/va_list.h new file mode 100644 index 0000000..c9ab2b0 --- /dev/null +++ b/contrib/gcc/config/alpha/va_list.h @@ -0,0 +1,16 @@ +/* A replacement for Digital Unix's . */ + +#include + +#if !defined(_VA_LIST) && !defined(_HIDDEN_VA_LIST) +#define _VA_LIST +typedef __gnuc_va_list va_list; + +#elif defined(_HIDDEN_VA_LIST) && !defined(_HIDDEN_VA_LIST_DONE) +#define _HIDDEN_VA_LIST_DONE +typedef __gnuc_va_list __va_list; + +#elif defined(_HIDDEN_VA_LIST) && defined(_VA_LIST) +#undef _HIDDEN_VA_LIST + +#endif diff --git a/contrib/gcc/config/alpha/vms-tramp.asm b/contrib/gcc/config/alpha/vms-tramp.asm new file mode 100644 index 0000000..fce9ec5 --- /dev/null +++ b/contrib/gcc/config/alpha/vms-tramp.asm @@ -0,0 +1,22 @@ +;# New Alpha OpenVMS trampoline +;# + .set noreorder + .set volatile + .set noat + .file 1 "tramp.s" +.text + .align 3 + .globl __tramp + .ent __tramp +__tramp..en: + +.link + .align 3 +__tramp: + .pdesc __tramp..en,null +.text + ldq $1,24($27) + ldq $27,16($27) + ldq $28,8($27) + jmp $31,($28),0 + .end __tramp diff --git a/contrib/gcc/config/alpha/vms.h b/contrib/gcc/config/alpha/vms.h new file mode 100644 index 0000000..44cf5bf --- /dev/null +++ b/contrib/gcc/config/alpha/vms.h @@ -0,0 +1,510 @@ +/* Output variables, constants and external declarations, for GNU compiler. + Copyright (C) 1996, 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 +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 OPEN_VMS 1 + +/* This enables certain macros in alpha.h, which will make an indirect + reference to an external symbol an invalid address. This needs to be + defined before we include alpha.h, since it determines which macros + are used for GO_IF_*. */ + +#define NO_EXTERNAL_INDIRECT_ADDRESS + +#include "alpha/alpha.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ +"-D__ALPHA -Dvms -DVMS -D__vms__ -D__VMS__ -Asystem(vms)" + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "\ +%{mfloat-ieee:-D__IEEE_FLOAT} \ +%{mfloat-vax:-D__G_FLOAT} \ +%{!mfloat-vax:-D__IEEE_FLOAT}" + +/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */ + +#define LIB_SPEC "%{p:-lprof1 -lpdf} %{pg:-lprof1 -lpdf} %{a:-lprof2} -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 + -call_shared as appropriate. Also pass -pg. */ +#define LINK_SPEC \ + "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \ + %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \ + %{rpath*}" + +/* We allow $'s in identifiers unless -ansi is used .. */ + +#define DOLLARS_IN_IDENTIFIERS 2 + +/* These match the definitions used in DECCRTL, the VMS C run-time library + +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +*/ + +/* Use memcpy for structure copying, and so forth. */ +#define TARGET_MEM_FUNCTIONS + +/* By default, allow $ to be part of an identifier. */ +#define DOLLARS_IN_IDENTIFIERS 2 + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_FP|MASK_FPREGS|MASK_GAS) +#undef TARGET_OPEN_VMS +#define TARGET_OPEN_VMS 1 + +#undef TARGET_NAME +#define TARGET_NAME "OpenVMS/Alpha" +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME); + +/* The structure return address arrives as an "argument" on VMS. */ +#undef STRUCT_VALUE_REGNUM +#define STRUCT_VALUE 0 +#undef PCC_STATIC_STRUCT_RETURN + +/* no floating emulation. */ +#undef REAL_ARITHMETIC + +/* "long" is 32 bits. */ +#undef LONG_TYPE_SIZE +#define LONG_TYPE_SIZE 32 + +/* 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 + +#define MAX_OFILE_ALIGNMENT 524288 /* 8 x 2^16 by DEC Ada Test CD40VRA */ + +#undef FIXED_REGISTERS +#define FIXED_REGISTERS \ + {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, \ + 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 } + +#undef CALL_USED_REGISTERS +#define CALL_USED_REGISTERS \ + {1, 1, 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, 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 } + +#undef HARD_FRAME_POINTER_REGNUM +#define HARD_FRAME_POINTER_REGNUM 29 + +#undef CAN_ELIMINATE +#define CAN_ELIMINATE(FROM, TO) \ +((TO) != STACK_POINTER_REGNUM || ! alpha_using_fp ()) + +#undef INITIAL_ELIMINATION_OFFSET +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ +{ if ((FROM) == FRAME_POINTER_REGNUM) \ + (OFFSET) = alpha_sa_size () + alpha_pv_save_size (); \ + else if ((FROM) == ARG_POINTER_REGNUM) \ + (OFFSET) = (ALPHA_ROUND (alpha_sa_size () + alpha_pv_save_size () \ + + get_frame_size () \ + + current_function_pretend_args_size) \ + - current_function_pretend_args_size); \ + if ((TO) == STACK_POINTER_REGNUM) \ + (OFFSET) += ALPHA_ROUND (current_function_outgoing_args_size); \ +} + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. + + On Alpha/VMS, this is a structure that contains the number of + arguments and, for each argument, the datatype of that argument. + + The number of arguments is a number of words of arguments scanned so far. + Thus 6 or more means all following args should go on the stack. */ + +enum avms_arg_type {I64, FF, FD, FG, FS, FT}; +typedef struct {char num_args; enum avms_arg_type atypes[6];} avms_arg_info; + +#undef CUMULATIVE_ARGS +#define CUMULATIVE_ARGS avms_arg_info + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +#undef INIT_CUMULATIVE_ARGS +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ + (CUM).num_args = 0; \ + (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64; \ + (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64; + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + +extern enum avms_arg_type alpha_arg_type (); + +/* Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode (or VOIDmode for no more args). + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). + + On Alpha the first 6 words of args are normally in registers + and the rest are pushed. */ + +extern struct rtx_def *alpha_arg_info_reg_val (); +#undef FUNCTION_ARG +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +((MODE) == VOIDmode ? alpha_arg_info_reg_val (CUM) \ + : ((CUM.num_args) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ + ? gen_rtx(REG, (MODE), \ + ((CUM).num_args + 16 \ + + ((TARGET_FPREGS \ + && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ + || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ + * 32))) \ + : 0)) + +#undef FUNCTION_ARG_ADVANCE +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + if (MUST_PASS_IN_STACK (MODE, TYPE)) \ + (CUM).num_args += 6; \ + else \ + { \ + if ((CUM).num_args < 6) \ + (CUM).atypes[(CUM).num_args] = alpha_arg_type (MODE); \ + \ + (CUM).num_args += ALPHA_ARG_SIZE (MODE, TYPE, NAMED); \ + } + +/* For an arg passed partly in registers and partly in memory, + this is the number of registers used. + For args passed entirely in registers or entirely in memory, zero. */ + +#undef FUNCTION_ARG_PARTIAL_NREGS +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ +((CUM).num_args < 6 && 6 < (CUM).num_args \ + + ALPHA_ARG_SIZE (MODE, TYPE, NAMED) \ + ? 6 - (CUM).num_args : 0) + +/* Perform any needed actions needed for a function that is receiving a + variable number of arguments. + + CUM is as for INIT_CUMULATIVE_ARGS. + + MODE and TYPE are the mode and type of the current parameter. + + PRETEND_SIZE is a variable that should be set to the amount of stack + that must be pushed by the prolog to pretend that our caller pushed + it. + + Normally, this macro will push all remaining incoming registers on the + stack and set PRETEND_SIZE to the length of the registers pushed. + + For VMS, we allocate space for all 6 arg registers plus a count. + + However, if NO registers need to be saved, don't allocate any space. + This is not only because we won't need the space, but because AP includes + the current_pretend_args_size and we don't want to mess up any + ap-relative addresses already made. */ + +#undef SETUP_INCOMING_VARARGS +#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ +{ if ((CUM).num_args < 6) \ + { \ + if (! (NO_RTL)) \ + { \ + emit_move_insn (gen_rtx (REG, DImode, 1), \ + virtual_incoming_args_rtx); \ + emit_insn (gen_arg_home ()); \ + } \ + \ + PRETEND_SIZE = 7 * UNITS_PER_WORD; \ + } \ +} + +#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"); \ + ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ +} + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.%c_floating %s\n", (TARGET_FLOAT_VAX)?'f':'s', str); \ + } \ + } + +#define LINK_SECTION_ASM_OP ".link" +#define READONLY_SECTION_ASM_OP ".rdata" +#define LITERALS_SECTION_ASM_OP ".literals" +#define CTORS_SECTION_ASM_OP ".ctors" +#define DTORS_SECTION_ASM_OP ".dtors" + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_link, in_rdata, in_literals, in_ctors, in_dtors + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ +void \ +readonly_section () \ +{ \ + if (in_section != in_rdata) \ + { \ + fprintf (asm_out_file, "%s\n", READONLY_SECTION_ASM_OP); \ + in_section = in_rdata; \ + } \ +} \ +void \ +link_section () \ +{ \ + if (in_section != in_link) \ + { \ + fprintf (asm_out_file, "%s\n", LINK_SECTION_ASM_OP); \ + in_section = in_link; \ + } \ +} \ +void \ +literals_section () \ +{ \ + if (in_section != in_literals) \ + { \ + fprintf (asm_out_file, "%s\n", LITERALS_SECTION_ASM_OP); \ + in_section = in_literals; \ + } \ +} \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) abort () + +#undef ASM_OUTPUT_ADDR_VEC_ELT +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\t.quad $L%d\n", (VALUE)) + +#undef READONLY_DATA_SECTION +#define READONLY_DATA_SECTION readonly_section + +#define ASM_FILE_END(FILE) alpha_write_linkage (FILE); + +#undef CASE_VECTOR_MODE +#define CASE_VECTOR_MODE DImode +#undef CASE_VECTOR_PC_RELATIVE + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \ +{ ASM_OUTPUT_ALIGN (FILE, 3); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); } + +/* This says how to output assembler code to declare an + uninitialized external linkage data object. */ + +#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) + +#define NO_MD_PROTOTYPES + +/* 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. + Note that $27 has been set to the address of the trampoline, so we can + use it for addressability of the two data items. Trampolines are always + aligned to FUNCTION_BOUNDARY, which is 64 bits. */ + +#undef TRAMPOLINE_TEMPLATE +#define TRAMPOLINE_TEMPLATE(FILE) \ +{ \ + fprintf (FILE, "\t.quad 0\n"); \ + fprintf (FILE, "\t.linkage __tramp\n"); \ + fprintf (FILE, "\t.quad 0\n"); \ +} + +/* Length in units of the trampoline for entering a nested function. */ + +#undef TRAMPOLINE_SIZE +#define TRAMPOLINE_SIZE 32 + +/* 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, 16, 24, -1) + +/* 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.quad "); \ + 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.quad "); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, NAME, ARGS) \ + (vms_valid_decl_attribute_p (DECL, ATTRIBUTES, NAME, ARGS)) +extern int vms_valid_decl_attribute_p (); + +#undef SDB_DEBUGGING_INFO +#undef MIPS_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO + +#define DWARF2_DEBUGGING_INFO + +/* 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) \ + 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 () \ + : named_section (NULL_TREE, SECTION, 0), \ + ASM_OUTPUT_ALIGN (FILE, 0) \ + +#define ASM_OUTPUT_SECTION_NAME(FILE,DECL,NAME,RELOC) \ + do \ + { \ + char *flags; \ + int ovr = 0; \ + if (DECL && DECL_MACHINE_ATTRIBUTES (DECL) \ + && lookup_attribute \ + ("overlaid", DECL_MACHINE_ATTRIBUTES (DECL))) \ + flags = ",OVR", ovr = 1; \ + else if (strncmp (NAME,".debug", 6) == 0) \ + flags = ",NOWRT"; \ + else \ + flags = ""; \ + fputc ('\n', (FILE)); \ + fprintf (FILE, ".section\t%s%s\n", NAME, flags); \ + if (ovr) \ + (NAME) = ""; \ + } while (0) + +#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \ + do { literals_section(); \ + fprintf ((FILE), "\t"); \ + assemble_name (FILE, LABEL1); \ + fprintf (FILE, " = "); \ + assemble_name (FILE, LABEL2); \ + fprintf (FILE, "\n"); \ + } while (0) + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +#undef ASM_FORMAT_PRIVATE_NAME +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \ + sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) + +/* ??? VMS uses different linkage. */ +#undef ASM_OUTPUT_MI_THUNK + +#undef ASM_SPEC +#undef ASM_FINAL_SPEC +#undef LINK_SPEC +#undef STARTFILE_SPEC +#define ASM_SPEC "-nocpp %{pg}" +#define LINK_SPEC "%{g3:-g3} %{g0:-g0} %{shared:-shared} %{v:-v}" + +/* Define the names of the division and modulus functions. */ +#define DIVSI3_LIBCALL "OTS$DIV_I" +#define DIVDI3_LIBCALL "OTS$DIV_L" +#define UDIVSI3_LIBCALL "OTS$DIV_UI" +#define UDIVDI3_LIBCALL "OTS$DIV_UL" +#define MODSI3_LIBCALL "OTS$REM_I" +#define MODDI3_LIBCALL "OTS$REM_L" +#define UMODSI3_LIBCALL "OTS$REM_UI" +#define UMODDI3_LIBCALL "OTS$REM_UL" + +#define DIR_SEPARATOR ']' + +#define PREFIX "GNU_ROOT:" diff --git a/contrib/gcc/config/alpha/vxworks.h b/contrib/gcc/config/alpha/vxworks.h new file mode 100644 index 0000000..6dee4b3 --- /dev/null +++ b/contrib/gcc/config/alpha/vxworks.h @@ -0,0 +1,51 @@ +/* Definitions of target machine for GNU compiler. Vxworks Alpha version. + 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. */ + +/* This file just exists to give specs for the Alpha running on VxWorks. */ + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "\ +%{mvxsim:-DCPU=SIMALPHADUNIX} \ +%{!mvxsim: %{!mcpu*|mcpu=21064:-DCPU=21064} %{mcpu=21164:-DCPU=21164}} \ +%{posix: -D_POSIX_SOURCE}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "\ +-D__vxworks -D__alpha_vxworks -Asystem(vxworks) \ +-Asystem(embedded) -D_LONGLONG" + +/* 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/alpha/x-alpha b/contrib/gcc/config/alpha/x-alpha index 9919747..9686ab9 100644 --- a/contrib/gcc/config/alpha/x-alpha +++ b/contrib/gcc/config/alpha/x-alpha @@ -1 +1,2 @@ CLIB=-lmld +EXTRA_HEADERS = $(srcdir)/config/alpha/va_list.h diff --git a/contrib/gcc/config/alpha/xm-alpha.h b/contrib/gcc/config/alpha/xm-alpha.h index 642e1cf..7665127 100644 --- a/contrib/gcc/config/alpha/xm-alpha.h +++ b/contrib/gcc/config/alpha/xm-alpha.h @@ -41,12 +41,18 @@ Boston, MA 02111-1307, USA. */ #define SUCCESS_EXIT_CODE 0 #define FATAL_EXIT_CODE 33 -/* If not compiled with GNU C, use the builtin alloca. */ -#if !defined(__GNUC__) && !defined(_WIN32) +/* If compiled with GNU C, use the builtin alloca. */ +#ifndef alloca +#if defined(__GNUC__) && !defined(USE_C_ALLOCA) +#define alloca __builtin_alloca +#else +#if !defined(_WIN32) && !defined(USE_C_ALLOCA) && !defined(OPEN_VMS) #include #else extern void *alloca (); #endif +#endif +#endif /* The host compiler has problems with enum bitfields since it makes them signed so we can't fit all our codes in. */ @@ -65,14 +71,6 @@ extern void *malloc (), *realloc (), *calloc (); #include "string.h" #endif -/* OSF/1 has vprintf. */ - -#define HAVE_VPRINTF - -/* OSF/1 has putenv. */ - -#define HAVE_PUTENV - /* OSF/1 is POSIX.1 compliant. */ #define POSIX diff --git a/contrib/gcc/config/alpha/xm-openbsd.h b/contrib/gcc/config/alpha/xm-openbsd.h new file mode 100644 index 0000000..50f4366 --- /dev/null +++ b/contrib/gcc/config/alpha/xm-openbsd.h @@ -0,0 +1,23 @@ +/* Configuration file for an host running alpha OpenBSD. + 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 +#include + diff --git a/contrib/gcc/config/alpha/xm-vms.h b/contrib/gcc/config/alpha/xm-vms.h new file mode 100644 index 0000000..472a225 --- /dev/null +++ b/contrib/gcc/config/alpha/xm-vms.h @@ -0,0 +1,93 @@ +/* Configuration for GNU C-compiler for openVMS/Alpha. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Klaus Kaempf (kkaempf@progis.de). + +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. */ + +/* If compiling with DECC, need to fix problem with + which defines a macro called FILE_TYPE that breaks "tree.h". + Fortunately it uses #ifndef to suppress multiple inclusions. + Three possible cases: + 1) has already been included -- ours will be no-op; + 2) will be included after us -- "theirs" will be no-op; + 3) isn't needed -- including it here shouldn't hurt. + In all three cases, the problem macro will be removed here. */ + +#include +#include +#include +#ifdef __DECC +#undef FILE_TYPE +#endif + +#undef HOST_BITS_PER_LONG +#define HOST_BITS_PER_LONG 32 + +#define HOST_WIDE_INT long long +#define HOST_BITS_PER_WIDE_INT 64 + +#undef SUCCESS_EXIT_CODE +#define SUCCESS_EXIT_CODE 1 +#undef FATAL_EXIT_CODE +#define FATAL_EXIT_CODE (44 | 0x10000000) /* Abort, and no DCL message. */ + +/* A couple of conditionals for execution machine are controlled here. */ +#ifndef VMS +#define VMS +#endif + +#define GCC_INCLUDE_DIR "" +/* Specify the list of include file directories. */ +#define INCLUDE_DEFAULTS \ +{ \ + { "GNU_GXX_INCLUDE:", "G++", 1, 1 }, \ + { "GNU_CC_INCLUDE:", "GCC", 0, 0 }, \ + { ".", 0, 0, 1 }, \ + { 0, 0, 0, 0 } \ +} + +/* Define a local equivalent (sort of) for unlink */ +#define unlink remove + +#define NEED_ATEXIT +#define HAVE_VPRINTF +#define HAVE_PUTENV +#define HAVE_STRERROR +#define HAVE_ATOLL + +#define NO_SYS_PARAMS_H /* Don't have */ +#define USE_C_ALLOCA /* Using alloca.c */ + +#define HAVE_FCNTL_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_STRING_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_TIME_H 1 +#define STDC_HEADERS 1 +#define HAVE_CPP_STRINGIFY 1 + +#if __STDC__ +extern void *alloca (size_t); +#else +extern char *alloca (unsigned int); +#endif + +#define OBJECT_SUFFIX ".obj" +#define EXECUTABLE_SUFFIX ".exe" diff --git a/contrib/gcc/config/aoutos.h b/contrib/gcc/config/aoutos.h index e9caa71..6f4e262 100644 --- a/contrib/gcc/config/aoutos.h +++ b/contrib/gcc/config/aoutos.h @@ -39,50 +39,3 @@ Boston, MA 02111-1307, USA. */ /* Define a symbol indicating that we are using aoutos.h. */ #define USING_AOUTOS_H - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. - If using GNU LD, tell it that this is part of the static destructor set. - This code works for any machine provided you use GNU as/ld. - If not using GNU LD, rely on a "collect" program to look for names defined - in the particular form we choose as global constructor function names. */ - -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - if (flag_gnu_linker) \ - { \ - /* Output an N_SETT (0x16, 22.) for the name. */ \ - fprintf (FILE, "%s \"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ - } \ - } while (0) - - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ - -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - if (flag_gnu_linker) \ - { \ - /* Output an N_SETT (0x16, 22.) for the name. */ \ - fprintf (FILE, "%s \"___DTOR_LIST__\",22,0,0,", ASM_STABS_OP); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ - } \ - } while (0) - -/* Likewise for entries we want to record for garbage collection. - Garbage collection is still under development. */ - -#define ASM_OUTPUT_GC_ENTRY(FILE,NAME) \ - do { \ - if (flag_gnu_linker) \ - { \ - /* Output an N_SETT (0x16, 22.) for the name. */ \ - fprintf (FILE, "%s \"___PTR_LIST__\",22,0,0,", ASM_STABS_OP); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ - } \ - } while (0) diff --git a/contrib/gcc/config/dbx.h b/contrib/gcc/config/dbx.h new file mode 100644 index 0000000..c5cd3b5 --- /dev/null +++ b/contrib/gcc/config/dbx.h @@ -0,0 +1,30 @@ +/* Prefer DBX (stabs) debugging information. + Copyright (C) 1996 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 causes gcc to prefer using DBX (stabs) debugging + information. The configure script will add a #include of this file + to tm.h when --with-stabs is used for certain targets. */ + +#ifndef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO +#endif + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG diff --git a/contrib/gcc/config/dbxcoff.h b/contrib/gcc/config/dbxcoff.h new file mode 100644 index 0000000..9497a70 --- /dev/null +++ b/contrib/gcc/config/dbxcoff.h @@ -0,0 +1,87 @@ +/* Definitions needed when using stabs embedded in COFF sections. + Copyright (C) 1996 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 COFF target which wishes to + support -gstabs generating stabs in sections, as produced by gas + and understood by gdb. */ + +/* Output DBX (stabs) debugging information if doing -gstabs. */ + +#undef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +/* Generate SDB debugging information by default. */ + +#ifndef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG +#endif + +/* Be function-relative for block and source line stab directives. */ + +#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 + +/* 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) \ + fprintf (FILE, \ + "\t.text\n\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO) + +/* Like block addresses, stabs line numbers are relative to the + current function. */ + +#undef ASM_OUTPUT_SOURCE_LINE +#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \ +{ if (write_symbols == SDB_DEBUG) { \ + fprintf ((FILE), "\t.ln\t%d\n", \ + ((sdb_begin_function_line > -1) \ + ? (LINE) - sdb_begin_function_line : 1)); \ + } else if (write_symbols == DBX_DEBUG) { \ + static int sym_lineno = 1; \ + char buffer[256]; \ + ASM_GENERATE_INTERNAL_LABEL (buffer, "LM", sym_lineno); \ + fprintf (FILE, ".stabn 68,0,%d,", LINE); \ + assemble_name (FILE, buffer); \ + 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++; \ + } } + +/* 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 diff --git a/contrib/gcc/config/float-i128.h b/contrib/gcc/config/float-i128.h new file mode 100644 index 0000000..6a9dd48 --- /dev/null +++ b/contrib/gcc/config/float-i128.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32, 64 and 128 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 113 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 33 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-16381) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 3.362103143112093506262677817321752603E-4932L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-4931) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 16384 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.189731495357231765085759326628007016E+4932L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 4932 + +#endif /* _FLOAT_H_ */ diff --git a/contrib/gcc/config/float-i32.h b/contrib/gcc/config/float-i32.h new file mode 100644 index 0000000..c834926 --- /dev/null +++ b/contrib/gcc/config/float-i32.h @@ -0,0 +1,96 @@ +/* float.h for target with only IEEE 32 bit floating point format */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 24 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 6 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-125) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 128 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 24 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 6 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-125) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 128 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 38 + +#endif /* _FLOAT_H_ */ diff --git a/contrib/gcc/config/float-i386.h b/contrib/gcc/config/float-i386.h new file mode 100644 index 0000000..2d14f70 --- /dev/null +++ b/contrib/gcc/config/float-i386.h @@ -0,0 +1,104 @@ +/* float.h for target with IEEE 32/64 bit and Intel 386 style 80 bit + floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 64 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 18 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#ifndef __LDBL_UNION__ +#define __LDBL_UNION__ +union __convert_long_double { + unsigned __convert_long_double_i[4]; + long double __convert_long_double_d; +}; +#endif +#define LDBL_EPSILON (__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x0, 0x80000000, 0x3fc0, 0x0}}).__convert_long_double_d) + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-16381) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN (__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x0, 0x80000000, 0x1, 0x0}}).__convert_long_double_d) + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-4931) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 16384 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX (__extension__ ((union __convert_long_double) {__convert_long_double_i: {0xffffffff, 0xffffffff, 0x107ffe, 0x0}}).__convert_long_double_d) + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 4932 + +#endif /* _FLOAT_H___ */ diff --git a/contrib/gcc/config/float-i64.h b/contrib/gcc/config/float-i64.h new file mode 100644 index 0000000..7dbe4e9 --- /dev/null +++ b/contrib/gcc/config/float-i64.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32 bit and 64 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/contrib/gcc/config/float-m68k.h b/contrib/gcc/config/float-m68k.h new file mode 100644 index 0000000..b36d447 --- /dev/null +++ b/contrib/gcc/config/float-m68k.h @@ -0,0 +1,97 @@ +/* float.h for target with IEEE 32 bit and 64 bit and Motorola style 96 bit + floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 64 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 18 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 1.08420217248550443401e-19L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-16382) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 1.68105157155604675313e-4932L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-4931) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 16384 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.18973149535723176502e+4932L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 4932 + +#endif /* _FLOAT_H_ */ diff --git a/contrib/gcc/config/float-sh.h b/contrib/gcc/config/float-sh.h new file mode 100644 index 0000000..9a94298 --- /dev/null +++ b/contrib/gcc/config/float-sh.h @@ -0,0 +1,130 @@ +/* float.h for target sh3e with optional IEEE 32 bit double format */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + +#ifdef __SH3E__ + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 24 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 6 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-125) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 128 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 38 + +#else + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + +#endif + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/contrib/gcc/config/float-vax.h b/contrib/gcc/config/float-vax.h new file mode 100644 index 0000000..3c87f79 --- /dev/null +++ b/contrib/gcc/config/float-vax.h @@ -0,0 +1,96 @@ +/* float.h for target with VAX floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-127) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 2.93873588e-39F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-38) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 127 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 1.70141173e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 56 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 16 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.77555756156289135e-17 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-127) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.93873587705571877e-39 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-38) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 127 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.70141183460469229e+38 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 56 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 16 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.77555756156289135e-17 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-127) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.93873587705571877e-39 + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-38) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 127 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.70141183460469229e+38 + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 38 + +#endif /* _FLOAT_H_ */ diff --git a/contrib/gcc/config/fp-bit.c b/contrib/gcc/config/fp-bit.c index 4ee08f1..f4a1e2a 100644 --- a/contrib/gcc/config/fp-bit.c +++ b/contrib/gcc/config/fp-bit.c @@ -1,8 +1,7 @@ /* This is a software floating point library which can be used instead of the floating point routines in libgcc1.c for targets without hardware - floating point. */ - -/* Copyright (C) 1994, 1995 Free Software Foundation, Inc. + floating point. + Copyright (C) 1994, 1995, 1996, 1997, 1998 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 @@ -44,6 +43,55 @@ Boston, MA 02111-1307, USA. */ /* The intended way to use this file is to make two copies, add `#define FLOAT' to one copy, then compile both copies and add them to libgcc.a. */ +/* Defining FINE_GRAINED_LIBRARIES allows one to select which routines + from this file are compiled via additional -D options. + + This avoids the need to pull in the entire fp emulation library + when only a small number of functions are needed. + + If FINE_GRAINED_LIBRARIES is not defined, then compile every + suitable routine. */ +#ifndef FINE_GRAINED_LIBRARIES +#define L_pack_df +#define L_unpack_df +#define L_pack_sf +#define L_unpack_sf +#define L_addsub_sf +#define L_addsub_df +#define L_mul_sf +#define L_mul_df +#define L_div_sf +#define L_div_df +#define L_fpcmp_parts_sf +#define L_fpcmp_parts_df +#define L_compare_sf +#define L_compare_df +#define L_eq_sf +#define L_eq_df +#define L_ne_sf +#define L_ne_df +#define L_gt_sf +#define L_gt_df +#define L_ge_sf +#define L_ge_df +#define L_lt_sf +#define L_lt_df +#define L_le_sf +#define L_le_df +#define L_si_to_sf +#define L_si_to_df +#define L_sf_to_si +#define L_df_to_si +#define L_f_to_usi +#define L_df_to_usi +#define L_negate_sf +#define L_negate_df +#define L_make_sf +#define L_make_df +#define L_sf_to_df +#define L_df_to_sf +#endif + /* The following macros can be defined to change the behaviour of this file: FLOAT: Implement a `float', aka SFmode, fp library. If this is not defined, then this file implements a `double', aka DFmode, fp library. @@ -62,6 +110,52 @@ Boston, MA 02111-1307, USA. */ SMALL_MACHINE: Useful when operations on QIs and HIs are faster than on an SI */ +/* We don't currently support extended floats (long doubles) on machines + without hardware to deal with them. + + These stubs are just to keep the linker from complaining about unresolved + references which can be pulled in from libio & libstdc++, even if the + user isn't using long doubles. However, they may generate an unresolved + external to abort if abort is not used by the function, and the stubs + are referenced from within libc, since libgcc goes before and after the + system library. */ + +#ifdef EXTENDED_FLOAT_STUBS +__truncxfsf2 (){ abort(); } +__extendsfxf2 (){ abort(); } +__addxf3 (){ abort(); } +__divxf3 (){ abort(); } +__eqxf2 (){ abort(); } +__extenddfxf2 (){ abort(); } +__gtxf2 (){ abort(); } +__lexf2 (){ abort(); } +__ltxf2 (){ abort(); } +__mulxf3 (){ abort(); } +__negxf2 (){ abort(); } +__nexf2 (){ abort(); } +__subxf3 (){ abort(); } +__truncxfdf2 (){ abort(); } + +__trunctfsf2 (){ abort(); } +__extendsftf2 (){ abort(); } +__addtf3 (){ abort(); } +__divtf3 (){ abort(); } +__eqtf2 (){ abort(); } +__extenddftf2 (){ abort(); } +__gttf2 (){ abort(); } +__letf2 (){ abort(); } +__lttf2 (){ abort(); } +__multf3 (){ abort(); } +__negtf2 (){ abort(); } +__netf2 (){ abort(); } +__subtf3 (){ abort(); } +__trunctfdf2 (){ abort(); } +__gexf2 (){ abort(); } +__fixxfsi (){ abort(); } +__floatsixf (){ abort(); } +#else /* !EXTENDED_FLOAT_STUBS, rest of file */ + + typedef SFtype __attribute__ ((mode (SF))); typedef DFtype __attribute__ ((mode (DF))); @@ -99,8 +193,9 @@ typedef unsigned int UDItype __attribute__ ((mode (DI))); # define FRAC_NBITS 32 # define FRACHIGH 0x80000000L # define FRACHIGH2 0xc0000000L -# define pack_d pack_f -# define unpack_d unpack_f +# define pack_d __pack_f +# define unpack_d __unpack_f +# define __fpcmp_parts __fpcmp_parts_f typedef USItype fractype; typedef UHItype halffractype; typedef SFtype FLO_type; @@ -121,6 +216,9 @@ typedef unsigned int UDItype __attribute__ ((mode (DI))); # define FRAC_NBITS 64 # define FRACHIGH 0x8000000000000000LL # define FRACHIGH2 0xc000000000000000LL +# define pack_d __pack_d +# define unpack_d __unpack_d +# define __fpcmp_parts __fpcmp_parts_d typedef UDItype fractype; typedef USItype halffractype; typedef DFtype FLO_type; @@ -191,7 +289,9 @@ typedef unsigned int UDItype __attribute__ ((mode (DI))); #endif +#ifndef INLINE #define INLINE __inline__ +#endif /* Preserve the sticky-bit when shifting fractions to the right. */ #define LSHIFT(a) { a = (a & 1) | (a >> 1); } @@ -199,7 +299,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI))); /* numeric parameters */ /* F_D_BITOFF is the number of bits offset between the MSB of the mantissa of a float and of a double. Assumes there are only two float types. - (double::FRAC_BITS+double::NGARGS-(float::FRAC_BITS-float::NGARDS)) + (double::FRAC_BITS+double::NGARDS-(float::FRAC_BITS-float::NGARDS)) */ #define F_D_BITOFF (52+8-(23+7)) @@ -328,7 +428,10 @@ flip_sign ( fp_number_type * x) x->sign = !x->sign; } -static FLO_type +extern FLO_type pack_d ( fp_number_type * ); + +#if defined(L_pack_df) || defined(L_pack_sf) +FLO_type pack_d ( fp_number_type * src) { FLO_union_type dst; @@ -414,7 +517,7 @@ pack_d ( fp_number_type * src) } /* We previously used bitfields to store the number, but this doesn't - handle little/big endian systems conviently, so use shifts and + handle little/big endian systems conveniently, so use shifts and masks */ #ifdef FLOAT_BIT_ORDER_MISMATCH dst.bits.fraction = fraction; @@ -436,12 +539,16 @@ pack_d ( fp_number_type * src) return dst.value; } +#endif -static void +extern void unpack_d (FLO_union_type *, fp_number_type *); + +#if defined(L_unpack_df) || defined(L_unpack_sf) +void unpack_d (FLO_union_type * src, fp_number_type * dst) { /* We previously used bitfields to store the number, but this doesn't - handle little/big endian systems conviently, so use shifts and + handle little/big endian systems conveniently, so use shifts and masks */ fractype fraction; int exp; @@ -504,13 +611,13 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) else { /* Non zero fraction, means nan */ - if (sign) + if (fraction & QUIET_NAN) { - dst->class = CLASS_SNAN; + dst->class = CLASS_QNAN; } else { - dst->class = CLASS_QNAN; + dst->class = CLASS_SNAN; } /* Keep the fraction part as the nan number */ dst->fraction.ll = fraction; @@ -524,7 +631,9 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1; } } +#endif +#if defined(L_addsub_sf) || defined(L_addsub_df) static fp_number_type * _fpadd_parts (fp_number_type * a, fp_number_type * b, @@ -559,6 +668,12 @@ _fpadd_parts (fp_number_type * a, } if (iszero (b)) { + if (iszero (a)) + { + *tmp = *a; + tmp->sign = a->sign & b->sign; + return tmp; + } return a; } if (iszero (a)) @@ -692,8 +807,10 @@ sub (FLO_type arg_a, FLO_type arg_b) return pack_d (res); } +#endif -static fp_number_type * +#if defined(L_mul_sf) || defined(L_mul_df) +static INLINE fp_number_type * _fpmul_parts ( fp_number_type * a, fp_number_type * b, fp_number_type * tmp) @@ -741,13 +858,13 @@ _fpmul_parts ( fp_number_type * a, /* Calculate the mantissa by multiplying both 64bit numbers to get a 128 bit number */ { - fractype x = a->fraction.ll; - fractype ylow = b->fraction.ll; - fractype yhigh = 0; - int bit; - #if defined(NO_DI_MODE) { + fractype x = a->fraction.ll; + fractype ylow = b->fraction.ll; + fractype yhigh = 0; + int bit; + /* ??? This does multiplies one bit at a time. Optimize. */ for (bit = 0; bit < FRAC_NBITS; bit++) { @@ -878,20 +995,18 @@ multiply (FLO_type arg_a, FLO_type arg_b) return pack_d (res); } +#endif -static fp_number_type * +#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) { - fractype low = 0; - fractype high = 0; - fractype r0, r1, y0, y1, bit; - fractype q; + fractype bit; fractype numerator; fractype denominator; fractype quotient; - fractype remainder; if (isnan (a)) { @@ -901,13 +1016,15 @@ _fpdiv_parts (fp_number_type * a, { return b; } + + a->sign = a->sign ^ b->sign; + if (isinf (a) || iszero (a)) { if (a->class == b->class) return nan (); return a; } - a->sign = a->sign ^ b->sign; if (isinf (b)) { @@ -918,15 +1035,12 @@ _fpdiv_parts (fp_number_type * a, if (iszero (b)) { a->class = CLASS_INFINITY; - return b; + return a; } /* Calculate the mantissa by multiplying both 64bit numbers to get a 128 bit number */ { - int carry; - intfrac d0, d1; /* weren't unsigned before ??? */ - /* quotient = ( numerator / denominator) * 2^(numerator exponent - denominator exponent) */ @@ -989,15 +1103,19 @@ divide (FLO_type arg_a, FLO_type arg_b) return pack_d (res); } +#endif +int __fpcmp_parts (fp_number_type * a, fp_number_type *b); + +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) /* according to the demo, fpcmp returns a comparison with 0... thus a -1 a==b -> 0 a>b -> +1 */ -static int -_fpcmp_parts (fp_number_type * a, fp_number_type * b) +int +__fpcmp_parts (fp_number_type * a, fp_number_type * b) { #if 0 /* either nan -> unordered. Must be checked outside of this routine. */ @@ -1072,7 +1190,9 @@ _fpcmp_parts (fp_number_type * a, fp_number_type * b) /* after all that, they're equal. */ return 0; } +#endif +#if defined(L_compare_sf) || defined(L_compare_df) CMPtype compare (FLO_type arg_a, FLO_type arg_b) { @@ -1082,13 +1202,15 @@ compare (FLO_type arg_a, FLO_type arg_b) unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); - return _fpcmp_parts (&a, &b); + return __fpcmp_parts (&a, &b); } +#endif #ifndef US_SOFTWARE_GOFAST /* These should be optimized for their specific tasks someday. */ +#if defined(L_eq_sf) || defined(L_eq_df) CMPtype _eq_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1101,9 +1223,11 @@ _eq_f2 (FLO_type arg_a, FLO_type arg_b) if (isnan (&a) || isnan (&b)) return 1; /* false, truth == 0 */ - return _fpcmp_parts (&a, &b) ; + return __fpcmp_parts (&a, &b) ; } +#endif +#if defined(L_ne_sf) || defined(L_ne_df) CMPtype _ne_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1116,9 +1240,11 @@ _ne_f2 (FLO_type arg_a, FLO_type arg_b) if (isnan (&a) || isnan (&b)) return 1; /* true, truth != 0 */ - return _fpcmp_parts (&a, &b) ; + return __fpcmp_parts (&a, &b) ; } +#endif +#if defined(L_gt_sf) || defined(L_gt_df) CMPtype _gt_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1131,9 +1257,11 @@ _gt_f2 (FLO_type arg_a, FLO_type arg_b) if (isnan (&a) || isnan (&b)) return -1; /* false, truth > 0 */ - return _fpcmp_parts (&a, &b); + return __fpcmp_parts (&a, &b); } +#endif +#if defined(L_ge_sf) || defined(L_ge_df) CMPtype _ge_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1145,9 +1273,11 @@ _ge_f2 (FLO_type arg_a, FLO_type arg_b) if (isnan (&a) || isnan (&b)) return -1; /* false, truth >= 0 */ - return _fpcmp_parts (&a, &b) ; + return __fpcmp_parts (&a, &b) ; } +#endif +#if defined(L_lt_sf) || defined(L_lt_df) CMPtype _lt_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1160,9 +1290,11 @@ _lt_f2 (FLO_type arg_a, FLO_type arg_b) if (isnan (&a) || isnan (&b)) return 1; /* false, truth < 0 */ - return _fpcmp_parts (&a, &b); + return __fpcmp_parts (&a, &b); } +#endif +#if defined(L_le_sf) || defined(L_le_df) CMPtype _le_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1175,11 +1307,13 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b) if (isnan (&a) || isnan (&b)) return 1; /* false, truth <= 0 */ - return _fpcmp_parts (&a, &b) ; + return __fpcmp_parts (&a, &b) ; } +#endif #endif /* ! US_SOFTWARE_GOFAST */ +#if defined(L_si_to_sf) || defined(L_si_to_df) FLO_type si_to_float (SItype arg_a) { @@ -1215,7 +1349,9 @@ si_to_float (SItype arg_a) } return pack_d (&in); } +#endif +#if defined(L_sf_to_si) || defined(L_df_to_si) SItype float_to_si (FLO_type arg_a) { @@ -1229,7 +1365,7 @@ float_to_si (FLO_type arg_a) return 0; /* get reasonable MAX_SI_INT... */ if (isinf (&a)) - return a.sign ? MAX_SI_INT : (-MAX_SI_INT)-1; + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; /* it is a number, but a small one */ if (a.normal_exp < 0) return 0; @@ -1238,7 +1374,9 @@ float_to_si (FLO_type arg_a) tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); return a.sign ? (-tmp) : (tmp); } +#endif +#if defined(L_sf_to_usi) || defined(L_df_to_usi) #ifdef US_SOFTWARE_GOFAST /* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines, we also define them for GOFAST because the ones in libgcc2.c have the @@ -1256,24 +1394,26 @@ float_to_usi (FLO_type arg_a) return 0; if (isnan (&a)) return 0; - /* get reasonable MAX_USI_INT... */ - if (isinf (&a)) - return a.sign ? MAX_USI_INT : 0; /* it is a negative number */ if (a.sign) return 0; + /* get reasonable MAX_USI_INT... */ + if (isinf (&a)) + return MAX_USI_INT; /* it is a number, but a small one */ if (a.normal_exp < 0) return 0; if (a.normal_exp > 31) return MAX_USI_INT; else if (a.normal_exp > (FRACBITS + NGARDS)) - return a.fraction.ll << ((FRACBITS + NGARDS) - a.normal_exp); + return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS)); else return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); } #endif +#endif +#if defined(L_negate_sf) || defined(L_negate_df) FLO_type negate (FLO_type arg_a) { @@ -1283,9 +1423,11 @@ negate (FLO_type arg_a) flip_sign (&a); return pack_d (&a); } +#endif #ifdef FLOAT +#if defined(L_make_sf) SFtype __make_fp(fp_class_type class, unsigned int sign, @@ -1300,6 +1442,7 @@ __make_fp(fp_class_type class, in.fraction.ll = frac; return pack_d (&in); } +#endif #ifndef FLOAT_ONLY @@ -1310,6 +1453,7 @@ __make_fp(fp_class_type class, extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype frac); +#if defined(L_sf_to_df) DFtype sf_to_df (SFtype arg_a) { @@ -1319,6 +1463,7 @@ sf_to_df (SFtype arg_a) return __make_dp (in.class, in.sign, in.normal_exp, ((UDItype) in.fraction.ll) << F_D_BITOFF); } +#endif #endif #endif @@ -1327,6 +1472,7 @@ sf_to_df (SFtype arg_a) extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); +#if defined(L_make_df) DFtype __make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac) { @@ -1338,15 +1484,27 @@ __make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac) in.fraction.ll = frac; return pack_d (&in); } +#endif +#if defined(L_df_to_sf) SFtype df_to_sf (DFtype arg_a) { fp_number_type in; + USItype sffrac; unpack_d ((FLO_union_type *) & arg_a, &in); - return __make_fp (in.class, in.sign, in.normal_exp, - in.fraction.ll >> F_D_BITOFF); + + sffrac = in.fraction.ll >> F_D_BITOFF; + + /* We set the lowest guard bit in SFFRAC if we discarded any non + zero bits. */ + if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0) + sffrac |= 1; + + return __make_fp (in.class, in.sign, in.normal_exp, sffrac); } +#endif #endif +#endif /* !EXTENDED_FLOAT_STUBS */ diff --git a/contrib/gcc/config/gnu.h b/contrib/gcc/config/gnu.h index 8ea3ead..d169164 100644 --- a/contrib/gcc/config/gnu.h +++ b/contrib/gcc/config/gnu.h @@ -1,12 +1,5 @@ /* Configuration common to all targets running the GNU system. */ -/* Macro to produce CPP_PREDEFINES for GNU on a given machine. */ -#define GNU_CPP_PREDEFINES(machine) \ -"-D" machine " -Acpu(" machine ") -Amachine(" machine ")" \ -"-Dunix -Asystem(unix) \ --DMACH -Asystem(mach) \ --D__GNU__ -Asystem(gnu)" - /* Provide GCC options for standard feature-test macros. */ #undef CPP_SPEC #define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{bsd:-D_BSD_SOURCE}" diff --git a/contrib/gcc/config/i386/386bsd.h b/contrib/gcc/config/i386/386bsd.h index cdab5f5..7962321 100644 --- a/contrib/gcc/config/i386/386bsd.h +++ b/contrib/gcc/config/i386/386bsd.h @@ -49,11 +49,6 @@ } \ } -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - #undef ASM_APP_ON #define ASM_APP_ON "#APP\n" @@ -68,13 +63,13 @@ i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 +#define JUMP_TABLES_IN_TEXT_SECTION 1 /* Don't default to pcc-struct-return, because gcc is the only compiler, and we want to retain compatibility with older gcc versions. */ diff --git a/contrib/gcc/config/i386/aix386ng.h b/contrib/gcc/config/i386/aix386ng.h index 5d09fc3..a177b69 100644 --- a/contrib/gcc/config/i386/aix386ng.h +++ b/contrib/gcc/config/i386/aix386ng.h @@ -1,6 +1,6 @@ /* Definitions for IBM PS2 running AIX/386. - From: Minh Tran-Le - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. + Contributed by Minh Tran-Le . This file is part of GNU CC. @@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */ #include "svr3.h" /* Use the ATT assembler syntax. - This overrides at least one macro (ASM_OUTPUT_LABELREF) from svr3.h. */ + This overrides at least one macro (USER_LABEL_PREFIX) from svr3.h. */ #include "i386/att.h" @@ -44,10 +44,10 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ -#define CPP_PREDEFINES "-Dps2 -Dunix -Di386 -Asystem(unix) -Asystem(aix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dps2 -Dunix -Asystem(aix)" -#define CPP_SPEC \ - "%{posix:-D_POSIX_SOURCE}%{!posix:-DAIX} -D_I386 -D_AIX -D_MBCS" +#define CPP_SPEC "%(cpp_cpu) \ + %{posix:-D_POSIX_SOURCE}%{!posix:-DAIX} -D_I386 -D_AIX -D_MBCS" /* special flags for the aix assembler to generate the short form for all qualifying forward reference */ @@ -132,8 +132,7 @@ const_section () \ # undef EXTRA_SECTION_FUNCTIONS # define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION + CONST_SECTION_FUNCTION /* for collect2 */ # define OBJECT_FORMAT_COFF diff --git a/contrib/gcc/config/i386/att.h b/contrib/gcc/config/i386/att.h index f8bbb76..e5c2d9c 100644 --- a/contrib/gcc/config/i386/att.h +++ b/contrib/gcc/config/i386/att.h @@ -1,5 +1,5 @@ /* Definitions for AT&T assembler syntax for the Intel 80386. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -68,18 +68,6 @@ do \ /* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */ #define ASM_NO_SKIP_IN_TEXT 1 - -#undef BSS_SECTION_FUNCTION /* Override the definition from svr3.h. */ -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} /* Define the syntax of labels and symbol definitions/declarations. */ @@ -99,8 +87,7 @@ bss_section () \ #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ fprintf (FILE, ".%s%d:\n", PREFIX, NUM) -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf (FILE, "%s", NAME) +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" diff --git a/contrib/gcc/config/i386/bsd.h b/contrib/gcc/config/i386/bsd.h index 6bf7399..d50be36 100644 --- a/contrib/gcc/config/i386/bsd.h +++ b/contrib/gcc/config/i386/bsd.h @@ -1,7 +1,7 @@ /* Definitions for BSD assembler syntax for Intel 386 (actually AT&T syntax for insns and operands, adapted to BSD conventions for symbol names and debugging.) - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -115,12 +115,12 @@ Boston, MA 02111-1307, USA. */ fprintf (FILE, "%s%d:\n", PREFIX, NUM) #endif -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ #ifdef NO_UNDERSCORES -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME) +#define USER_LABEL_PREFIX "" #else -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "_%s", NAME) +#define USER_LABEL_PREFIX "_" #endif /* not NO_UNDERSCORES */ /* Sequent has some changes in the format of DBX symbols. */ diff --git a/contrib/gcc/config/i386/bsd386.h b/contrib/gcc/config/i386/bsd386.h index 935a2e0..c0dcf87 100644 --- a/contrib/gcc/config/i386/bsd386.h +++ b/contrib/gcc/config/i386/bsd386.h @@ -1,5 +1,5 @@ -/* Configuration for an i386 running BSDI's BSD/386 1.1 as the target - machine. */ +/* Configuration for an i386 running BSDI's BSD/OS (formerly known as BSD/386) + as the target machine. */ #include "i386/386bsd.h" @@ -16,3 +16,18 @@ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 + +/* This is suitable for BSD/OS 3.0; we don't know about earlier releases. */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START " #" + +/* Until they use ELF or something that handles dwarf2 unwinds + and initialization stuff better. */ +#define DWARF2_UNWIND_INFO 0 + +/* BSD/OS still uses old binutils that don't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) diff --git a/contrib/gcc/config/i386/crtdll.h b/contrib/gcc/config/i386/crtdll.h new file mode 100644 index 0000000..f7eaf2b --- /dev/null +++ b/contrib/gcc/config/i386/crtdll.h @@ -0,0 +1,42 @@ +/* Operating system specific defines to be used when targeting GCC for + 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. + This variant uses CRTDLL.DLL insted of MSVCRTDLL.DLL. + 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. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \ + -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\ + -D__stdcall=__attribute__((__stdcall__)) \ + -D_stdcall=__attribute__((__stdcall__)) \ + -D__cdecl=__attribute__((__cdecl__)) \ + -D__declspec(x)=__attribute__((x)) \ + -Asystem(winnt) -Acpu(i386) -Amachine(i386)" + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lcrtdll" + +/* Specify a different entry point when linking a DLL */ +#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/dgux.c b/contrib/gcc/config/i386/dgux.c new file mode 100644 index 0000000..ff36135 --- /dev/null +++ b/contrib/gcc/config/i386/dgux.c @@ -0,0 +1,190 @@ +/* Subroutines for GNU compiler for Intel 80x86 running DG/ux + Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. + Currently maintained by (gcc@dg-rtp.dg.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. */ + +#include +#include "i386/i386.c" + + +extern char *version_string; + +struct option +{ + char *string; + int *variable; + int on_value; +}; + +static int +output_option (file, sep, type, name, indent, pos, max) + FILE *file; + char *sep; + char *type; + char *name; + char *indent; + int pos; + int max; +{ + if (strlen (sep) + strlen (type) + strlen (name) + pos > max) + { + fprintf (file, indent); + return fprintf (file, "%s%s", type, name); + } + return pos + fprintf (file, "%s%s%s", sep, type, name); +} + +static struct { char *name; int value; } m_options[] = TARGET_SWITCHES; + +static void +output_options (file, f_options, f_len, W_options, W_len, + pos, max, sep, indent, term) + FILE *file; + struct option *f_options; + struct option *W_options; + int f_len, W_len; + int pos; + int max; + char *indent; + char *term; +{ + register int j; + + if (optimize) + pos = output_option (file, sep, "-O", "", indent, pos, max); + if (write_symbols != NO_DEBUG) + pos = output_option (file, sep, "-g", "", indent, pos, max); +/* if (flag_traditional) + pos = output_option (file, sep, "-traditional", "", indent, pos, max);*/ + if (profile_flag) + pos = output_option (file, sep, "-p", "", indent, pos, max); + if (profile_block_flag) + pos = output_option (file, sep, "-a", "", indent, pos, max); + + for (j = 0; j < f_len; j++) + if (*f_options[j].variable == f_options[j].on_value) + pos = output_option (file, sep, "-f", f_options[j].string, + indent, pos, max); + + for (j = 0; j < W_len; j++) + if (*W_options[j].variable == W_options[j].on_value) + pos = output_option (file, sep, "-W", W_options[j].string, + indent, pos, max); + + for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++) + if (m_options[j].name[0] != '\0' + && m_options[j].value > 0 + && ((m_options[j].value & target_flags) + == m_options[j].value)) + pos = output_option (file, sep, "-m", m_options[j].name, + indent, pos, max); + + pos = output_option (file, sep, "-mcpu=", ix86_cpu_string, indent, pos, max); + pos = output_option (file, sep, "-march=", ix86_arch_string, indent, pos, max); + fprintf (file, term); +} + +/* Output to FILE the start of the assembler file. */ + +void +output_file_start (file, f_options, f_len, W_options, W_len) + FILE *file; + struct option *f_options; + struct option *W_options; + int f_len, W_len; +{ + register int pos; + + output_file_directive (file, main_input_filename); + fprintf (file, "\t.version\t\"01.01\"\n"); \ + /* Switch to the data section so that the coffsem symbol and the + gcc2_compiled. symbol aren't in the text section. */ + data_section (); + + pos = fprintf (file, "\n// cc1 (%s) arguments:", VERSION_STRING); + output_options (file, f_options, f_len, W_options, W_len, + pos, 75, " ", "\n// ", "\n\n"); + +#ifdef TARGET_IDENTIFY_REVISION + if (TARGET_IDENTIFY_REVISION) + { + char indent[256]; + + time_t now = time ((time_t *)0); + sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename); + fprintf (file, indent+3); + pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now)); + output_options (file, f_options, f_len, W_options, W_len, + pos, 150 - strlen (indent), " ", indent, "]\"\n\n"); + } +#endif /* TARGET_IDENTIFY_REVISION */ +} + +#ifndef CROSS_COMPILE +#if defined (_abort_aux) +/* Debugging aid to be registered via `atexit'. See the definition + of abort in dgux.h. */ +void +abort_aux () +{ + extern int insn_; + extern char * file_; + extern int line_; + static int done; + rtx line_note; + + if (done++) + return; + if (file_ || line_) + { + if (write_symbols != NO_DEBUG) + { + for (line_note = (rtx) insn_ ; line_note != 0 ; line_note = PREV_INSN (line_note)) + if (GET_CODE (line_note) == NOTE && NOTE_LINE_NUMBER (line_note) > 0) + break; + if (line_note != 0) + { + error_with_file_and_line (NOTE_SOURCE_FILE (line_note), + NOTE_LINE_NUMBER (line_note), + "Internal gcc abort from %s:%d", + file_ ? file_ : "", line_); + if (insn_ && file_ && strcmp (file_, "toplev.c")) + { + error_with_file_and_line (NOTE_SOURCE_FILE (line_note), + NOTE_LINE_NUMBER (line_note), + "The local variable `insn' has the value:", 0); + debug_rtx ((rtx) insn_); + } + } + } + if (write_symbols == NO_DEBUG || line_note == 0) + { + error ("Internal gcc abort from %s:%d", + file_ ? file_ : "", line_); + if (insn_ && file_ && strcmp (file_, "toplev.c")) + { + error ("The local variable `insn' has the value:", 0); + debug_rtx ((rtx) insn_); + } + } + } +} +#endif +#endif + + diff --git a/contrib/gcc/config/i386/dgux.h b/contrib/gcc/config/i386/dgux.h new file mode 100644 index 0000000..dae050f --- /dev/null +++ b/contrib/gcc/config/i386/dgux.h @@ -0,0 +1,265 @@ +/* Target definitions for GNU compiler for Intel 80x86 running DG/ux + Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Currently maintained by gcc@dg-rtp.dg.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. */ + +/* for now, we are just like the sysv4 version with a + few hacks +*/ + +#include "i386/sysv4.h" + +#ifndef VERSION_INFO2 +#define VERSION_INFO2 "$Revision: 1.3 $" +#endif + +#ifndef VERSION_STRING +#define VERSION_STRING version_string +#endif + +/* Identify the compiler. */ +/* TARGET_VERSION used by toplev.c VERSION_STRING used by -midentify-revision */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (%s%s, %s)", \ + VERSION_INFO1, VERSION_INFO2, __DATE__) +#undef VERSION_INFO1 +#define VERSION_INFO1 "ix86 DG/ux, " + +/* Augment TARGET_SWITCHES with the MXDB options. */ +#define MASK_STANDARD 0x40000000 /* Retain standard information */ +#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 TARGET_STANDARD (target_flags & MASK_STANDARD) +#define TARGET_NOLEGEND (target_flags & MASK_NOLEGEND) +#define TARGET_EXTERNAL_LEGEND (target_flags & MASK_EXTERNAL_LEGEND) +#define TARGET_IDENTIFY_REVISION (target_flags & MASK_IDENTIFY_REVISION) +#define TARGET_WARN_PASS_STRUCT (target_flags & MASK_WARN_PASS_STRUCT) + +#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 }, + +#undef DWARF_DEBUGGING_INFO +#define DWARF_DEBUGGING_INFO + +/* + allow -gstabs so that those who have gnu-as installed + can debug c++ programs. +*/ +#undef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG + +/* Override svr[34].h. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_start (FILE, f_options, sizeof f_options / sizeof f_options[0], \ + W_options, sizeof W_options / sizeof W_options[0]) + +/* ix86 abi specified type for wchar_t */ + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + + +/* Some machines may desire to change what optimizations are performed for + various optimization levels. This macro, if defined, is executed once + just after the optimization level is determined and before the remainder + of the command options have been parsed. Values set in this macro are + used as the default values for the other command line options. + + LEVEL is the optimization level specified; 2 if -O2 is specified, + 1 if -O is specified, and 0 if neither is specified. */ + +/* This macro used to store 0 in flag_signed_bitfields. + Not only is that misuse of this macro; the whole idea is wrong. + + The GNU C dialect makes bitfields signed by default, + regardless of machine type. Making any machine inconsistent in this + regard is bad for portability. + + I chose to make bitfields signed by default because this is consistent + with the way ordinary variables are handled: `int' equals `signed int'. + If there is a good reason to prefer making bitfields unsigned by default, + it cannot have anything to do with the choice of machine. + If the reason is good enough, we should change the convention for all machines. + + -- rms, 20 July 1991. */ + +/* + this really should go into dgux-local.h +*/ + +#undef OPTIMIZATION_OPTIONS +#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ + do { \ + extern int flag_signed_bitfields; \ + flag_signed_bitfields = 0; \ + abort_helper (); \ + optimization_options (LEVEL,SIZE); \ + } while (0) + + +/* The normal location of the `ld' and `as' programs */ + +#undef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/bin/" + +/* The normal location of the various *crt*.o files is the */ + +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/usr/lib/" + +/* Macros to be automatically defined. + __CLASSIFY_TYPE__ is used in the and header + files with DG/UX revision 5.40 and later. This allows GNU CC to + operate without installing the header files. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -D__ix86 -Dunix -DDGUX -D__CLASSIFY_TYPE__=2\ + -Asystem(unix) -Asystem(svr4) -Acpu(i386) -Amachine(i386)" + + /* + If not -ansi, -traditional, or restricting include files to one + specific source target, specify full DG/UX features. + */ +#undef CPP_SPEC +#define CPP_SPEC "%{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}}" + +/* Assembler support (legends for mxdb). */ +#undef ASM_SPEC +#define ASM_SPEC "\ +%{mno-legend:%{mstandard:-Wc,off}}\ +%{g:%{!mno-legend:-Wc,-fix-bb,-s\"%i\"\ +%{traditional:,-lc}%{!traditional:,-lansi-c}\ +%{mstandard:,-keep-std}\ +%{mexternal-legend:,-external}}}" + +/* Override svr4.h. */ + +/* hassey 3/12/94 keep svr4 ASM_FINAL_SPEC allows -pipe to work */ + +/* Linker and library spec's. + -static, -shared, -symbolic, -h* and -z* access AT&T V.4 link options. + -svr4 instructs gcc to place /usr/lib/values-X[cat].o on link the line. + The absence of -msvr4 indicates linking done in a COFF environment and + adds the link script to the link line. In all environments, the first + and last objects are crtbegin.o and crtend.o. + When the -G link option is used (-shared and -symbolic) a final link is + not being done. */ + +#undef LIB_SPEC +#define LIB_SPEC \ +"%{!shared:%{!symbolic:-lc}}" + +#undef LINK_SPEC +#define LINK_SPEC "%{z*} %{h*} %{v:-V} \ + %{static:-dn -Bstatic} \ + %{shared:-G -dy} \ + %{symbolic:-Bsymbolic -G -dy} \ + %{pg:-L/usr/lib/libp}%{p:-L/usr/lib/libp}" + +#ifdef CROSS_COMPILE + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt1.o%s} \ + %{!pg:%{p:mcrt1.o%s} \ + %{!p:crt1.o%s}}}} \ + %{pg:gcrti.o%s}%{!pg:crti.o%s} \ + crtbegin.o%s \ + %{ansi:values-Xc.o%s} \ + %{!ansi:%{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}" + +#else + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt1.o%s} \ + %{!pg:%{p:/lib/mcrt1.o%s} \ + %{!p:/lib/crt1.o%s}}} \ + %{pg:gcrti.o%s}%{!pg:/lib/crti.o%s}} \ + crtbegin.o%s \ + %{ansi:/lib/values-Xc.o%s} \ + %{!ansi:%{traditional:/lib/values-Xt.o%s} \ + %{!traditional:/lib/values-Xa.o%s}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:/lib/crtn.o}" + +#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 +#define MAX_OFILE_ALIGNMENT 0x1000 + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ +} + +/* This supplements FUNCTION_ARG's definition in i386.h to check + TARGET_WARN_PASS_STRUCT */ + +#undef FUNCTION_ARG +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +((((MODE) == BLKmode && TARGET_WARN_PASS_STRUCT) ? \ + warning ("argument is a structure"),0 : 0), \ + (function_arg (&CUM, MODE, TYPE, NAMED))) + +/* Add .align 1 to avoid .backalign bug in assembler */ +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP ".section\t.rodata\n\t.align 1" diff --git a/contrib/gcc/config/i386/freebsd-elf.h b/contrib/gcc/config/i386/freebsd-elf.h index 393ede7..0a556fe 100644 --- a/contrib/gcc/config/i386/freebsd-elf.h +++ b/contrib/gcc/config/i386/freebsd-elf.h @@ -1,8 +1,8 @@ /* Definitions for Intel 386 running FreeBSD with ELF format - Copyright (C) 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1996 Free Software Foundation, Inc. Contributed by Eric Youngdale. Modified for stabs-in-ELF by H.J. Lu. - Adapted from Linux version by John Polstra. + Adapted from GNU/Linux version by John Polstra. This file is part of GNU CC. @@ -21,31 +21,29 @@ 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. */ -/* A lie, I guess, but the general idea behind FreeBSD/ELF is that we are - supposed to be outputting something that will assemble under SVr4. - This gets us pretty close. */ -#include /* Base i386 target machine definitions */ -#include /* Use the i386 AT&T assembler syntax */ -#include /* some common stuff */ - #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); /* The svr4 ABI for the i386 says that records and unions are returned in memory. */ +/* On FreeBSD, we do not. */ #undef DEFAULT_PCC_STRUCT_RETURN -#define DEFAULT_PCC_STRUCT_RETURN 1 +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL /* 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. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) /* Copy this from the svr4 specifications... */ /* Define the register numbers to be used in Dwarf debugging information. @@ -147,14 +145,10 @@ Boston, MA 02111-1307, USA. */ #define WCHAR_TYPE_SIZE BITS_PER_WORD #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -D__ELF__ -D__FreeBSD__=2 -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" #undef CPP_SPEC -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#endif +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #undef LIB_SPEC #if 1 @@ -196,4 +190,16 @@ Boston, MA 02111-1307, USA. */ %{static:-static}}}" /* Get perform_* macros to build libgcc.a. */ -#include "i386/perform.h" + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< +/* Definitions for Intel 386 running FreeBSD with ELF format + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + Adapted from GNU/Linux version by John Polstra. This file is part of GNU CC. @@ -20,231 +21,185 @@ 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 goes away when the math-emulator is fixed */ -#define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */ +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); -/* This is tested by i386gas.h. */ -#define YES_UNDERSCORES - -/* Don't assume anything about the header files. */ -#define NO_IMPLICIT_EXTERN_C - -#include "i386/gstabs.h" - -/* Get perform_* macros to build libgcc.a. */ -#include "i386/perform.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__ -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" - -/* Like the default, except no -lg. */ -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" - -#define WCHAR_UNSIGNED 1 - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -#define HAVE_ATEXIT - -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +/* On FreeBSD, we do not. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -/* The following macros are stolen from i386v4.h */ -/* These have to be defined to get PIC code correct */ +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL /* 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. */ - #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 (flag_pic) + +/* 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 + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#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)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ -#define JUMP_TABLES_IN_TEXT_SECTION - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Profiling routines, partially copied from i386/osfrose.h. */ - -/* Redefine this to use %eax instead of %edx. */ #undef FUNCTION_PROFILER #define FUNCTION_PROFILER(FILE, LABELNO) \ { \ if (flag_pic) \ { \ - fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%eax\n", \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ } \ else \ { \ - fprintf (FILE, "\tmovl $%sP%d,%%eax\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall mcount\n"); \ } \ } -/* - * Some imports from svr4.h in support of shared libraries. - * Currently, we need the DECLARE_OBJECT_SIZE stuff. - */ - -/* 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" - -/* 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. */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" -/* 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) \ - { \ - 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) - -#define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}" -#define LINK_SPEC \ - "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" - -/* This is defined when gcc is compiled in the BSD-directory-tree, and must - * make up for the gap to all the stuff done in the GNU-makefiles. +#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 \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif -#ifdef FREEBSD_NATIVE +/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_i386 %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-static}}}" -#define INCLUDE_DEFAULTS { \ - { "/usr/include", 0 }, \ - { "/usr/include/g++", 1 }, \ - { 0, 0} \ - } +/* Get perform_* macros to build libgcc.a. */ -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/libexec/" +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< +/* Definitions for Intel 386 running FreeBSD with ELF format + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + Adapted from GNU/Linux version by John Polstra. This file is part of GNU CC. @@ -20,231 +21,185 @@ 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 goes away when the math-emulator is fixed */ -#define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */ +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); -/* This is tested by i386gas.h. */ -#define YES_UNDERSCORES - -/* Don't assume anything about the header files. */ -#define NO_IMPLICIT_EXTERN_C - -#include "i386/gstabs.h" - -/* Get perform_* macros to build libgcc.a. */ -#include "i386/perform.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__ -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" - -/* Like the default, except no -lg. */ -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" - -#define WCHAR_UNSIGNED 1 - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -#define HAVE_ATEXIT - -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +/* On FreeBSD, we do not. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -/* The following macros are stolen from i386v4.h */ -/* These have to be defined to get PIC code correct */ +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL /* 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. */ - #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 (flag_pic) + +/* 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 + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#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)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ -#define JUMP_TABLES_IN_TEXT_SECTION - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Profiling routines, partially copied from i386/osfrose.h. */ - -/* Redefine this to use %eax instead of %edx. */ #undef FUNCTION_PROFILER #define FUNCTION_PROFILER(FILE, LABELNO) \ { \ if (flag_pic) \ { \ - fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%eax\n", \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ } \ else \ { \ - fprintf (FILE, "\tmovl $%sP%d,%%eax\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall mcount\n"); \ } \ } -/* - * Some imports from svr4.h in support of shared libraries. - * Currently, we need the DECLARE_OBJECT_SIZE stuff. - */ - -/* 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" - -/* 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. */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" -/* 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) \ - { \ - 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) - -#define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}" -#define LINK_SPEC \ - "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" - -/* This is defined when gcc is compiled in the BSD-directory-tree, and must - * make up for the gap to all the stuff done in the GNU-makefiles. +#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 \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif -#ifdef FREEBSD_NATIVE +/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_i386 %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-static}}}" -#define INCLUDE_DEFAULTS { \ - { "/usr/include", 0 }, \ - { "/usr/include/g++", 1 }, \ - { 0, 0} \ - } +/* Get perform_* macros to build libgcc.a. */ -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/libexec/" +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1<, + * 14/8/96 based on the original gmon.c in GCC and the hacked version + * solaris 2 sparc version (config/sparc/gmon-sol.c) by Mark Eichin. To do + * process profiling on solaris 2.X X86 + * + * It must be used in conjunction with sol2-gc1.asm, which is used to start + * and stop process monitoring. + * + * Differences. + * + * On Solaris 2 _mcount is called by library functions not mcount, so support + * has been added for both. + * + * Also the prototype for profil() is different + * + * Solaris 2 does not seem to have char *minbrk whcih allows the setting of + * the minimum SBRK region so this code has been removed and lets pray malloc + * does not mess it up. + * + * Notes + * + * This code could easily be integrated with the original gmon.c and perhaps + * should be. + */ + +#ifndef lint +static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91"; +#endif /* not lint */ + +#if 0 +#include + +#endif +#ifdef DEBUG +#include +#endif + +#if 0 +#include "i386/gmon.h" +#else + +struct phdr { + char *lpc; + char *hpc; + int ncnt; +}; + + +#define HISTFRACTION 2 +#define HISTCOUNTER unsigned short +#define HASHFRACTION 1 +#define ARCDENSITY 2 +#define MINARCS 50 +#define BASEADDRESS 0x8000000 /* On Solaris 2 X86 all executables start here + and not at 0 */ + +struct tostruct { + char *selfpc; + long count; + unsigned short link; +}; +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) +#endif + +/* char *minbrk; */ + +#ifdef __alpha +extern char *sbrk (); +#endif + + /* + * froms is actually a bunch of unsigned shorts indexing tos + */ +static int profiling = 3; +static unsigned short *froms; +static struct tostruct *tos = 0; +static long tolimit = 0; +static char *s_lowpc = 0; +static char *s_highpc = 0; +static unsigned long s_textsize = 0; + +static int ssiz; +static char *sbuf; +static int s_scale; + /* see profil(2) where this is describe (incorrectly) */ +#define SCALE_1_TO_1 0x10000L + +#define MSG "No space for profiling buffer(s)\n" + +extern int errno; + +monstartup(lowpc, highpc) + char *lowpc; + char *highpc; +{ + int monsize; + char *buffer; + register int o; + + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + lowpc = (char *) + ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_lowpc = lowpc; + highpc = (char *) + ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_highpc = highpc; + s_textsize = highpc - lowpc; + monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr); + buffer = (char *) sbrk( monsize ); + if ( buffer == (char *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + return; + } + froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION ); + if ( froms == (unsigned short *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + return; + } + tolimit = s_textsize * ARCDENSITY / 100; + if ( tolimit < MINARCS ) { + tolimit = MINARCS; + } else if ( tolimit > 65534 ) { + tolimit = 65534; + } + tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) ); + if ( tos == (struct tostruct *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + tos = 0; + return; + } +/* minbrk = (char *) sbrk(0);*/ + tos[0].link = 0; + sbuf = buffer; + ssiz = monsize; + ( (struct phdr *) buffer ) -> lpc = lowpc; + ( (struct phdr *) buffer ) -> hpc = highpc; + ( (struct phdr *) buffer ) -> ncnt = ssiz; + monsize -= sizeof(struct phdr); + if ( monsize <= 0 ) + return; + o = highpc - lowpc; + if( monsize < o ) +#ifndef hp300 + s_scale = ( (float) monsize / o ) * SCALE_1_TO_1; +#else /* avoid floating point */ + { + int quot = o / monsize; + + if (quot >= 0x10000) + s_scale = 1; + else if (quot >= 0x100) + s_scale = 0x10000 / quot; + else if (o >= 0x800000) + s_scale = 0x1000000 / (o / (monsize >> 8)); + else + s_scale = 0x1000000 / ((o << 8) / monsize); + } +#endif + else + s_scale = SCALE_1_TO_1; + moncontrol(1); +} + +_mcleanup() +{ + int fd; + int fromindex; + int endfrom; + char *frompc; + int toindex; + struct rawarc rawarc; + + moncontrol(0); + fd = creat( "gmon.out" , 0666 ); + if ( fd < 0 ) { + perror( "mcount: gmon.out" ); + return; + } +# ifdef DEBUG + fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); +# endif DEBUG + + write( fd , sbuf , ssiz ); + endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); + for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { + if ( froms[fromindex] == 0 ) { + continue; + } + frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); + for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { +# ifdef DEBUG + fprintf( stderr , + "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , + frompc , tos[toindex].selfpc , tos[toindex].count ); +# endif DEBUG + rawarc.raw_frompc = (unsigned long) frompc; + rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; + rawarc.raw_count = tos[toindex].count; + write( fd , &rawarc , sizeof rawarc ); + } + } + close( fd ); +} + +/* Solaris 2 libraries use _mcount. */ +asm(".globl _mcount; _mcount: jmp internal_mcount"); +/* This is for compatibility with old versions of gcc which used mcount. */ +asm(".globl mcount; mcount: jmp internal_mcount"); + +internal_mcount() +{ + register char *selfpc; + register unsigned short *frompcindex; + register struct tostruct *top; + register struct tostruct *prevtop; + register long toindex; + static char already_setup; + + /* + * find the return address for mcount, + * and the return address for mcount's caller. + */ + + /* selfpc = pc pushed by mcount call. + This identifies the function that was just entered. */ + selfpc = (void *) __builtin_return_address (0); + /* frompcindex = pc in preceding frame. + This identifies the caller of the function just entered. */ + frompcindex = (void *) __builtin_return_address (1); + + if(!already_setup) { + extern etext(); + already_setup = 1; +/* monstartup(0, etext); */ + monstartup(0x08040000, etext); +#ifdef USE_ONEXIT + on_exit(_mcleanup, 0); +#else + atexit(_mcleanup); +#endif + } + /* + * check that we are profiling + * and that we aren't recursively invoked. + */ + if (profiling) { + goto out; + } + profiling++; + /* + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); + if ((unsigned long)frompcindex > s_textsize) { + goto done; + } + frompcindex = + &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; + toindex = *frompcindex; + if (toindex == 0) { + /* + * first time traversing this arc + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + *frompcindex = toindex; + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &tos[toindex]; + if (top->selfpc == selfpc) { + /* + * arc at front of chain; usual case. + */ + top->count++; + goto done; + } + /* + * have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (; /* goto done */; ) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &tos[top->link]; + if (top->selfpc == selfpc) { + /* + * there it is. + * increment its count + * move it to the head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + + } +done: + profiling--; + /* and fall through */ +out: + return; /* normal return restores saved registers */ + +overflow: + profiling++; /* halt further profiling */ +# define TOLIMIT "mcount: tos overflow\n" + write(2, TOLIMIT, sizeof(TOLIMIT)); + goto out; +} + +/* + * Control profiling + * profiling is what mcount checks to see if + * all the data structures are ready. + */ +moncontrol(mode) + int mode; +{ + if (mode) + { + /* start */ + profil((unsigned short *)(sbuf + sizeof(struct phdr)), + ssiz - sizeof(struct phdr), + (int)s_lowpc, s_scale); + + profiling = 0; + } else { + /* stop */ + profil((unsigned short *)0, 0, 0, 0); + profiling = 3; + } +} diff --git a/contrib/gcc/config/i386/gnu.h b/contrib/gcc/config/i386/gnu.h index 1ad5df9..971a5f8 100644 --- a/contrib/gcc/config/i386/gnu.h +++ b/contrib/gcc/config/i386/gnu.h @@ -4,16 +4,19 @@ #include #undef CPP_PREDEFINES -#define CPP_PREDEFINES GNU_CPP_PREDEFINES("i386") +#define CPP_PREDEFINES "-Di386 -Acpu(i386) -Amachine(i386) \ +-Dunix -Asystem(unix) -DMACH -Asystem(mach) -D__GNU__ -Asystem(gnu)" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 GNU)"); #undef LINK_SPEC #define LINK_SPEC "-m elf_i386 %{shared:-shared} \ %{!shared: \ - %{!ibcs: \ - %{!static: \ - %{rdynamic:-export-dynamic} \ - %{!dynamic-linker:-dynamic-linker /lib/ld.so} \ - %{!rpath:-rpath /lib/}} %{static:-static}}}" + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld.so}} \ + %{static:-static}}" /* Get machine-independent configuration parameters for the GNU system. */ diff --git a/contrib/gcc/config/i386/go32.h b/contrib/gcc/config/i386/go32.h index 5618a0d..dd03cc8 100644 --- a/contrib/gcc/config/i386/go32.h +++ b/contrib/gcc/config/i386/go32.h @@ -1,5 +1,7 @@ /* Configuration for an i386 running MS-DOS with djgpp/go32. */ +#include "dbxcoff.h" + /* Don't assume anything about the header files. */ #define NO_IMPLICIT_EXTERN_C @@ -53,7 +55,13 @@ dtor_section () \ fprintf (FILE, "\n"); \ } while (0) -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ +/* 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); \ @@ -61,4 +69,28 @@ dtor_section () \ fprintf (FILE, "\n"); \ } while (0) +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +/* Use the main_input_filename instead of dump_base_name */ + +#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/i386.c b/contrib/gcc/config/i386/i386.c index 48c58a0..b2512a0 100644 --- a/contrib/gcc/config/i386/i386.c +++ b/contrib/gcc/config/i386/i386.c @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Intel X86. - Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 94-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -16,12 +16,11 @@ 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. */ +Boston, MA 02111-1307, USA. */ -#include #include -#include #include "config.h" +#include "system.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" @@ -33,7 +32,11 @@ Boston, MA 02111-1307, USA. */ #include "insn-attr.h" #include "tree.h" #include "flags.h" +#include "except.h" #include "function.h" +#include "recog.h" +#include "expr.h" +#include "toplev.h" #ifdef EXTRA_CONSTRAINT /* If EXTRA_CONSTRAINT is defined, then the 'S' @@ -44,11 +47,69 @@ Boston, MA 02111-1307, USA. */ even if the conditional was untrue. */ #endif -#define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx)) +#ifndef CHECK_STACK_LIMIT +#define CHECK_STACK_LIMIT -1 +#endif + +/* Type of an operand for ix86_{binary,unary}_operator_ok */ +enum reg_mem +{ + reg_p, + mem_p, + imm_p +}; + +/* Processor costs (relative to an add) */ +struct processor_costs i386_cost = { /* 386 specific costs */ + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 3, /* variable shift costs */ + 2, /* constant shift costs */ + 6, /* cost of starting a multiply */ + 1, /* cost of multiply per each bit set */ + 23 /* cost of a divide/mod */ +}; + +struct processor_costs i486_cost = { /* 486 specific costs */ + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 3, /* variable shift costs */ + 2, /* constant shift costs */ + 12, /* cost of starting a multiply */ + 1, /* cost of multiply per each bit set */ + 40 /* cost of a divide/mod */ +}; + +struct processor_costs pentium_cost = { + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 4, /* variable shift costs */ + 1, /* constant shift costs */ + 11, /* cost of starting a multiply */ + 0, /* cost of multiply per each bit set */ + 25 /* cost of a divide/mod */ +}; + +struct processor_costs pentiumpro_cost = { + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 3, /* variable shift costs */ + 1, /* constant shift costs */ + 4, /* cost of starting a multiply */ + 0, /* cost of multiply per each bit set */ + 17 /* cost of a divide/mod */ +}; + +struct processor_costs *ix86_cost = &pentium_cost; + +#define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx)) extern FILE *asm_out_file; extern char *strcat (); +static void ix86_epilogue PROTO((int)); +static void ix86_prologue PROTO((int)); + char *singlemove_string (); char *output_move_const_single (); char *output_fp_cc0_set (); @@ -68,7 +129,7 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] = SIREG, DIREG, INDEX_REGS, GENERAL_REGS, /* FP registers */ FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS, - FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, + FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, /* arg pointer */ INDEX_REGS }; @@ -80,24 +141,48 @@ struct rtx_def *i386_compare_op0 = NULL_RTX; struct rtx_def *i386_compare_op1 = NULL_RTX; struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); +/* which cpu are we scheduling for */ +enum processor_type ix86_cpu; + +/* which instruction set architecture to use. */ +int ix86_arch; + +/* Strings to hold which cpu and instruction set architecture to use. */ +char *ix86_cpu_string; /* for -mcpu= */ +char *ix86_arch_string; /* for -march= */ + /* Register allocation order */ char *i386_reg_alloc_order; static char regs_allocated[FIRST_PSEUDO_REGISTER]; /* # of registers to use to pass arguments. */ -char *i386_regparm_string; /* # registers to use to pass args */ -int i386_regparm; /* i386_regparm_string as a number */ +char *i386_regparm_string; -/* Alignment to use for loops and jumps */ -char *i386_align_loops_string; /* power of two alignment for loops */ -char *i386_align_jumps_string; /* power of two alignment for non-loop jumps */ -char *i386_align_funcs_string; /* power of two alignment for functions */ +/* i386_regparm_string as a number */ +int i386_regparm; -int i386_align_loops; /* power of two alignment for loops */ -int i386_align_jumps; /* power of two alignment for non-loop jumps */ -int i386_align_funcs; /* power of two alignment for functions */ +/* Alignment to use for loops and jumps: */ + +/* Power of two alignment for loops. */ +char *i386_align_loops_string; + +/* Power of two alignment for non-loop jumps. */ +char *i386_align_jumps_string; + +/* Values 1-5: see jump.c */ +int i386_branch_cost; +char *i386_branch_cost_string; + +/* Power of two alignment for functions. */ +int i386_align_funcs; +char *i386_align_funcs_string; + +/* Power of two alignment for loops. */ +int i386_align_loops; + +/* Power of two alignment for non-loop jumps. */ +int i386_align_jumps; - /* Sometimes certain combinations of command options do not make sense on a particular target machine. You can define a macro `OVERRIDE_OPTIONS' to take account of this. This macro, if @@ -110,19 +195,39 @@ int i386_align_funcs; /* power of two alignment for functions */ void override_options () { - int ch, i, regno; - char *p; + int ch, i, j; int def_align; + static struct ptt + { + char *name; /* Canonical processor name. */ + enum processor_type processor; /* Processor type enum value. */ + 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}}; + + int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt); + #ifdef SUBTARGET_OVERRIDE_OPTIONS SUBTARGET_OVERRIDE_OPTIONS; #endif - /* Validate registers in register allocation order */ + /* Validate registers in register allocation order. */ if (i386_reg_alloc_order) { for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++) { + int regno = 0; + switch (ch) { case 'a': regno = 0; break; @@ -137,23 +242,75 @@ override_options () } if (regs_allocated[regno]) - fatal ("Register '%c' was already specified in the allocation order", ch); + fatal ("Register '%c' already specified in allocation order", ch); regs_allocated[regno] = 1; } } - /* Validate -mregparm= value */ + if (ix86_arch_string == 0) + { + ix86_arch_string = PROCESSOR_PENTIUM_STRING; + if (ix86_cpu_string == 0) + ix86_cpu_string = PROCESSOR_DEFAULT_STRING; + } + + for (i = 0; i < ptt_size; i++) + if (! strcmp (ix86_arch_string, processor_target_table[i].name)) + { + ix86_arch = processor_target_table[i].processor; + if (ix86_cpu_string == 0) + ix86_cpu_string = processor_target_table[i].name; + break; + } + + if (i == ptt_size) + { + error ("bad value (%s) for -march= switch", ix86_arch_string); + ix86_arch_string = PROCESSOR_PENTIUM_STRING; + ix86_arch = PROCESSOR_DEFAULT; + } + + if (ix86_cpu_string == 0) + ix86_cpu_string = PROCESSOR_DEFAULT_STRING; + + for (j = 0; j < ptt_size; j++) + if (! strcmp (ix86_cpu_string, processor_target_table[j].name)) + { + ix86_cpu = processor_target_table[j].processor; + ix86_cost = processor_target_table[j].cost; + if (i > j && (int) ix86_arch >= (int) PROCESSOR_PENTIUMPRO) + error ("-mcpu=%s does not support -march=%s", + ix86_cpu_string, ix86_arch_string); + + target_flags |= processor_target_table[j].target_enable; + target_flags &= ~processor_target_table[j].target_disable; + break; + } + + if (j == ptt_size) + { + error ("bad value (%s) for -mcpu= switch", ix86_cpu_string); + ix86_cpu_string = PROCESSOR_DEFAULT_STRING; + ix86_cpu = PROCESSOR_DEFAULT; + } + + /* Validate -mregparm= value. */ if (i386_regparm_string) { i386_regparm = atoi (i386_regparm_string); if (i386_regparm < 0 || i386_regparm > REGPARM_MAX) - fatal ("-mregparm=%d is not between 0 and %d", i386_regparm, REGPARM_MAX); + fatal ("-mregparm=%d is not between 0 and %d", + i386_regparm, REGPARM_MAX); } - def_align = (TARGET_386) ? 2 : 4; + /* The 486 suffers more from non-aligned cache line fills, and the + larger code size results in a larger cache foot-print and more misses. + The 486 has a 16 byte cache line, pentium and pentiumpro have a 32 byte + cache line. */ + def_align = (TARGET_486) ? 4 : 2; - /* Validate -malign-loops= value, or provide default */ + /* Validate -malign-loops= value, or provide default. */ if (i386_align_loops_string) { i386_align_loops = atoi (i386_align_loops_string); @@ -162,9 +319,13 @@ override_options () i386_align_loops, MAX_CODE_ALIGN); } else +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN + i386_align_loops = 4; +#else i386_align_loops = 2; +#endif - /* Validate -malign-jumps= value, or provide default */ + /* Validate -malign-jumps= value, or provide default. */ if (i386_align_jumps_string) { i386_align_jumps = atoi (i386_align_jumps_string); @@ -173,9 +334,13 @@ override_options () 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 */ + /* Validate -malign-functions= value, or provide default. */ if (i386_align_funcs_string) { i386_align_funcs = atoi (i386_align_funcs_string); @@ -185,6 +350,21 @@ override_options () } else i386_align_funcs = def_align; + + /* Validate -mbranch-cost= value, or provide default. */ + 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); + } + else + i386_branch_cost = 1; + + /* Keep nonleaf frame pointers. */ + if (TARGET_OMIT_LEAF_FRAME_POINTER) + flag_omit_frame_pointer = 1; } /* A C statement (sans semicolon) to choose the order in which to @@ -203,13 +383,16 @@ override_options () void order_regs_for_local_alloc () { - int i, ch, order, regno; + int i, ch, order; + + /* User specified the register allocation order. */ - /* User specified the register allocation order */ if (i386_reg_alloc_order) { for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++) { + int regno = 0; + switch (ch) { case 'a': regno = 0; break; @@ -226,59 +409,116 @@ order_regs_for_local_alloc () for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { - if (!regs_allocated[i]) + if (! regs_allocated[i]) reg_alloc_order[order++] = i; } } - /* If users did not specify a register allocation order, favor eax - normally except if DImode variables are used, in which case - favor edx before eax, which seems to cause less spill register - not found messages. */ + /* If user did not specify a register allocation order, use natural order. */ else { - rtx insn; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) reg_alloc_order[i] = i; + } +} + +void +optimization_options (level, size) + int level; + int size ATTRIBUTE_UNUSED; +{ + /* For -O2 and beyond, turn off -fschedule-insns by default. It tends to + make the problem with not enough registers even worse. */ +#ifdef INSN_SCHEDULING + if (level > 1) + flag_schedule_insns = 0; +#endif +} + +/* Sign-extend a 16-bit constant */ - if (optimize) - { - int use_dca = FALSE; +struct rtx_def * +i386_sext16_if_const (op) + struct rtx_def *op; +{ + if (GET_CODE (op) == CONST_INT) + { + HOST_WIDE_INT val = INTVAL (op); + HOST_WIDE_INT sext_val; + if (val & 0x8000) + sext_val = val | ~0xffff; + else + sext_val = val & 0xffff; + if (sext_val != val) + op = GEN_INT (sext_val); + } + return op; +} + +/* Return nonzero if the rtx is aligned */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == INSN) - { - rtx set = NULL_RTX; - rtx pattern = PATTERN (insn); - - if (GET_CODE (pattern) == SET) - set = pattern; - - else if ((GET_CODE (pattern) == PARALLEL - || GET_CODE (pattern) == SEQUENCE) - && GET_CODE (XVECEXP (pattern, 0, 0)) == SET) - set = XVECEXP (pattern, 0, 0); - - if (set && GET_MODE (SET_SRC (set)) == DImode) - { - use_dca = TRUE; - break; - } - } - } +static int +i386_aligned_reg_p (regno) + int regno; +{ + return (regno == STACK_POINTER_REGNUM + || (! flag_omit_frame_pointer && regno == FRAME_POINTER_REGNUM)); +} - if (use_dca) - { - reg_alloc_order[0] = 1; /* edx */ - reg_alloc_order[1] = 2; /* ecx */ - reg_alloc_order[2] = 0; /* eax */ - } - } +int +i386_aligned_p (op) + rtx op; +{ + /* Registers and immediate operands are always "aligned". */ + if (GET_CODE (op) != MEM) + return 1; + + /* Don't even try to do any aligned optimizations with volatiles. */ + if (MEM_VOLATILE_P (op)) + return 0; + + /* Get address of memory operand. */ + op = XEXP (op, 0); + + switch (GET_CODE (op)) + { + case CONST_INT: + if (INTVAL (op) & 3) + break; + return 1; + + /* Match "reg + offset" */ + case PLUS: + if (GET_CODE (XEXP (op, 1)) != CONST_INT) + break; + if (INTVAL (XEXP (op, 1)) & 3) + break; + + op = XEXP (op, 0); + if (GET_CODE (op) != REG) + break; + + /* ... fall through ... */ + + case REG: + return i386_aligned_reg_p (REGNO (op)); + + default: + break; } + + return 0; } + +/* Return nonzero if INSN looks like it won't compute useful cc bits + as a side effect. This information is only a hint. */ +int +i386_cc_probably_useless_p (insn) + rtx insn; +{ + return ! next_cc0_user (insn); +} /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific attribute for DECL. The attributes in ATTRIBUTES have previously been @@ -286,10 +526,10 @@ order_regs_for_local_alloc () int i386_valid_decl_attribute_p (decl, attributes, identifier, args) - tree decl; - tree attributes; - tree identifier; - tree args; + tree decl ATTRIBUTE_UNUSED; + tree attributes ATTRIBUTE_UNUSED; + tree identifier ATTRIBUTE_UNUSED; + tree args ATTRIBUTE_UNUSED; { return 0; } @@ -301,11 +541,12 @@ i386_valid_decl_attribute_p (decl, attributes, identifier, args) int i386_valid_type_attribute_p (type, attributes, identifier, args) tree type; - tree attributes; + tree attributes ATTRIBUTE_UNUSED; tree identifier; tree args; { if (TREE_CODE (type) != FUNCTION_TYPE + && TREE_CODE (type) != METHOD_TYPE && TREE_CODE (type) != FIELD_DECL && TREE_CODE (type) != TYPE_DECL) return 0; @@ -315,17 +556,17 @@ i386_valid_type_attribute_p (type, attributes, identifier, args) if (is_attribute_p ("stdcall", identifier)) return (args == NULL_TREE); - /* Cdecl attribute says the callee is a normal C declaration */ + /* Cdecl attribute says the callee is a normal C declaration. */ if (is_attribute_p ("cdecl", identifier)) return (args == NULL_TREE); /* Regparm attribute specifies how many integer arguments are to be - passed in registers */ + passed in registers. */ if (is_attribute_p ("regparm", identifier)) { tree cst; - if (!args || TREE_CODE (args) != TREE_LIST + if (! args || TREE_CODE (args) != TREE_LIST || TREE_CHAIN (args) != NULL_TREE || TREE_VALUE (args) == NULL_TREE) return 0; @@ -351,8 +592,8 @@ i386_valid_type_attribute_p (type, attributes, identifier, args) int i386_comp_type_attributes (type1, type2) - tree type1; - tree type2; + tree type1 ATTRIBUTE_UNUSED; + tree type2 ATTRIBUTE_UNUSED; { return 1; } @@ -381,30 +622,27 @@ i386_return_pops_args (fundecl, funtype, size) tree funtype; int size; { - int rtd = TARGET_RTD; + int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE); - if (TREE_CODE (funtype) == IDENTIFIER_NODE) - return 0; - - /* Cdecl functions override -mrtd, and never pop the stack */ - if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) - return 0; + /* Cdecl functions override -mrtd, and never pop the stack. */ + if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) { - /* Stdcall functions will pop the stack if not variable args */ - if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))) - rtd = 1; + /* Stdcall functions will pop the stack if not variable args. */ + if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))) + rtd = 1; - if (rtd) - { - if (TYPE_ARG_TYPES (funtype) == NULL_TREE - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node)) - return size; + if (rtd + && (TYPE_ARG_TYPES (funtype) == NULL_TREE + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) + == void_type_node))) + return size; + } - if (aggregate_value_p (TREE_TYPE (funtype))) - return GET_MODE_SIZE (Pmode); - } + /* Lose any fake structure return argument. */ + if (aggregate_value_p (TREE_TYPE (funtype))) + return GET_MODE_SIZE (Pmode); - return 0; + return 0; } @@ -416,7 +654,7 @@ i386_return_pops_args (fundecl, funtype, size) void init_cumulative_args (cum, fntype, libname) - CUMULATIVE_ARGS *cum; /* argument info to initialize */ + CUMULATIVE_ARGS *cum; /* Argument info to initialize */ tree fntype; /* tree ptr for function decl */ rtx libname; /* SYMBOL_REF of library name or 0 */ { @@ -427,12 +665,9 @@ init_cumulative_args (cum, fntype, libname) { fprintf (stderr, "\ninit_cumulative_args ("); if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - fprintf (stderr, "fntype code = %s, ret code = %s", - tree_code_name[ (int)TREE_CODE (fntype) ], - tree_code_name[ (int)TREE_CODE (ret_type) ]); - } + fprintf (stderr, "fntype code = %s, ret code = %s", + tree_code_name[(int) TREE_CODE (fntype)], + tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]); else fprintf (stderr, "no fntype"); @@ -447,6 +682,7 @@ init_cumulative_args (cum, fntype, libname) if (fntype) { tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype)); + if (attr) cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))); } @@ -459,11 +695,10 @@ init_cumulative_args (cum, fntype, libname) if (cum->nregs) { for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0; - param != (tree)0; - param = next_param) + param != 0; param = next_param) { next_param = TREE_CHAIN (param); - if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node) + if (next_param == 0 && TREE_VALUE (param) != void_type_node) cum->nregs = 0; } } @@ -485,12 +720,13 @@ function_arg_advance (cum, mode, type, named) tree type; /* type of the argument or 0 if lib support */ int named; /* whether or not the argument was named */ { - int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); + int bytes + = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (TARGET_DEBUG_ARG) fprintf (stderr, - "function_adv( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d )\n\n", + "function_adv (sz=%d, wds=%2d, nregs=%d, mode=%s, named=%d)\n\n", words, cum->words, cum->nregs, GET_MODE_NAME (mode), named); cum->words += words; @@ -527,12 +763,14 @@ function_arg (cum, mode, type, named) int named; /* != 0 for normal args, == 0 for ... args */ { rtx ret = NULL_RTX; - int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); + int bytes + = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; switch (mode) { - default: /* for now, pass fp/complex values on the stack */ + /* For now, pass fp/complex values on the stack. */ + default: break; case BLKmode: @@ -541,14 +779,14 @@ function_arg (cum, mode, type, named) case HImode: case QImode: if (words <= cum->nregs) - ret = gen_rtx (REG, mode, cum->regno); + ret = gen_rtx_REG (mode, cum->regno); break; } if (TARGET_DEBUG_ARG) { fprintf (stderr, - "function_arg( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d", + "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d", words, cum->words, cum->nregs, GET_MODE_NAME (mode), named); if (ret) @@ -568,14 +806,13 @@ function_arg (cum, mode, type, named) int function_arg_partial_nregs (cum, mode, type, named) - CUMULATIVE_ARGS *cum; /* current arg information */ - enum machine_mode mode; /* current arg mode */ - tree type; /* type of the argument or 0 if lib support */ - int named; /* != 0 for normal args, == 0 for ... args */ + CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; /* current arg information */ + enum machine_mode mode ATTRIBUTE_UNUSED; /* current arg mode */ + tree type ATTRIBUTE_UNUSED; /* type of the argument or 0 if lib support */ + int named ATTRIBUTE_UNUSED; /* != 0 for normal args, == 0 for ... args */ { 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 @@ -609,18 +846,19 @@ output_op_from_reg (src, template) if (size > UNITS_PER_WORD) { rtx high; + if (size > 2 * UNITS_PER_WORD) { - high = gen_rtx (REG, SImode, REGNO (src) + 2); + high = gen_rtx_REG (SImode, REGNO (src) + 2); output_asm_insn (AS1 (push%L0,%0), &high); } - high = gen_rtx (REG, SImode, REGNO (src) + 1); + + 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 (AS1 (push%L0,%0), &src); output_asm_insn (template, xops); - output_asm_insn (AS2 (add%L3,%2,%3), xops); } @@ -630,27 +868,45 @@ output_op_from_reg (src, template) otherwise a `fst' float store is done. */ void -output_to_reg (dest, dies) +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)); - xops[0] = AT_SP (Pmode); + 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; - output_asm_insn (AS2 (sub%L1,%2,%1), xops); + 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) @@ -666,19 +922,38 @@ output_to_reg (dest, dies) output_asm_insn (AS1 (fst%z3,%y0), xops); } } + else abort (); - output_asm_insn (AS1 (pop%L0,%0), &dest); + 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); - output_asm_insn (AS1 (pop%L0,%0), &dest); + 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); - output_asm_insn (AS1 (pop%L0,%0), &dest); + 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); + } } } } @@ -696,9 +971,7 @@ singlemove_string (operands) return "push%L1 %1"; } else if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - return output_move_const_single (operands); - } + return output_move_const_single (operands); else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) return AS2 (mov%L0,%1,%0); else if (CONSTANT_P (operands[1])) @@ -730,11 +1003,11 @@ find_addr_reg (addr) else abort (); } + if (GET_CODE (addr) == REG) return addr; abort (); } - /* Output an insn to add the constant N to the register X. */ @@ -750,7 +1023,7 @@ asm_add (n, x) output_asm_insn (AS1 (dec%L0,%0), xops); else if (n == 1) output_asm_insn (AS1 (inc%L0,%0), xops); - else if (n < 0) + else if (n < 0 || n == 128) { xops[1] = GEN_INT (-n); output_asm_insn (AS2 (sub%L0,%1,%0), xops); @@ -761,7 +1034,6 @@ asm_add (n, x) output_asm_insn (AS2 (add%L0,%1,%0), xops); } } - /* Output assembler code to perform a doubleword move insn with operands OPERANDS. */ @@ -828,11 +1100,11 @@ output_move_double (operands) operands[0] = XEXP (XEXP (operands[0], 0), 0); asm_add (-size, operands[0]); if (GET_MODE (operands[1]) == XFmode) - operands[0] = gen_rtx (MEM, XFmode, operands[0]); + operands[0] = gen_rtx_MEM (XFmode, operands[0]); else if (GET_MODE (operands[0]) == DFmode) - operands[0] = gen_rtx (MEM, DFmode, operands[0]); + operands[0] = gen_rtx_MEM (DFmode, operands[0]); else - operands[0] = gen_rtx (MEM, DImode, operands[0]); + operands[0] = gen_rtx_MEM (DImode, operands[0]); optype0 = OFFSOP; } @@ -842,11 +1114,11 @@ output_move_double (operands) operands[1] = XEXP (XEXP (operands[1], 0), 0); asm_add (-size, operands[1]); if (GET_MODE (operands[1]) == XFmode) - operands[1] = gen_rtx (MEM, XFmode, operands[1]); + operands[1] = gen_rtx_MEM (XFmode, operands[1]); else if (GET_MODE (operands[1]) == DFmode) - operands[1] = gen_rtx (MEM, DFmode, operands[1]); + operands[1] = gen_rtx_MEM (DFmode, operands[1]); else - operands[1] = gen_rtx (MEM, DImode, operands[1]); + operands[1] = gen_rtx_MEM (DImode, operands[1]); optype1 = OFFSOP; } @@ -872,8 +1144,8 @@ output_move_double (operands) { if (optype0 == REGOP) { - middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); + middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); + latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2); } else if (optype0 == OFFSOP) { @@ -885,11 +1157,11 @@ output_move_double (operands) middlehalf[0] = operands[0]; latehalf[0] = operands[0]; } - + if (optype1 == REGOP) { - middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); + middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); + latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2); } else if (optype1 == OFFSOP) { @@ -918,17 +1190,20 @@ output_move_double (operands) latehalf[1] = operands[1]; } } - else /* size is not 12: */ + + else { + /* Size is not 12. */ + if (optype0 == REGOP) - latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); else if (optype0 == OFFSOP) latehalf[0] = adj_offsettable_operand (operands[0], 4); else latehalf[0] = operands[0]; if (optype1 == REGOP) - latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); else if (optype1 == OFFSOP) latehalf[1] = adj_offsettable_operand (operands[1], 4); else if (optype1 == CNSTOP) @@ -960,34 +1235,34 @@ output_move_double (operands) { /* If both halves of dest are used in the src memory address, compute the address into latehalf of dest. */ -compadr: + compadr: xops[0] = latehalf[0]; xops[1] = XEXP (operands[1], 0); output_asm_insn (AS2 (lea%L0,%a1,%0), xops); - if( GET_MODE (operands[1]) == XFmode ) + if (GET_MODE (operands[1]) == XFmode) { -/* abort (); */ - operands[1] = gen_rtx (MEM, XFmode, latehalf[0]); + operands[1] = gen_rtx_MEM (XFmode, latehalf[0]); middlehalf[1] = adj_offsettable_operand (operands[1], size-8); latehalf[1] = adj_offsettable_operand (operands[1], size-4); } else { - operands[1] = gen_rtx (MEM, DImode, latehalf[0]); + operands[1] = gen_rtx_MEM (DImode, latehalf[0]); latehalf[1] = adj_offsettable_operand (operands[1], size-4); } } + else if (size == 12 && reg_mentioned_p (middlehalf[0], XEXP (operands[1], 0))) { /* Check for two regs used by both source and dest. */ if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) || reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) - goto compadr; + goto compadr; /* JRV says this can't happen: */ if (addreg0 || addreg1) - abort(); + abort (); /* Only the middle reg conflicts; simply put it last. */ output_asm_insn (singlemove_string (operands), operands); @@ -995,6 +1270,7 @@ compadr: output_asm_insn (singlemove_string (middlehalf), middlehalf); return ""; } + else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))) /* If the low half of dest is mentioned in the source memory address, the arrange to emit the move late half first. */ @@ -1009,12 +1285,13 @@ compadr: such overlap can't happen in memory unless the user explicitly sets it up, and that is an undefined circumstance. */ -/* +#if 0 if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP && REGNO (operands[0]) == REGNO (latehalf[1])) || dest_overlapped_low) -*/ +#endif + if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1])) @@ -1032,17 +1309,17 @@ compadr: /* Undo the adds we just did. */ if (addreg0) - asm_add (-4, 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); + if (addreg0) + asm_add (-4, addreg0); + if (addreg1) + asm_add (-4, addreg1); } /* Do low-numbered word. */ @@ -1081,7 +1358,6 @@ compadr: return ""; } - #define MAX_TMPS 2 /* max temporary registers used */ @@ -1095,12 +1371,12 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) int tmp_start; int n_operands; { - - struct { - char *load; - char *push; - rtx xops[2]; - } tmp_info[MAX_TMPS]; + struct + { + char *load; + char *push; + rtx xops[2]; + } tmp_info[MAX_TMPS]; rtx src = operands[1]; int max_tmps = 0; @@ -1110,7 +1386,7 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) int i, num_tmps; rtx xops[1]; - if (!offsettable_memref_p (src)) + if (! offsettable_memref_p (src)) fatal_insn ("Source is not offsettable", insn); if ((length & 3) != 0) @@ -1146,7 +1422,8 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) { tmp_info[num_tmps].load = AS2(mov%L0,%0,%1); tmp_info[num_tmps].push = AS1(push%L0,%1); - tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset); + tmp_info[num_tmps].xops[0] + = adj_offsettable_operand (src, offset + stack_offset); offset -= 4; } @@ -1162,9 +1439,7 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) return ""; } - - /* Output the appropriate code to move data between two memory locations */ char * @@ -1175,11 +1450,12 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) int tmp_start; int n_operands; { - struct { - char *load; - char *store; - rtx xops[3]; - } tmp_info[MAX_TMPS]; + struct + { + char *load; + char *store; + rtx xops[3]; + } tmp_info[MAX_TMPS]; rtx dest = operands[0]; rtx src = operands[1]; @@ -1194,10 +1470,10 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx) return output_move_pushmem (operands, insn, length, tmp_start, n_operands); - if (!offsettable_memref_p (src)) + if (! offsettable_memref_p (src)) fatal_insn ("Source is not offsettable", insn); - if (!offsettable_memref_p (dest)) + if (! offsettable_memref_p (dest)) fatal_insn ("Destination is not offsettable", insn); /* Figure out which temporary registers we have available */ @@ -1205,7 +1481,7 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) { if (GET_CODE (operands[i]) == REG) { - if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i])) + if ((length & 1) != 0 && qi_tmp == 0 && QI_REG_P (operands[i])) qi_tmp = operands[i]; if (reg_overlap_mentioned_p (operands[i], dest)) @@ -1214,19 +1490,21 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) if (reg_overlap_mentioned_p (operands[i], src)) fatal_insn ("Temporary register overlaps the source", insn); - tmp_info[ max_tmps++ ].xops[2] = operands[i]; + 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); + fatal_insn ("No scratch registers were found to do memory->memory moves", + insn); if ((length & 1) != 0) { - if (!qi_tmp) - fatal_insn ("No byte register found when moving odd # of bytes.", insn); + if (qi_tmp == 0) + fatal_insn ("No byte register found when moving odd # of bytes.", + insn); } while (length > 1) @@ -1237,17 +1515,24 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) { 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); + 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); + 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; } @@ -1273,7 +1558,6 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) return ""; } - int standard_80387_constant_p (x) @@ -1289,7 +1573,7 @@ standard_80387_constant_p (x) set_float_handler (handler); REAL_VALUE_FROM_CONST_DOUBLE (d, x); - is0 = REAL_VALUES_EQUAL (d, dconst0); + is0 = REAL_VALUES_EQUAL (d, dconst0) && !REAL_VALUE_MINUS_ZERO (d); is1 = REAL_VALUES_EQUAL (d, dconst1); set_float_handler (NULL_PTR); @@ -1321,6 +1605,7 @@ output_move_const_single (operands) if (conval == 2) return "fld1"; } + if (GET_CODE (operands[1]) == CONST_DOUBLE) { REAL_VALUE_TYPE r; long l; @@ -1332,6 +1617,7 @@ output_move_const_single (operands) REAL_VALUE_TO_TARGET_SINGLE (r, l); operands[1] = GEN_INT (l); } + return singlemove_string (operands); } @@ -1341,18 +1627,20 @@ output_move_const_single (operands) int symbolic_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { switch (GET_CODE (op)) { case SYMBOL_REF: case LABEL_REF: return 1; + case CONST: op = XEXP (op, 0); return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: return 0; } @@ -1366,7 +1654,7 @@ symbolic_operand (op, mode) int call_insn_operand (op, mode) rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == MEM && ((CONSTANT_ADDRESS_P (XEXP (op, 0)) @@ -1374,9 +1662,10 @@ call_insn_operand (op, mode) && general_operand (XEXP (op, 0), Pmode)) || (GET_CODE (XEXP (op, 0)) == REG && XEXP (op, 0) != arg_pointer_rtx - && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER - && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) + && ! (REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER + && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) return 1; + return 0; } @@ -1386,15 +1675,16 @@ call_insn_operand (op, mode) int expander_call_insn_operand (op, mode) rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == MEM && (CONSTANT_ADDRESS_P (XEXP (op, 0)) || (GET_CODE (XEXP (op, 0)) == REG && XEXP (op, 0) != arg_pointer_rtx - && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER - && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) + && ! (REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER + && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) return 1; + return 0; } @@ -1410,12 +1700,22 @@ arithmetic_comparison_operator (op, mode) if (mode != VOIDmode && mode != GET_MODE (op)) return 0; + code = GET_CODE (op); if (GET_RTX_CLASS (code) != '<') return 0; return (code != GT && code != LE); } + +int +ix86_logical_operator (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR; +} + /* Returns 1 if OP contains a symbol reference */ @@ -1440,6 +1740,7 @@ symbolic_reference_mentioned_p (op) if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) return 1; } + else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) return 1; } @@ -1447,89 +1748,477 @@ symbolic_reference_mentioned_p (op) return 0; } -/* This function generates the assembly code for function entry. - FILE is an stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. */ +/* Attempt to expand a binary operator. Make the expansion closer to the + actual machine, then just general_operand, which will allow 3 separate + memory references (one output, two input) in a single insn. Return + whether the insn fails, or succeeds. */ -void -function_prologue (file, size) - FILE *file; - int size; +int +ix86_expand_binary_operator (code, mode, operands) + enum rtx_code code; + enum machine_mode mode; + rtx operands[]; { - register int regno; - int limit; - rtx xops[4]; - int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table - || current_function_uses_const_pool); + int modified; - xops[0] = stack_pointer_rtx; - xops[1] = frame_pointer_rtx; - xops[2] = GEN_INT (size); - if (frame_pointer_needed) + /* Recognize = for commutative operators */ + if (GET_RTX_CLASS (code) == 'c' + && (rtx_equal_p (operands[0], operands[2]) + || immediate_operand (operands[1], mode))) { - output_asm_insn ("push%L1 %1", xops); - output_asm_insn (AS2 (mov%L0,%0,%1), xops); + rtx temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; } - if (size) - output_asm_insn (AS2 (sub%L0,%2,%0), xops); + /* If optimizing, copy to regs to improve CSE */ + if (TARGET_PSEUDO && optimize + && ((reload_in_progress | reload_completed) == 0)) + { + if (GET_CODE (operands[1]) == MEM + && ! rtx_equal_p (operands[0], operands[1])) + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); - /* Note If use enter it is NOT reversed args. - This one is not reversed from intel!! - I think enter is slower. Also sdb doesn't like it. - But if you want it the code is: - { - xops[3] = const0_rtx; - output_asm_insn ("enter %2,%3", xops); - } - */ - limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); - for (regno = limit - 1; regno >= 0; regno--) - if ((regs_ever_live[regno] && ! call_used_regs[regno]) - || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) - { - xops[0] = gen_rtx (REG, SImode, regno); - output_asm_insn ("push%L0 %0", xops); - } + if (GET_CODE (operands[2]) == MEM) + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); - if (pic_reg_used) - { - xops[0] = pic_offset_table_rtx; - xops[1] = (rtx) gen_label_rtx (); + if (GET_CODE (operands[1]) == CONST_INT && code == MINUS) + { + rtx temp = gen_reg_rtx (GET_MODE (operands[0])); - 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); + emit_move_insn (temp, operands[1]); + operands[1] = temp; + return TRUE; + } } -} -/* Return 1 if it is appropriate to emit `ret' instructions in the - body of a function. Do this only if the epilogue is simple, needing a - couple of insns. Prior to reloading, we can't tell how many registers - must be saved, so return 0 then. + if (!ix86_binary_operator_ok (code, mode, operands)) + { + /* If not optimizing, try to make a valid insn (optimize code + previously did this above to improve chances of CSE) */ - If NON_SAVING_SETJMP is defined and true, then it is not possible - for the epilogue to be simple, so return 0. This is a special case - since NON_SAVING_SETJMP will not cause regs_ever_live to change until - final, but jump_optimize may need to know sooner if a `return' is OK. */ + if ((! TARGET_PSEUDO || !optimize) + && ((reload_in_progress | reload_completed) == 0) + && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)) + { + modified = FALSE; + if (GET_CODE (operands[1]) == MEM + && ! rtx_equal_p (operands[0], operands[1])) + { + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); + modified = TRUE; + } -int -simple_386_epilogue () -{ - int regno; - int nregs = 0; - int reglimit = (frame_pointer_needed - ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); - int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table - || current_function_uses_const_pool); + if (GET_CODE (operands[2]) == MEM) + { + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); + modified = TRUE; + } -#ifdef NON_SAVING_SETJMP - if (NON_SAVING_SETJMP && current_function_calls_setjmp) - return 0; -#endif + if (GET_CODE (operands[1]) == CONST_INT && code == MINUS) + { + rtx temp = gen_reg_rtx (GET_MODE (operands[0])); - if (! reload_completed) + emit_move_insn (temp, operands[1]); + operands[1] = temp; + return TRUE; + } + + if (modified && ! ix86_binary_operator_ok (code, mode, operands)) + return FALSE; + } + else + return FALSE; + } + + return TRUE; +} + +/* Return TRUE or FALSE depending on whether the binary operator meets the + appropriate constraints. */ + +int +ix86_binary_operator_ok (code, mode, operands) + enum rtx_code code; + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx operands[3]; +{ + return (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM) + && (GET_CODE (operands[1]) != CONST_INT || GET_RTX_CLASS (code) == 'c'); +} + +/* Attempt to expand a unary operator. Make the expansion closer to the + actual machine, then just general_operand, which will allow 2 separate + memory references (one output, one input) in a single insn. Return + whether the insn fails, or succeeds. */ + +int +ix86_expand_unary_operator (code, mode, operands) + enum rtx_code code; + enum machine_mode mode; + rtx operands[]; +{ + /* If optimizing, copy to regs to improve CSE */ + if (TARGET_PSEUDO + && optimize + && ((reload_in_progress | reload_completed) == 0) + && GET_CODE (operands[1]) == MEM) + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); + + if (! ix86_unary_operator_ok (code, mode, operands)) + { + if ((! TARGET_PSEUDO || optimize == 0) + && ((reload_in_progress | reload_completed) == 0) + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); + if (! ix86_unary_operator_ok (code, mode, operands)) + return FALSE; + } + else + return FALSE; + } + + return TRUE; +} + +/* Return TRUE or FALSE depending on whether the unary operator meets the + appropriate constraints. */ + +int +ix86_unary_operator_ok (code, mode, operands) + enum rtx_code code ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx operands[2] ATTRIBUTE_UNUSED; +{ + return TRUE; +} + +static rtx pic_label_rtx; +static char pic_label_name [256]; +static int pic_label_no = 0; + +/* This function generates code for -fpic that loads %ebx with + the return address of the caller and then returns. */ + +void +asm_output_function_prefix (file, name) + FILE *file; + char *name ATTRIBUTE_UNUSED; +{ + rtx xops[2]; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + xops[0] = pic_offset_table_rtx; + xops[1] = stack_pointer_rtx; + + /* Deep branch prediction favors having a return for every call. */ + if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION) + { + tree prologue_node; + + if (pic_label_rtx == 0) + { + pic_label_rtx = gen_label_rtx (); + ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", pic_label_no++); + LABEL_NAME (pic_label_rtx) = pic_label_name; + } + + prologue_node = make_node (FUNCTION_DECL); + DECL_RESULT (prologue_node) = 0; + + /* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an + internal (non-global) label that's being emitted, it didn't make + sense to have .type information for local labels. This caused + the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving + me debug info for a label that you're declaring non-global?) this + was changed to call ASM_OUTPUT_LABEL() instead. */ + + + ASM_OUTPUT_LABEL (file, pic_label_name); + output_asm_insn ("movl (%1),%0", xops); + output_asm_insn ("ret", xops); + } +} + +/* Generate the assembly code for function entry. + FILE is an stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. */ + +void +function_prologue (file, size) + FILE *file ATTRIBUTE_UNUSED; + int size ATTRIBUTE_UNUSED; +{ + if (TARGET_SCHEDULE_PROLOGUE) + { + pic_label_rtx = 0; + return; + } + + ix86_prologue (0); +} + +/* Expand the prologue into a bunch of separate insns. */ + +void +ix86_expand_prologue () +{ + if (! TARGET_SCHEDULE_PROLOGUE) + return; + + ix86_prologue (1); +} + +void +load_pic_register (do_rtl) + int do_rtl; +{ + rtx xops[4]; + + if (TARGET_DEEP_BRANCH_PREDICTION) + { + xops[0] = pic_offset_table_rtx; + if (pic_label_rtx == 0) + { + pic_label_rtx = gen_label_rtx (); + ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", pic_label_no++); + LABEL_NAME (pic_label_rtx) = pic_label_name; + } + + xops[1] = gen_rtx_MEM (QImode, + gen_rtx (SYMBOL_REF, Pmode, + LABEL_NAME (pic_label_rtx))); + + if (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_"), + xops[1])); + } + else + { + output_asm_insn (AS1 (call,%X1), xops); + output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_,%0", xops); + pic_label_rtx = 0; + } + } + + else + { + xops[0] = pic_offset_table_rtx; + xops[1] = gen_label_rtx (); + + if (do_rtl) + { + /* We can't put a raw CODE_LABEL into the RTL, and we can't emit + a new CODE_LABEL after reload, so we need a single pattern to + emit the 3 necessary instructions. */ + emit_insn (gen_prologue_get_pc_and_set_got (xops[0])); + } + else + { + output_asm_insn (AS1 (call,%P1), xops); + 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); + } + } + + /* When -fpic, we must emit a scheduling barrier, so that the instruction + that restores %ebx (which is PIC_OFFSET_TABLE_REGNUM), does not get + moved before any instruction which implicitly uses the got. */ + + if (do_rtl) + emit_insn (gen_blockage ()); +} + +static void +ix86_prologue (do_rtl) + int do_rtl; +{ + register int regno; + int limit; + 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 (); + rtx insn; + int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset; + + xops[0] = stack_pointer_rtx; + xops[1] = frame_pointer_rtx; + xops[2] = GEN_INT (tsize); + + if (frame_pointer_needed) + { + if (do_rtl) + { + insn = emit_insn (gen_rtx (SET, VOIDmode, + gen_rtx_MEM (SImode, + gen_rtx (PRE_DEC, SImode, + stack_pointer_rtx)), + frame_pointer_rtx)); + + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_move_insn (xops[1], xops[0]); + RTX_FRAME_RELATED_P (insn) = 1; + } + + else + { + output_asm_insn ("push%L1 %1", xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + + cfa_store_offset += 4; + cfa_offset = cfa_store_offset; + dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset); + dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, - cfa_store_offset); + } +#endif + + output_asm_insn (AS2 (mov%L0,%0,%1), xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + dwarf2out_def_cfa ("", FRAME_POINTER_REGNUM, cfa_offset); +#endif + } + } + + if (tsize == 0) + ; + else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT) + { + if (do_rtl) + { + insn = emit_insn (gen_prologue_set_stack_ptr (xops[2])); + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + output_asm_insn (AS2 (sub%L0,%2,%0), xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + { + cfa_store_offset += tsize; + if (! frame_pointer_needed) + { + cfa_offset = cfa_store_offset; + dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset); + } + } +#endif + } + } + else + { + xops[3] = gen_rtx_REG (SImode, 0); + if (do_rtl) + emit_move_insn (xops[3], xops[2]); + else + output_asm_insn (AS2 (mov%L0,%2,%3), xops); + + xops[3] = gen_rtx_MEM (FUNCTION_MODE, + gen_rtx (SYMBOL_REF, Pmode, "_alloca")); + + if (do_rtl) + emit_call_insn (gen_rtx (CALL, VOIDmode, xops[3], const0_rtx)); + else + output_asm_insn (AS1 (call,%P3), xops); + } + + /* Note If use enter it is NOT reversed args. + This one is not reversed from intel!! + I think enter is slower. Also sdb doesn't like it. + But if you want it the code is: + { + xops[3] = const0_rtx; + output_asm_insn ("enter %2,%3", xops); + } + */ + + limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); + for (regno = limit - 1; regno >= 0; regno--) + if ((regs_ever_live[regno] && ! call_used_regs[regno]) + || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) + { + xops[0] = gen_rtx_REG (SImode, regno); + if (do_rtl) + { + insn = emit_insn (gen_rtx (SET, VOIDmode, + gen_rtx_MEM (SImode, + gen_rtx (PRE_DEC, SImode, + stack_pointer_rtx)), + xops[0])); + + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + output_asm_insn ("push%L0 %0", xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + + cfa_store_offset += 4; + if (! frame_pointer_needed) + { + cfa_offset = cfa_store_offset; + dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset); + } + + dwarf2out_reg_save (l, regno, - cfa_store_offset); + } +#endif + } + } + + if (pic_reg_used) + load_pic_register (do_rtl); + + /* If we are profiling, make sure no instructions are scheduled before + the call to mcount. However, if -fpic, the above call will have + done that. */ + if ((profile_flag || profile_block_flag) + && ! pic_reg_used && do_rtl) + emit_insn (gen_blockage ()); +} + +/* Return 1 if it is appropriate to emit `ret' instructions in the + body of a function. Do this only if the epilogue is simple, needing a + couple of insns. Prior to reloading, we can't tell how many registers + must be saved, so return 0 then. Return 0 if there is no frame + marker to de-allocate. + + If NON_SAVING_SETJMP is defined and true, then it is not possible + for the epilogue to be simple, so return 0. This is a special case + since NON_SAVING_SETJMP will not cause regs_ever_live to change + until final, but jump_optimize may need to know sooner if a + `return' is OK. */ + +int +ix86_can_use_return_insn_p () +{ + int regno; + int nregs = 0; + int reglimit = (frame_pointer_needed + ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + +#ifdef NON_SAVING_SETJMP + if (NON_SAVING_SETJMP && current_function_calls_setjmp) + return 0; +#endif + + if (! reload_completed) return 0; for (regno = reglimit - 1; regno >= 0; regno--) @@ -1540,15 +2229,29 @@ simple_386_epilogue () return nregs == 0 || ! frame_pointer_needed; } - /* This function generates the assembly code for function exit. FILE is an stdio stream to output the code to. SIZE is an int: how many units of temporary storage to deallocate. */ void function_epilogue (file, size) - FILE *file; - int size; + FILE *file ATTRIBUTE_UNUSED; + int size ATTRIBUTE_UNUSED; +{ + return; +} + +/* Restore function stack, frame, and registers. */ + +void +ix86_expand_epilogue () +{ + ix86_epilogue (1); +} + +static void +ix86_epilogue (do_rtl) + int do_rtl; { register int regno; register int nregs, limit; @@ -1556,12 +2259,11 @@ function_epilogue (file, size) 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); + limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); nregs = 0; @@ -1570,66 +2272,158 @@ function_epilogue (file, size) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) nregs++; - /* sp is often unreliable so we must go off the frame pointer, - */ + /* 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. */ + 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 = -size - (nregs * UNITS_PER_WORD); + offset = - tsize - (nregs * UNITS_PER_WORD); xops[2] = stack_pointer_rtx; + /* When -fpic, we must emit a scheduling barrier, so that the instruction + that restores %ebx (which is PIC_OFFSET_TABLE_REGNUM), does not get + moved before any instruction which implicitly uses the got. This + includes any instruction which uses a SYMBOL_REF or a LABEL_REF. + + Alternatively, this could be fixed by making the dependence on the + PIC_OFFSET_TABLE_REGNUM explicit in the RTL. */ + + if (flag_pic || profile_flag || profile_block_flag) + emit_insn (gen_blockage ()); + if (nregs > 1 || ! frame_pointer_needed) { if (frame_pointer_needed) { - xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset); - output_asm_insn (AS2 (lea%L2,%0,%2), xops); + xops[0] = adj_offsettable_operand (AT_BP (QImode), offset); + if (do_rtl) + emit_insn (gen_movsi_lea (xops[2], XEXP (xops[0], 0))); + else + output_asm_insn (AS2 (lea%L2,%0,%2), xops); } for (regno = 0; regno < limit; regno++) if ((regs_ever_live[regno] && ! call_used_regs[regno]) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) { - xops[0] = gen_rtx (REG, SImode, regno); - output_asm_insn ("pop%L0 %0", xops); + xops[0] = gen_rtx_REG (SImode, regno); + + if (do_rtl) + emit_insn (gen_pop (xops[0])); + else + output_asm_insn ("pop%L0 %0", xops); } } + else for (regno = 0; regno < limit; regno++) if ((regs_ever_live[regno] && ! call_used_regs[regno]) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) { - xops[0] = gen_rtx (REG, SImode, regno); + xops[0] = gen_rtx_REG (SImode, regno); xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset); - output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + if (do_rtl) + emit_move_insn (xops[0], xops[1]); + else + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + offset += 4; } if (frame_pointer_needed) { - /* On i486, mov & pop is faster than "leave". */ + /* If not an i386, mov & pop is faster than "leave". */ - if (!TARGET_386) + if (TARGET_USE_LEAVE) { - xops[0] = frame_pointer_rtx; - output_asm_insn (AS2 (mov%L2,%0,%2), xops); - output_asm_insn ("pop%L0 %0", xops); + if (do_rtl) + emit_insn (gen_leave()); + else + output_asm_insn ("leave", xops); } else - output_asm_insn ("leave", xops); + { + xops[0] = frame_pointer_rtx; + xops[1] = stack_pointer_rtx; + + if (do_rtl) + { + emit_insn (gen_epilogue_set_stack_ptr()); + emit_insn (gen_pop (xops[0])); + } + else + { + output_asm_insn (AS2 (mov%L2,%0,%2), xops); + output_asm_insn ("pop%L0 %0", xops); + } + } } - else if (size) + + else if (tsize) { - /* If there is no frame pointer, we must still release the frame. */ + /* Intel's docs say that for 4 or 8 bytes of stack frame one should + use `pop' and not `add'. */ + int use_pop = tsize == 4; + + /* Use two pops only for the Pentium processors. */ + if (tsize == 8 && !TARGET_386 && !TARGET_486) + { + rtx retval = current_function_return_rtx; + + xops[1] = gen_rtx_REG (SImode, 1); /* %edx */ + + /* This case is a bit more complex. Since we cannot pop into + %ecx twice we need a second register. But this is only + available if the return value is not of DImode in which + case the %edx register is not available. */ + use_pop = (retval == NULL + || ! reg_overlap_mentioned_p (xops[1], retval)); + } + + if (use_pop) + { + xops[0] = gen_rtx_REG (SImode, 2); /* %ecx */ + + if (do_rtl) + { + /* We have to prevent the two pops here from being scheduled. + GCC otherwise would try in some situation to put other + instructions in between them which has a bad effect. */ + emit_insn (gen_blockage ()); + emit_insn (gen_pop (xops[0])); + if (tsize == 8) + emit_insn (gen_pop (xops[1])); + } + else + { + output_asm_insn ("pop%L0 %0", xops); + if (tsize == 8) + output_asm_insn ("pop%L1 %1", xops); + } + } + else + { + /* If there is no frame pointer, we must still release the frame. */ + xops[0] = GEN_INT (tsize); + + if (do_rtl) + emit_insn (gen_rtx (SET, VOIDmode, xops[2], + gen_rtx (PLUS, SImode, xops[2], xops[0]))); + else + output_asm_insn (AS2 (add%L2,%0,%2), xops); + } + } - xops[0] = GEN_INT (size); - output_asm_insn (AS2 (add%L2,%0,%2), xops); +#ifdef FUNCTION_BLOCK_PROFILER_EXIT + if (profile_block_flag == 2) + { + FUNCTION_BLOCK_PROFILER_EXIT(file); } +#endif if (current_function_pops_args && current_function_args_size) { @@ -1642,18 +2436,38 @@ function_epilogue (file, size) if (current_function_pops_args >= 32768) { /* ??? Which register to use here? */ - xops[0] = gen_rtx (REG, SImode, 2); - output_asm_insn ("pop%L0 %0", xops); - output_asm_insn (AS2 (add%L2,%1,%2), xops); - output_asm_insn ("jmp %*%0", xops); + xops[0] = gen_rtx_REG (SImode, 2); + + if (do_rtl) + { + emit_insn (gen_pop (xops[0])); + emit_insn (gen_rtx (SET, VOIDmode, xops[2], + gen_rtx (PLUS, SImode, xops[1], xops[2]))); + emit_jump_insn (xops[0]); + } + else + { + output_asm_insn ("pop%L0 %0", xops); + output_asm_insn (AS2 (add%L2,%1,%2), xops); + output_asm_insn ("jmp %*%0", xops); + } } else - output_asm_insn ("ret %1", xops); + { + if (do_rtl) + emit_jump_insn (gen_return_pop_internal (xops[1])); + else + output_asm_insn ("ret %1", xops); + } } else - output_asm_insn ("ret", xops); + { + if (do_rtl) + emit_jump_insn (gen_return_internal ()); + else + output_asm_insn ("ret", xops); + } } - /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a valid memory address for an instruction. @@ -1703,14 +2517,14 @@ legitimate_address_p (mode, addr, strict) if (TARGET_DEBUG_ADDR) { fprintf (stderr, - "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", + "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", GET_MODE_NAME (mode), strict); debug_rtx (addr); } if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG) - base = addr; /* base reg */ + base = addr; else if (GET_CODE (addr) == PLUS) { @@ -1723,13 +2537,13 @@ legitimate_address_p (mode, addr, strict) { if (code1 == REG || code1 == SUBREG) { - indx = op0; /* index + base */ + indx = op0; /* index + base */ base = op1; } else { - base = op0; /* base + displacement */ + base = op0; /* base + displacement */ disp = op1; } } @@ -1740,10 +2554,10 @@ legitimate_address_p (mode, addr, strict) scale = XEXP (op0, 1); if (code1 == REG || code1 == SUBREG) - base = op1; /* index*scale + base */ + base = op1; /* index*scale + base */ else - disp = op1; /* index*scale + disp */ + disp = op1; /* index*scale + disp */ } else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT) @@ -1756,7 +2570,7 @@ legitimate_address_p (mode, addr, strict) else if (code0 == PLUS) { - indx = XEXP (op0, 0); /* index + base + disp */ + indx = XEXP (op0, 0); /* index + base + disp */ base = XEXP (op0, 1); disp = op1; } @@ -1770,12 +2584,12 @@ legitimate_address_p (mode, addr, strict) else if (GET_CODE (addr) == MULT) { - indx = XEXP (addr, 0); /* index*scale */ + indx = XEXP (addr, 0); /* index*scale */ scale = XEXP (addr, 1); } else - disp = addr; /* displacement */ + disp = addr; /* displacement */ /* Allow arg pointer and stack pointer as index if there is not scaling */ if (base && indx && !scale @@ -1786,10 +2600,12 @@ legitimate_address_p (mode, addr, strict) indx = tmp; } - /* Validate base register */ - /* Don't allow SUBREG's here, it can lead to spill failures when the base + /* Validate base register: + + Don't allow SUBREG's here, it can lead to spill failures when the base is one word out of a two word structure, which is represented internally as a DImode int. */ + if (base) { if (GET_CODE (base) != REG) @@ -1798,16 +2614,17 @@ legitimate_address_p (mode, addr, strict) return FALSE; } - if ((strict && !REG_OK_FOR_BASE_STRICT_P (base)) - || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base))) + if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base)) + || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base))) { ADDR_INVALID ("Base is not valid.\n", base); return FALSE; } } - /* Validate index register */ - /* Don't allow SUBREG's here, it can lead to spill failures when the index + /* Validate index register: + + Don't allow SUBREG's here, it can lead to spill failures when the index is one word out of a two word structure, which is represented internally as a DImode int. */ if (indx) @@ -1818,17 +2635,17 @@ legitimate_address_p (mode, addr, strict) return FALSE; } - if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx)) - || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx))) + if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (indx)) + || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (indx))) { ADDR_INVALID ("Index is not valid.\n", indx); return FALSE; } } else if (scale) - abort (); /* scale w/o index invalid */ + abort (); /* scale w/o index invalid */ - /* Validate scale factor */ + /* Validate scale factor: */ if (scale) { HOST_WIDE_INT value; @@ -1847,32 +2664,44 @@ legitimate_address_p (mode, addr, strict) } } - /* Validate displacement */ + /* 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. */ if (disp) { - if (!CONSTANT_ADDRESS_P (disp)) + if (GET_CODE (disp) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (disp) + && base == 0 + && indx == 0) + ; + + else if (!CONSTANT_ADDRESS_P (disp)) { ADDR_INVALID ("Displacement is not valid.\n", disp); return FALSE; } - if (GET_CODE (disp) == CONST_DOUBLE) + else if (GET_CODE (disp) == CONST_DOUBLE) { ADDR_INVALID ("Displacement is a const_double.\n", disp); return FALSE; } - if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx - && (indx != pic_offset_table_rtx || scale != NULL_RTX)) + else if (flag_pic && SYMBOLIC_CONST (disp) + && base != pic_offset_table_rtx + && (indx != pic_offset_table_rtx || scale != NULL_RTX)) { ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp); return FALSE; } - if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp) - && (base != NULL_RTX || indx != NULL_RTX)) + else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp) + && (base != NULL_RTX || indx != NULL_RTX)) { - ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp); + ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", + disp); return FALSE; } } @@ -1883,7 +2712,6 @@ legitimate_address_p (mode, addr, strict) /* Everything looks valid, return true */ return TRUE; } - /* Return a legitimate reference for ORIG (an address) using the register REG. If REG is 0, a new pseudo is generated. @@ -1933,15 +2761,15 @@ legitimize_pic_address (orig, reg) || 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)); + new = gen_rtx_MEM (Pmode, + gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig)); emit_move_insn (reg, new); } current_function_uses_pic_offset_table = 1; return reg; } + else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) { rtx base; @@ -1971,27 +2799,26 @@ legitimize_pic_address (orig, reg) base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0)); addr = XEXP (addr, 1); } - return gen_rtx (PLUS, Pmode, base, addr); + + return gen_rtx (PLUS, Pmode, base, addr); } return new; } - /* Emit insns to move operands[1] into operands[0]. */ void emit_pic_move (operands, mode) rtx *operands; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) - operands[1] = (rtx) force_reg (SImode, operands[1]); + operands[1] = force_reg (SImode, operands[1]); else operands[1] = legitimize_pic_address (operands[1], temp); } - /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. @@ -2017,7 +2844,7 @@ emit_pic_move (operands, mode) rtx legitimize_address (x, oldx, mode) register rtx x; - register rtx oldx; + register rtx oldx ATTRIBUTE_UNUSED; enum machine_mode mode; { int changed = 0; @@ -2025,7 +2852,8 @@ legitimize_address (x, oldx, mode) if (TARGET_DEBUG_ADDR) { - fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode)); + fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", + GET_MODE_NAME (mode)); debug_rtx (x); } @@ -2038,14 +2866,14 @@ 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)), + x = gen_rtx (MULT, Pmode, force_reg (Pmode, XEXP (x, 0)), GEN_INT (1 << log)); } if (GET_CODE (x) == PLUS) { - /* Canonicalize shifts by 0, 1, 2, 3 into multiply */ + /* Canonicalize shifts by 0, 1, 2, 3 into multiply. */ + if (GET_CODE (XEXP (x, 0)) == ASHIFT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4) @@ -2066,7 +2894,7 @@ legitimize_address (x, oldx, mode) GEN_INT (1 << log)); } - /* Put multiply first if it isn't already */ + /* Put multiply first if it isn't already. */ if (GET_CODE (XEXP (x, 1)) == MULT) { rtx tmp = XEXP (x, 0); @@ -2083,18 +2911,21 @@ legitimize_address (x, oldx, mode) { changed = 1; x = gen_rtx (PLUS, Pmode, - gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)), + gen_rtx (PLUS, Pmode, XEXP (x, 0), + XEXP (XEXP (x, 1), 0)), XEXP (XEXP (x, 1), 1)); } - /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) + /* Canonicalize + (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) into (plus (plus (mult (reg) (const)) (reg)) (const)). */ else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS && CONSTANT_P (XEXP (x, 1))) { - rtx constant, other; + rtx constant; + rtx other = NULL_RTX; if (GET_CODE (XEXP (x, 1)) == CONST_INT) { @@ -2173,7 +3004,6 @@ legitimize_address (x, oldx, mode) return x; } - /* Print an integer constant expression in assembler syntax. Addition and subtraction are the only arithmetic that may appear in these @@ -2208,7 +3038,9 @@ output_pic_addr_const (file, x, code) assemble_name (asm_out_file, buf); } - if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) + 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"); @@ -2227,7 +3059,7 @@ output_pic_addr_const (file, x, code) break; case CONST_INT: - fprintf (file, "%d", INTVAL (x)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); break; case CONST: @@ -2241,10 +3073,11 @@ output_pic_addr_const (file, x, code) { /* We can use %d if the number is <32 bits and positive. */ if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) - fprintf (file, "0x%x%08x", - CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); + fprintf (file, "0x%lx%08lx", + (unsigned long) CONST_DOUBLE_HIGH (x), + (unsigned long) CONST_DOUBLE_LOW (x)); else - fprintf (file, "%d", CONST_DOUBLE_LOW (x)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); } else /* We can't handle floating point constants; @@ -2253,20 +3086,20 @@ output_pic_addr_const (file, x, code) break; case PLUS: - /* Some assemblers need integer constants to appear last (eg masm). */ + /* Some assemblers need integer constants to appear first. */ if (GET_CODE (XEXP (x, 0)) == CONST_INT) { - output_pic_addr_const (file, XEXP (x, 1), code); - if (INTVAL (XEXP (x, 0)) >= 0) - fprintf (file, "+"); output_pic_addr_const (file, XEXP (x, 0), code); + if (INTVAL (XEXP (x, 1)) >= 0) + fprintf (file, "+"); + output_pic_addr_const (file, XEXP (x, 1), code); } else { - output_pic_addr_const (file, XEXP (x, 0), code); - if (INTVAL (XEXP (x, 1)) >= 0) - fprintf (file, "+"); output_pic_addr_const (file, XEXP (x, 1), code); + if (INTVAL (XEXP (x, 0)) >= 0) + fprintf (file, "+"); + output_pic_addr_const (file, XEXP (x, 0), code); } break; @@ -2281,16 +3114,138 @@ output_pic_addr_const (file, x, code) } } +/* Append the correct conditional move suffix which corresponds to CODE. */ + +static void +put_condition_code (code, reverse_cc, mode, file) + enum rtx_code code; + int reverse_cc; + enum mode_class mode; + FILE * file; +{ + int ieee = (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)); + if (reverse_cc && ! ieee) + code = reverse_condition (code); + + if (mode == MODE_INT) + switch (code) + { + case NE: + if (cc_prev_status.flags & CC_Z_IN_NOT_C) + fputs ("b", file); + else + fputs ("ne", file); + return; + + case EQ: + if (cc_prev_status.flags & CC_Z_IN_NOT_C) + fputs ("ae", file); + else + fputs ("e", file); + return; + + case GE: + if (cc_prev_status.flags & CC_NO_OVERFLOW) + fputs ("ns", file); + else + fputs ("ge", file); + return; + + case GT: + fputs ("g", file); + return; + + case LE: + fputs ("le", file); + return; + + case LT: + if (cc_prev_status.flags & CC_NO_OVERFLOW) + fputs ("s", file); + else + fputs ("l", file); + return; + + case GEU: + fputs ("ae", file); + return; + + case GTU: + fputs ("a", file); + return; + + case LEU: + fputs ("be", file); + return; + + case LTU: + fputs ("b", file); + return; + + default: + output_operand_lossage ("Invalid %%C operand"); + } + + else if (mode == MODE_FLOAT) + switch (code) + { + case NE: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "ne", file); + return; + case EQ: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "e", file); + return; + case GE: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nb", file); + return; + case GT: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nbe", file); + return; + case LE: + fputs (ieee ? (reverse_cc ? "nb" : "b") : "be", file); + return; + case LT: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "b", file); + return; + case GEU: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nb", file); + return; + case GTU: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nbe", file); + return; + case LEU: + fputs (ieee ? (reverse_cc ? "nb" : "b") : "be", file); + return; + case LTU: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "b", file); + return; + default: + output_operand_lossage ("Invalid %%C operand"); + } +} + /* Meaning of CODE: - f -- float insn (print a CONST_DOUBLE as a float rather than in hex). - D,L,W,B,Q,S -- print the opcode suffix for specified size of operand. + L,W,B,Q,S,T -- print the opcode suffix for specified size of operand. + 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 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. + b -- print the QImode name of the register for the indicated operand. + %b0 would print %al if operands[0] is reg 0. + w -- likewise, print the HImode name of the register. + 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 */ void print_operand (file, x, code) @@ -2384,6 +3339,7 @@ print_operand (file, x, code) case 'h': case 'y': case 'P': + case 'X': break; case 'J': @@ -2403,8 +3359,37 @@ print_operand (file, x, code) case LTU: fputs ("#branch never", file); return; /* no matching branches for GT nor LE */ + + default: + abort (); } - abort (); + + case 's': + if (GET_CODE (x) == CONST_INT || ! SHIFT_DOUBLE_OMITS_COUNT) + { + PRINT_OPERAND (file, x, 0); + fputs (AS2C (,) + 1, file); + } + + return; + + /* This is used by the conditional move instructions. */ + case 'C': + put_condition_code (GET_CODE (x), 0, MODE_INT, file); + return; + + /* Like above, but reverse condition */ + case 'c': + put_condition_code (GET_CODE (x), 1, MODE_INT, file); return; + + case 'F': + put_condition_code (GET_CODE (x), 0, MODE_FLOAT, file); + return; + + /* Like above, but reverse condition */ + case 'f': + put_condition_code (GET_CODE (x), 1, MODE_FLOAT, file); + return; default: { @@ -2415,10 +3400,12 @@ print_operand (file, x, code) } } } + if (GET_CODE (x) == REG) { PRINT_REG (x, code, file); } + else if (GET_CODE (x) == MEM) { PRINT_PTR (x, file); @@ -2432,30 +3419,39 @@ print_operand (file, x, code) else output_address (XEXP (x, 0)); } + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) { - REAL_VALUE_TYPE r; long l; + REAL_VALUE_TYPE r; + long l; + REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_TARGET_SINGLE (r, l); PRINT_IMMED_PREFIX (file); - fprintf (file, "0x%x", l); + fprintf (file, "0x%lx", l); } + /* These float cases don't actually occur as immediate operands. */ else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) { - REAL_VALUE_TYPE r; char dstr[30]; + REAL_VALUE_TYPE r; + char dstr[30]; + REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr); fprintf (file, "%s", dstr); } + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode) { - REAL_VALUE_TYPE r; char dstr[30]; + REAL_VALUE_TYPE r; + char dstr[30]; + REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr); fprintf (file, "%s", dstr); } - else + else { if (code != 'P') { @@ -2507,38 +3503,35 @@ print_operand_address (file, addr) offset = XEXP (addr, 1); addr = XEXP (addr, 0); } - if (GET_CODE (addr) != PLUS) ; + + if (GET_CODE (addr) != PLUS) + ; else if (GET_CODE (XEXP (addr, 0)) == MULT) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } + reg1 = XEXP (addr, 0), addr = XEXP (addr, 1); else if (GET_CODE (XEXP (addr, 1)) == MULT) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } + reg1 = XEXP (addr, 1), addr = XEXP (addr, 0); else if (GET_CODE (XEXP (addr, 0)) == REG) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } + reg1 = XEXP (addr, 0), addr = XEXP (addr, 1); else if (GET_CODE (XEXP (addr, 1)) == REG) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } + reg1 = XEXP (addr, 1), addr = XEXP (addr, 0); + if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT) { - if (reg1 == 0) reg1 = addr; - else reg2 = addr; + if (reg1 == 0) + reg1 = addr; + else + reg2 = addr; + addr = 0; } + if (offset != 0) { - if (addr != 0) abort (); + if (addr != 0) + abort (); addr = offset; } + if ((reg1 && GET_CODE (reg1) == MULT) || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) { @@ -2559,10 +3552,8 @@ print_operand_address (file, addr) { if (flag_pic) output_pic_addr_const (file, addr, 0); - else if (GET_CODE (addr) == LABEL_REF) output_asm_label (addr); - else output_addr_const (file, addr); } @@ -2593,6 +3584,7 @@ print_operand_address (file, addr) case MULT: { int scale; + if (GET_CODE (XEXP (addr, 0)) == CONST_INT) { scale = INTVAL (XEXP (addr, 0)); @@ -2603,8 +3595,9 @@ print_operand_address (file, addr) scale = INTVAL (XEXP (addr, 1)); ireg = XEXP (addr, 0); } + output_addr_const (file, const0_rtx); - PRINT_B_I_S ((rtx) 0, ireg, scale, file); + PRINT_B_I_S (NULL_RTX, ireg, scale, file); } break; @@ -2612,7 +3605,7 @@ print_operand_address (file, addr) if (GET_CODE (addr) == CONST_INT && INTVAL (addr) < 0x8000 && INTVAL (addr) >= -0x8000) - fprintf (file, "%d", INTVAL (addr)); + fprintf (file, "%d", (int) INTVAL (addr)); else { if (flag_pic) @@ -2625,7 +3618,7 @@ print_operand_address (file, addr) /* Set the cc_status for the results of an insn whose pattern is EXP. On the 80386, we assume that only test and compare insns, as well - as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, + as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, BSF, ASHIFT, ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully. Also, we assume that jumps, moves and sCOND don't affect the condition codes. All else clobbers the condition codes, by assumption. @@ -2645,40 +3638,51 @@ notice_update_cc (exp) /* Jumps do not alter the cc's. */ if (SET_DEST (exp) == pc_rtx) return; + /* Moving register or memory into a register: it doesn't alter the cc's, but it might invalidate the RTX's which we remember the cc's came from. (Note that moving a constant 0 or 1 MAY set the cc's). */ 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_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))) { if (cc_status.value1 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) cc_status.value1 = 0; + if (cc_status.value2 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) cc_status.value2 = 0; + return; } + /* Moving register into memory doesn't alter the cc's. It may invalidate the RTX's which we remember the cc's came from. */ if (GET_CODE (SET_DEST (exp)) == MEM && (REG_P (SET_SRC (exp)) || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) { - if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) + if (cc_status.value1 + && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) cc_status.value1 = 0; - if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) + if (cc_status.value2 + && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) cc_status.value2 = 0; + return; } + /* Function calls clobber the cc's. */ else if (GET_CODE (SET_SRC (exp)) == CALL) { CC_STATUS_INIT; return; } + /* Tests and compares set the cc's in predictable ways. */ else if (SET_DEST (exp) == cc0_rtx) { @@ -2686,14 +3690,14 @@ notice_update_cc (exp) cc_status.value1 = SET_SRC (exp); return; } + /* Certain instructions effect the condition codes. */ else if (GET_MODE (SET_SRC (exp)) == SImode || GET_MODE (SET_SRC (exp)) == HImode || GET_MODE (SET_SRC (exp)) == QImode) switch (GET_CODE (SET_SRC (exp))) { - case ASHIFTRT: case LSHIFTRT: - case ASHIFT: + case ASHIFTRT: case LSHIFTRT: case ASHIFT: /* Shifts on the 386 don't set the condition codes if the shift count is zero. */ if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT) @@ -2701,6 +3705,7 @@ notice_update_cc (exp) CC_STATUS_INIT; break; } + /* We assume that the CONST_INT is non-zero (this rtx would have been deleted if it were zero. */ @@ -2711,6 +3716,19 @@ notice_update_cc (exp) cc_status.value2 = SET_DEST (exp); break; + /* This is the bsf pattern used by ffs. */ + case UNSPEC: + if (XINT (SET_SRC (exp), 1) == 5) + { + /* Only the Z flag is defined after bsf. */ + cc_status.flags + = CC_NOT_POSITIVE | CC_NOT_NEGATIVE | CC_NO_OVERFLOW; + cc_status.value1 = XVECEXP (SET_SRC (exp), 0, 0); + cc_status.value2 = 0; + break; + } + /* FALLTHRU */ + default: CC_STATUS_INIT; } @@ -2725,14 +3743,21 @@ notice_update_cc (exp) if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) return; if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) + { CC_STATUS_INIT; - if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) - cc_status.flags |= CC_IN_80387; + 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 + (XEXP (SET_SRC (XVECEXP (exp, 0, 0)), 1))) + cc_status.flags |= CC_FCOMI; + } else cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); return; } + CC_STATUS_INIT; } else @@ -2755,19 +3780,20 @@ split_di (operands, num, lo_half, hi_half) { while (num--) { - if (GET_CODE (operands[num]) == REG) - { - lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num])); - hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1); - } - else if (CONSTANT_P (operands[num])) + rtx op = operands[num]; + if (GET_CODE (op) == REG) { - split_double (operands[num], &lo_half[num], &hi_half[num]); + lo_half[num] = gen_rtx_REG (SImode, REGNO (op)); + hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1); } - else if (offsettable_memref_p (operands[num])) + else if (CONSTANT_P (op)) + split_double (op, &lo_half[num], &hi_half[num]); + else if (offsettable_memref_p (op)) { - lo_half[num] = operands[num]; - hi_half[num] = adj_offsettable_operand (operands[num], 4); + rtx lo_addr = XEXP (op, 0); + rtx hi_addr = XEXP (adj_offsettable_operand (op, 4), 0); + lo_half[num] = change_address (op, SImode, lo_addr); + hi_half[num] = change_address (op, SImode, hi_addr); } else abort(); @@ -2797,7 +3823,6 @@ binary_387_op (op, mode) return 0; } } - /* Return 1 if this is a valid shift or rotate operation on a 386. OP is the expression matched, and MODE is its mode. */ @@ -2829,7 +3854,7 @@ shift_op (op, mode) int VOIDmode_compare_op (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode; } @@ -2908,16 +3933,22 @@ output_387_binary_op (insn, operands) if (NON_STACK_REG_P (operands[1])) { output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); - RET; + return ""; } + else if (NON_STACK_REG_P (operands[2])) { output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); - RET; + return ""; } if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) - return strcat (buf, AS2 (p,%2,%0)); + { + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (p,%0,%2)); + else + return strcat (buf, AS2 (p,%2,%0)); + } if (STACK_TOP_P (operands[0])) return strcat (buf, AS2C (%y2,%0)); @@ -2935,22 +3966,33 @@ output_387_binary_op (insn, operands) if (NON_STACK_REG_P (operands[1])) { output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1))); - RET; + return ""; } + else if (NON_STACK_REG_P (operands[2])) { output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); - RET; + return ""; } if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2])) abort (); if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) - return strcat (buf, AS2 (rp,%2,%0)); + { + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (p,%0,%2)); + else + return strcat (buf, AS2 (rp,%2,%0)); + } if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return strcat (buf, AS2 (p,%1,%0)); + { + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (rp,%0,%1)); + else + return strcat (buf, AS2 (p,%1,%0)); + } if (STACK_TOP_P (operands[0])) { @@ -2983,8 +4025,7 @@ output_fix_trunc (insn, operands) int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; rtx xops[2]; - if (! STACK_TOP_P (operands[1]) || - (GET_MODE (operands[0]) == DImode && ! stack_top_dies)) + if (! STACK_TOP_P (operands[1])) abort (); xops[0] = GEN_INT (12); @@ -2997,11 +4038,23 @@ output_fix_trunc (insn, operands) output_asm_insn (AS1 (fldc%W3,%3), operands); if (NON_STACK_REG_P (operands[0])) - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, operands[3]); + else if (GET_CODE (operands[0]) == MEM) { if (stack_top_dies) output_asm_insn (AS1 (fistp%z0,%0), operands); + else if (GET_MODE (operands[0]) == DImode && ! stack_top_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%z0,%0), operands); + output_asm_insn (AS1 (fild%z0,%0), operands); + } else output_asm_insn (AS1 (fist%z0,%0), operands); } @@ -3024,6 +4077,21 @@ output_float_compare (insn, operands) int stack_top_dies; rtx body = XVECEXP (PATTERN (insn), 0, 0); int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode; + rtx tmp; + + if (0 && TARGET_CMOVE && STACK_REG_P (operands[1])) + { + cc_status.flags |= CC_FCOMI; + cc_prev_status.flags &= ~CC_TEST_AX; + } + + if (! STACK_TOP_P (operands[0])) + { + tmp = operands[0]; + operands[0] = operands[1]; + operands[1] = tmp; + cc_status.flags |= CC_REVERSED; + } if (! STACK_TOP_P (operands[0])) abort (); @@ -3040,9 +4108,27 @@ output_float_compare (insn, operands) `fcompp' float compare */ if (unordered_compare) - output_asm_insn ("fucompp", operands); + { + if (cc_status.flags & CC_FCOMI) + { + output_asm_insn (AS2 (fucomip,%y1,%0), operands); + output_asm_insn (AS1 (fstp, %y0), operands); + return ""; + } + else + output_asm_insn ("fucompp", operands); + } else - output_asm_insn ("fcompp", operands); + { + if (cc_status.flags & CC_FCOMI) + { + output_asm_insn (AS2 (fcomip, %y1,%0), operands); + output_asm_insn (AS1 (fstp, %y0), operands); + return ""; + } + else + output_asm_insn ("fcompp", operands); + } } else { @@ -3052,9 +4138,9 @@ output_float_compare (insn, operands) unordered float compare. */ if (unordered_compare) - strcpy (buf, "fucom"); + strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fucomi" : "fucom"); else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT) - strcpy (buf, "fcom"); + strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fcomi" : "fcom"); else strcpy (buf, "ficom"); @@ -3065,6 +4151,11 @@ output_float_compare (insn, operands) 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) + { + output_asm_insn (strcat (buf, AS2 (%z1,%y1,%0)), operands); + return ""; + } else output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands); } @@ -3084,15 +4175,39 @@ output_fp_cc0_set (insn) rtx insn; { rtx xops[3]; - rtx unordered_label; rtx next; enum rtx_code code; - xops[0] = gen_rtx (REG, HImode, 0); + xops[0] = gen_rtx_REG (HImode, 0); output_asm_insn (AS1 (fnsts%W0,%0), xops); if (! TARGET_IEEE_FP) - return "sahf"; + { + if (!(cc_status.flags & CC_REVERSED)) + { + next = next_cc0_user (insn); + + if (GET_CODE (next) == JUMP_INSN + && 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)); + else if (GET_CODE (PATTERN (next)) == SET) + code = GET_CODE (SET_SRC (PATTERN (next))); + else + return "sahf"; + + if (code == GT || code == LT || code == EQ || code == NE + || code == LE || code == GE) + { + /* We will test eax directly. */ + cc_status.flags |= CC_TEST_AX; + return ""; + } + } + + return "sahf"; + } next = next_cc0_user (insn); if (next == NULL_RTX) @@ -3102,17 +4217,27 @@ output_fp_cc0_set (insn) && 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)); + else if (GET_CODE (PATTERN (next)) == SET) { - code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); + if (GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE) + code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); + else + code = GET_CODE (SET_SRC (PATTERN (next))); } - else if (GET_CODE (PATTERN (next)) == SET) + + else if (GET_CODE (PATTERN (next)) == PARALLEL + && GET_CODE (XVECEXP (PATTERN (next), 0, 0)) == SET) { - code = GET_CODE (SET_SRC (PATTERN (next))); + if (GET_CODE (SET_SRC (XVECEXP (PATTERN (next), 0, 0))) == IF_THEN_ELSE) + code = GET_CODE (XEXP (SET_SRC (XVECEXP (PATTERN (next), 0, 0)), 0)); + else + code = GET_CODE (SET_SRC (XVECEXP (PATTERN (next), 0, 0))); } else abort (); - xops[0] = gen_rtx (REG, QImode, 0); + xops[0] = gen_rtx_REG (QImode, 0); switch (code) { @@ -3168,7 +4293,8 @@ output_fp_cc0_set (insn) default: abort (); } - RET; + + return ""; } #define MAX_386_STACK_LOCALS 2 @@ -3179,6 +4305,8 @@ static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; struct machine_function { rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; + rtx pic_label_rtx; + char pic_label_name[256]; }; /* Functions to save and restore i386_stack_locals. @@ -3189,9 +4317,12 @@ void save_386_machine_status (p) struct function *p; { - p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals); + p->machine + = (struct machine_function *) xmalloc (sizeof (struct machine_function)); bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals, sizeof i386_stack_locals); + p->machine->pic_label_rtx = pic_label_rtx; + bcopy (pic_label_name, p->machine->pic_label_name, 256); } void @@ -3200,7 +4331,10 @@ restore_386_machine_status (p) { bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals, sizeof i386_stack_locals); + pic_label_rtx = p->machine->pic_label_rtx; + bcopy (p->machine->pic_label_name, pic_label_name, 256); free (p->machine); + p->machine = NULL; } /* Clear stack slot assignments remembered from previous functions. @@ -3218,6 +4352,8 @@ clear_386_stack_locals () for (n = 0; n < MAX_386_STACK_LOCALS; n++) i386_stack_locals[(int) mode][n] = NULL_RTX; + pic_label_rtx = NULL_RTX; + bzero (pic_label_name, 256); /* Arrange to save and restore i386_stack_locals around nested functions. */ save_machine_status = save_386_machine_status; restore_machine_status = restore_386_machine_status; @@ -3243,3 +4379,897 @@ assign_386_stack_local (mode, n) return i386_stack_locals[(int) mode][n]; } + +int is_mul(op,mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (op) == MULT); +} + +int is_div(op,mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (op) == DIV); +} + +#ifdef NOTYET +/* Create a new copy of an rtx. + Recursively copies the operands of the rtx, + except for those few rtx codes that are sharable. + Doesn't share CONST */ + +rtx +copy_all_rtx (orig) + register rtx orig; +{ + register rtx copy; + register int i, j; + register RTX_CODE code; + register char *format_ptr; + + code = GET_CODE (orig); + + switch (code) + { + case REG: + case QUEUED: + case CONST_INT: + case CONST_DOUBLE: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case SCRATCH: + /* SCRATCH must be shared because they represent distinct values. */ + return orig; + +#if 0 + case CONST: + /* CONST can be shared if it contains a SYMBOL_REF. If it contains + a LABEL_REF, it isn't sharable. */ + if (GET_CODE (XEXP (orig, 0)) == PLUS + && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT) + return orig; + break; +#endif + /* A MEM with a constant address is not sharable. The problem is that + the constant address may need to be reloaded. If the mem is shared, + then reloading one copy of this mem will cause all copies to appear + to have been reloaded. */ + } + + 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; + /* intel1 */ + copy->is_spill_rtx = orig->is_spill_rtx; + + format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); + + for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) + { + switch (*format_ptr++) + { + case 'e': + XEXP (copy, i) = XEXP (orig, i); + if (XEXP (orig, i) != NULL) + XEXP (copy, i) = copy_rtx (XEXP (orig, i)); + break; + + case '0': + case 'u': + XEXP (copy, i) = XEXP (orig, i); + break; + + case 'E': + case 'V': + XVEC (copy, i) = XVEC (orig, i); + if (XVEC (orig, i) != NULL) + { + XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); + for (j = 0; j < XVECLEN (copy, i); j++) + XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); + } + break; + + case 'w': + XWINT (copy, i) = XWINT (orig, i); + break; + + case 'i': + XINT (copy, i) = XINT (orig, i); + break; + + case 's': + case 'S': + XSTR (copy, i) = XSTR (orig, i); + break; + + default: + abort (); + } + } + return copy; +} + + +/* Try to rewrite a memory address to make it valid */ + +void +rewrite_address (mem_rtx) + rtx mem_rtx; +{ + rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx; + int scale = 1; + int offset_adjust = 0; + int was_only_offset = 0; + rtx mem_addr = XEXP (mem_rtx, 0); + char *storage = oballoc (0); + int in_struct = 0; + int is_spill_rtx = 0; + + in_struct = MEM_IN_STRUCT_P (mem_rtx); + is_spill_rtx = RTX_IS_SPILL_P (mem_rtx); + + if (GET_CODE (mem_addr) == PLUS + && GET_CODE (XEXP (mem_addr, 1)) == PLUS + && GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG) + { + /* This part is utilized by the combiner. */ + ret_rtx + = gen_rtx (PLUS, GET_MODE (mem_addr), + gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)), + XEXP (mem_addr, 0), XEXP (XEXP (mem_addr, 1), 0)), + XEXP (XEXP (mem_addr, 1), 1)); + + if (memory_address_p (GET_MODE (mem_rtx), ret_rtx)) + { + XEXP (mem_rtx, 0) = ret_rtx; + RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx; + return; + } + + obfree (storage); + } + + /* This part is utilized by loop.c. + If the address contains PLUS (reg,const) and this pattern is invalid + in this case - try to rewrite the address to make it valid. */ + storage = oballoc (0); + index_rtx = base_rtx = offset_rtx = NULL; + + /* Find the base index and offset elements of the memory address. */ + if (GET_CODE (mem_addr) == PLUS) + { + if (GET_CODE (XEXP (mem_addr, 0)) == REG) + { + if (GET_CODE (XEXP (mem_addr, 1)) == REG) + base_rtx = XEXP (mem_addr, 1), index_rtx = XEXP (mem_addr, 0); + else + base_rtx = XEXP (mem_addr, 0), offset_rtx = XEXP (mem_addr, 1); + } + + else if (GET_CODE (XEXP (mem_addr, 0)) == MULT) + { + index_rtx = XEXP (mem_addr, 0); + if (GET_CODE (XEXP (mem_addr, 1)) == REG) + base_rtx = XEXP (mem_addr, 1); + else + offset_rtx = XEXP (mem_addr, 1); + } + + else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS) + { + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS + && GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT + && (GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) + == REG) + && (GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) + == CONST_INT) + && (GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) + == CONST_INT) + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG + && GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF) + { + index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0); + offset_rtx = XEXP (mem_addr, 1); + base_rtx = XEXP (XEXP (mem_addr, 0), 1); + offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)); + } + else + { + offset_rtx = XEXP (mem_addr, 1); + index_rtx = XEXP (XEXP (mem_addr, 0), 0); + base_rtx = XEXP (XEXP (mem_addr, 0), 1); + } + } + + else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT) + { + was_only_offset = 1; + index_rtx = NULL; + base_rtx = NULL; + offset_rtx = XEXP (mem_addr, 1); + offset_adjust = INTVAL (XEXP (mem_addr, 0)); + if (offset_adjust == 0) + { + XEXP (mem_rtx, 0) = offset_rtx; + RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx; + return; + } + } + else + { + obfree (storage); + return; + } + } + else if (GET_CODE (mem_addr) == MULT) + index_rtx = mem_addr; + else + { + obfree (storage); + return; + } + + if (index_rtx != 0 && GET_CODE (index_rtx) == MULT) + { + if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT) + { + obfree (storage); + return; + } + + scale_rtx = XEXP (index_rtx, 1); + scale = INTVAL (scale_rtx); + index_rtx = copy_all_rtx (XEXP (index_rtx, 0)); + } + + /* Now find which of the elements are invalid and try to fix them. */ + if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL) + { + offset_adjust = INTVAL (index_rtx) * scale; + + if (offset_rtx != 0 && CONSTANT_P (offset_rtx)) + offset_rtx = plus_constant (offset_rtx, offset_adjust); + else if (offset_rtx == 0) + offset_rtx = const0_rtx; + + RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx; + XEXP (mem_rtx, 0) = offset_rtx; + return; + } + + if (base_rtx && GET_CODE (base_rtx) == PLUS + && GET_CODE (XEXP (base_rtx, 0)) == REG + && GET_CODE (XEXP (base_rtx, 1)) == CONST_INT) + { + offset_adjust += INTVAL (XEXP (base_rtx, 1)); + base_rtx = copy_all_rtx (XEXP (base_rtx, 0)); + } + + else if (base_rtx && GET_CODE (base_rtx) == CONST_INT) + { + offset_adjust += INTVAL (base_rtx); + base_rtx = NULL; + } + + if (index_rtx && GET_CODE (index_rtx) == PLUS + && GET_CODE (XEXP (index_rtx, 0)) == REG + && GET_CODE (XEXP (index_rtx, 1)) == CONST_INT) + { + offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale; + index_rtx = copy_all_rtx (XEXP (index_rtx, 0)); + } + + if (index_rtx) + { + if (! LEGITIMATE_INDEX_P (index_rtx) + && ! (index_rtx == stack_pointer_rtx && scale == 1 + && base_rtx == NULL)) + { + obfree (storage); + return; + } + } + + if (base_rtx) + { + if (! LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG) + { + obfree (storage); + return; + } + } + + if (offset_adjust != 0) + { + if (offset_rtx != 0 && CONSTANT_P (offset_rtx)) + offset_rtx = plus_constant (offset_rtx, offset_adjust); + else + offset_rtx = const0_rtx; + + if (index_rtx) + { + if (base_rtx) + { + if (scale != 1) + { + ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), + gen_rtx (MULT, GET_MODE (index_rtx), + index_rtx, scale_rtx), + base_rtx); + + if (GET_CODE (offset_rtx) != CONST_INT + || INTVAL (offset_rtx) != 0) + ret_rtx = gen_rtx (PLUS, GET_MODE (ret_rtx), + ret_rtx, offset_rtx); + } + else + { + ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), + index_rtx, base_rtx); + + if (GET_CODE (offset_rtx) != CONST_INT + || INTVAL (offset_rtx) != 0) + ret_rtx = gen_rtx (PLUS, GET_MODE (ret_rtx), + ret_rtx, offset_rtx); + } + } + else + { + if (scale != 1) + { + ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), + index_rtx, scale_rtx); + + if (GET_CODE (offset_rtx) != CONST_INT + || INTVAL (offset_rtx) != 0) + ret_rtx = gen_rtx (PLUS, GET_MODE (ret_rtx), + ret_rtx, offset_rtx); + } + else + { + if (GET_CODE (offset_rtx) == CONST_INT + && INTVAL (offset_rtx) == 0) + ret_rtx = index_rtx; + else + ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), + index_rtx, offset_rtx); + } + } + } + else + { + if (base_rtx) + { + if (GET_CODE (offset_rtx) == CONST_INT + && INTVAL (offset_rtx) == 0) + ret_rtx = base_rtx; + else + ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, + offset_rtx); + } + else if (was_only_offset) + ret_rtx = offset_rtx; + else + { + obfree (storage); + return; + } + } + + XEXP (mem_rtx, 0) = ret_rtx; + RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx; + return; + } + else + { + obfree (storage); + return; + } +} +#endif /* NOTYET */ + +/* Return 1 if the first insn to set cc before INSN also sets the register + REG_RTX; otherwise return 0. */ +int +last_to_set_cc (reg_rtx, insn) + rtx reg_rtx, insn; +{ + rtx prev_insn = PREV_INSN (insn); + + while (prev_insn) + { + if (GET_CODE (prev_insn) == NOTE) + ; + + else if (GET_CODE (prev_insn) == INSN) + { + if (GET_CODE (PATTERN (prev_insn)) != SET) + return (0); + + if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx)) + { + if (sets_condition_code (SET_SRC (PATTERN (prev_insn)))) + return (1); + + return (0); + } + + else if (! doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn)))) + return (0); + } + + else + return (0); + + prev_insn = PREV_INSN (prev_insn); + } + + return (0); +} + +int +doesnt_set_condition_code (pat) + rtx pat; +{ + switch (GET_CODE (pat)) + { + case MEM: + case REG: + return 1; + + default: + return 0; + + } +} + +int +sets_condition_code (pat) + rtx pat; +{ + switch (GET_CODE (pat)) + { + case PLUS: + case MINUS: + case AND: + case IOR: + case XOR: + case NOT: + case NEG: + case MULT: + case DIV: + case MOD: + case UDIV: + case UMOD: + return 1; + + default: + return (0); + } +} + +int +str_immediate_operand (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0) + return 1; + + return 0; +} + +int +is_fp_insn (insn) + rtx insn; +{ + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET + && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)) + return 1; + + return 0; +} + +/* Return 1 if the mode of the SET_DEST of insn is floating point + and it is not an fld or a move from memory to memory. + Otherwise return 0 */ + +int +is_fp_dest (insn) + rtx insn; +{ + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET + && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode) + && GET_CODE (SET_DEST (PATTERN (insn))) == REG + && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG + && GET_CODE (SET_SRC (PATTERN (insn))) != MEM) + return 1; + + return 0; +} + +/* Return 1 if the mode of the SET_DEST of INSN is floating point and is + memory and the source is a register. */ + +int +is_fp_store (insn) + rtx insn; +{ + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET + && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode) + && GET_CODE (SET_DEST (PATTERN (insn))) == MEM + && GET_CODE (SET_SRC (PATTERN (insn))) == REG) + return 1; + + return 0; +} + +/* Return 1 if DEP_INSN sets a register which INSN uses as a base + or index to reference memory. + otherwise return 0 */ + +int +agi_dependent (insn, dep_insn) + rtx insn, dep_insn; +{ + 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); + + 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); + + return 0; +} + +/* Return 1 if reg is used in rtl as a base or index for a memory ref + otherwise return 0. */ + +int +reg_mentioned_in_mem (reg, rtl) + rtx reg, rtl; +{ + register char *fmt; + register int i, j; + register enum rtx_code code; + + if (rtl == NULL) + return 0; + + code = GET_CODE (rtl); + + switch (code) + { + case HIGH: + case CONST_INT: + case CONST: + case CONST_DOUBLE: + case SYMBOL_REF: + case LABEL_REF: + case PC: + case CC0: + case SUBREG: + return 0; + default: + break; + } + + if (code == MEM && reg_mentioned_p (reg, rtl)) + return 1; + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'E') + { + for (j = XVECLEN (rtl, i) - 1; j >= 0; j--) + if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j))) + return 1; + } + + else if (fmt[i] == 'e' && reg_mentioned_in_mem (reg, XEXP (rtl, i))) + return 1; + } + + return 0; +} + +/* Output the appropriate insns for doing strlen if not just doing repnz; scasb + + operands[0] = result, initialized with the startaddress + operands[1] = alignment of the address. + operands[2] = scratch register, initialized with the startaddress when + not aligned, otherwise undefined + + This is just the body. It needs the initialisations mentioned above and + some address computing at the end. These things are done in i386.md. */ + +char * +output_strlen_unroll (operands) + rtx operands[]; +{ + rtx xops[18]; + + xops[0] = operands[0]; /* Result */ + /* operands[1]; * Alignment */ + xops[1] = operands[2]; /* Scratch */ + xops[2] = GEN_INT (0); + xops[3] = GEN_INT (2); + xops[4] = GEN_INT (3); + xops[5] = GEN_INT (4); + /* xops[6] = gen_label_rtx (); * label when aligned to 3-byte */ + /* xops[7] = gen_label_rtx (); * label when aligned to 2-byte */ + xops[8] = gen_label_rtx (); /* label of main loop */ + + if (TARGET_USE_Q_REG && QI_REG_P (xops[1])) + xops[9] = gen_label_rtx (); /* pentium optimisation */ + + xops[10] = gen_label_rtx (); /* end label 2 */ + xops[11] = gen_label_rtx (); /* end label 1 */ + xops[12] = gen_label_rtx (); /* end label */ + /* xops[13] * Temporary used */ + xops[14] = GEN_INT (0xff); + xops[15] = GEN_INT (0xff00); + xops[16] = GEN_INT (0xff0000); + xops[17] = GEN_INT (0xff000000); + + /* Loop to check 1..3 bytes for null to get an aligned pointer. */ + + /* Is there a known alignment and is it less than 4? */ + if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) < 4) + { + /* Is there a known alignment and is it not 2? */ + if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2) + { + xops[6] = gen_label_rtx (); /* Label when aligned to 3-byte */ + xops[7] = gen_label_rtx (); /* Label when aligned to 2-byte */ + + /* Leave just the 3 lower bits. + If this is a q-register, then the high part is used later + therefore use andl rather than andb. */ + output_asm_insn (AS2 (and%L1,%4,%1), xops); + + /* Is aligned to 4-byte address when zero */ + output_asm_insn (AS1 (je,%l8), xops); + + /* Side-effect even Parity when %eax == 3 */ + output_asm_insn (AS1 (jp,%6), xops); + + /* Is it aligned to 2 bytes ? */ + if (QI_REG_P (xops[1])) + output_asm_insn (AS2 (cmp%L1,%3,%1), xops); + else + output_asm_insn (AS2 (cmp%L1,%3,%1), xops); + + output_asm_insn (AS1 (je,%7), xops); + } + else + { + /* Since the alignment is 2, we have to check 2 or 0 bytes; + check if is aligned to 4 - byte. */ + output_asm_insn (AS2 (and%L1,%3,%1), xops); + + /* Is aligned to 4-byte address when zero */ + output_asm_insn (AS1 (je,%l8), xops); + } + + xops[13] = gen_rtx_MEM (QImode, xops[0]); + + /* Now compare the bytes; compare with the high part of a q-reg + gives shorter code. */ + if (QI_REG_P (xops[1])) + { + /* Compare the first n unaligned byte on a byte per byte basis. */ + output_asm_insn (AS2 (cmp%B1,%h1,%13), xops); + + /* When zero we reached the end. */ + output_asm_insn (AS1 (je,%l12), xops); + + /* Increment the address. */ + output_asm_insn (AS1 (inc%L0,%0), xops); + + /* Not needed with an alignment of 2 */ + if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2) + { + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[7])); + output_asm_insn (AS2 (cmp%B1,%h1,%13), xops); + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[6])); + } + + output_asm_insn (AS2 (cmp%B1,%h1,%13), xops); + } + else + { + output_asm_insn (AS2 (cmp%B13,%2,%13), xops); + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[7])); + output_asm_insn (AS2 (cmp%B13,%2,%13), xops); + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[6])); + output_asm_insn (AS2 (cmp%B13,%2,%13), xops); + } + + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + } + + /* Generate loop to check 4 bytes at a time. It is not a good idea to + align this loop. It gives only huge programs, but does not help to + speed up. */ + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[8])); + + xops[13] = gen_rtx_MEM (SImode, xops[0]); + output_asm_insn (AS2 (mov%L1,%13,%1), xops); + + if (QI_REG_P (xops[1])) + { + /* On i586 it is faster to combine the hi- and lo- part as + a kind of lookahead. If anding both yields zero, then one + of both *could* be zero, otherwise none of both is zero; + this saves one instruction, on i486 this is slower + tested with P-90, i486DX2-66, AMD486DX2-66 */ + if (TARGET_PENTIUM) + { + output_asm_insn (AS2 (test%B1,%h1,%b1), xops); + output_asm_insn (AS1 (jne,%l9), xops); + } + + /* Check first byte. */ + output_asm_insn (AS2 (test%B1,%b1,%b1), xops); + output_asm_insn (AS1 (je,%l12), xops); + + /* Check second byte. */ + output_asm_insn (AS2 (test%B1,%h1,%h1), xops); + output_asm_insn (AS1 (je,%l11), xops); + + if (TARGET_PENTIUM) + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[9])); + } + + else + { + /* Check first byte. */ + output_asm_insn (AS2 (test%L1,%14,%1), xops); + output_asm_insn (AS1 (je,%l12), xops); + + /* Check second byte. */ + output_asm_insn (AS2 (test%L1,%15,%1), xops); + output_asm_insn (AS1 (je,%l11), xops); + } + + /* Check third byte. */ + output_asm_insn (AS2 (test%L1,%16,%1), xops); + output_asm_insn (AS1 (je,%l10), xops); + + /* Check fourth byte and increment address. */ + output_asm_insn (AS2 (add%L0,%5,%0), xops); + output_asm_insn (AS2 (test%L1,%17,%1), xops); + output_asm_insn (AS1 (jne,%l8), xops); + + /* Now generate fixups when the compare stops within a 4-byte word. */ + output_asm_insn (AS2 (sub%L0,%4,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[10])); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[11])); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12])); + + return ""; +} + +char * +output_fp_conditional_move (which_alternative, operands) + int which_alternative; + rtx operands[]; +{ + switch (which_alternative) + { + case 0: + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + break; + + case 1: + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + break; + + default: + abort (); + } + + return ""; +} + +char * +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]; + + /* This is very tricky. We have to do it right. For a code segement + like: + + int foo, bar; + .... + foo = foo - x; + if (foo >= 0) + bar = y; + + final_scan_insn () may delete the insn which sets CC. We have to + tell final_scan_insn () if it should be reinserted. When CODE is + GT or LE, we have to check the CC_NO_OVERFLOW bit and return + NULL_PTR to tell final to reinsert the test insn because the + conditional move cannot be handled properly without it. */ + if ((code == GT || code == LE) + && (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: + abort (); + } + + return ""; +} diff --git a/contrib/gcc/config/i386/i386.h b/contrib/gcc/config/i386/i386.h index b00b0e5..b8fef11 100644 --- a/contrib/gcc/config/i386/i386.h +++ b/contrib/gcc/config/i386/i386.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler for Intel X86 (386, 486, Pentium). - Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -17,8 +17,7 @@ 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. */ - +Boston, MA 02111-1307, USA. */ /* The purpose of this file is to define the characteristics of the i386, independent of assembler syntax or operating system. @@ -53,6 +52,20 @@ Boston, MA 02111-1307, USA. */ #define HALF_PIC_FINISH(STREAM) #endif +/* Define the specific costs for a given cpu */ + +struct processor_costs { + int add; /* cost of an add instruction */ + int lea; /* cost of a lea instruction */ + int shift_var; /* variable shift costs */ + int shift_const; /* constant shift costs */ + int mult_init; /* cost of starting a multiply */ + int mult_bit; /* cost of multiply per each bit set */ + int divide; /* cost of a divide/mod */ +}; + +extern struct processor_costs *ix86_cost; + /* Run-time compilation parameters selecting different hardware subsets. */ extern int target_flags; @@ -66,20 +79,23 @@ extern int target_flags; /* Masks for the -m switches */ #define MASK_80387 000000000001 /* Hardware floating point */ -#define MASK_486 000000000002 /* 80486 specific */ -#define MASK_NOTUSED1 000000000004 /* bit not currently used */ +#define MASK_NOTUSED1 000000000002 /* bit not currently used */ +#define MASK_NOTUSED2 000000000004 /* bit not currently used */ #define MASK_RTD 000000000010 /* Use ret that pops args */ #define MASK_ALIGN_DOUBLE 000000000020 /* align doubles to 2 word boundary */ #define MASK_SVR3_SHLIB 000000000040 /* Uninit locals into bss */ #define MASK_IEEE_FP 000000000100 /* IEEE fp comparisons */ #define MASK_FLOAT_RETURNS 000000000200 /* Return float in st(0) */ #define MASK_NO_FANCY_MATH_387 000000000400 /* Disable sin, cos, sqrt */ - +#define MASK_OMIT_LEAF_FRAME_POINTER 0x00000800 /* omit leaf frame pointers */ /* Temporary codegen switches */ #define MASK_DEBUG_ADDR 000001000000 /* Debug GO_IF_LEGITIMATE_ADDRESS */ #define MASK_NO_WIDE_MULTIPLY 000002000000 /* Disable 32x32->64 multiplies */ #define MASK_NO_MOVE 000004000000 /* Don't generate mem->mem */ -#define MASK_DEBUG_ARG 000010000000 /* Debug function_arg */ +#define MASK_NO_PSEUDO 000010000000 /* Move op's args -> pseudos */ +#define MASK_DEBUG_ARG 000020000000 /* Debug function_arg */ +#define MASK_SCHEDULE_PROLOGUE 000040000000 /* Emit prologue as rtl */ +#define MASK_STACK_PROBE 000100000000 /* Enable stack probing */ /* Use the floating point instructions */ #define TARGET_80387 (target_flags & MASK_80387) @@ -112,6 +128,9 @@ extern int target_flags; This is because FreeBSD lacks these in the math-emulator-code */ #define TARGET_NO_FANCY_MATH_387 (target_flags & MASK_NO_FANCY_MATH_387) +/* Don't create frame pointers for leaf functions */ +#define TARGET_OMIT_LEAF_FRAME_POINTER (target_flags & MASK_OMIT_LEAF_FRAME_POINTER) + /* Temporary switches for tuning code generation */ /* Disable 32x32->64 bit multiplies that are used for long long multiplies @@ -119,6 +138,9 @@ extern int target_flags; #define TARGET_NO_WIDE_MULTIPLY (target_flags & MASK_NO_WIDE_MULTIPLY) #define TARGET_WIDE_MULTIPLY (!TARGET_NO_WIDE_MULTIPLY) +/* Emit/Don't emit prologue as rtl */ +#define TARGET_SCHEDULE_PROLOGUE (target_flags & MASK_SCHEDULE_PROLOGUE) + /* Debug GO_IF_LEGITIMATE_ADDRESS */ #define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR) @@ -127,10 +149,25 @@ extern int target_flags; /* Hack macros for tuning code generation */ #define TARGET_MOVE ((target_flags & MASK_NO_MOVE) == 0) /* Don't generate memory->memory */ - -/* Specific hardware switches */ -#define TARGET_486 (target_flags & MASK_486) /* 80486DX, 80486SX, 80486DX[24] */ -#define TARGET_386 (!TARGET_486) /* 80386 */ +#define TARGET_PSEUDO ((target_flags & MASK_NO_PSEUDO) == 0) /* Move op's args into pseudos */ + +#define TARGET_386 (ix86_cpu == PROCESSOR_I386) +#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_STACK_PROBE (target_flags & MASK_STACK_PROBE) #define TARGET_SWITCHES \ { { "80387", MASK_80387 }, \ @@ -138,10 +175,12 @@ extern int target_flags; { "hard-float", MASK_80387 }, \ { "soft-float", -MASK_80387 }, \ { "no-soft-float", MASK_80387 }, \ - { "386", -MASK_486 }, \ - { "no-386", MASK_486 }, \ - { "486", MASK_486 }, \ - { "no-486", -MASK_486 }, \ + { "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 }, \ @@ -154,16 +193,62 @@ extern int target_flags; { "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 }, \ SUBTARGET_SWITCHES \ - { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} + { "", MASK_SCHEDULE_PROLOGUE | TARGET_DEFAULT}} + +/* 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. */ + +enum processor_type + {PROCESSOR_I386, /* 80386 */ + PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */ + PROCESSOR_PENTIUM, + PROCESSOR_PENTIUMPRO}; + +#define PROCESSOR_I386_STRING "i386" +#define PROCESSOR_I486_STRING "i486" +#define PROCESSOR_I586_STRING "i586" +#define PROCESSOR_PENTIUM_STRING "pentium" +#define PROCESSOR_I686_STRING "i686" +#define PROCESSOR_PENTIUMPRO_STRING "pentiumpro" + +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_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 /* This macro is similar to `TARGET_SWITCHES' but defines names of command options that have values. Its definition is an @@ -175,11 +260,14 @@ extern int target_flags; option if the fixed part matches. The actual option name is made by appending `-m' to the specified name. */ #define TARGET_OPTIONS \ -{ { "reg-alloc=", &i386_reg_alloc_order }, \ +{ { "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 }, \ SUBTARGET_OPTIONS \ } @@ -198,6 +286,82 @@ extern int target_flags; #define SUBTARGET_SWITCHES #define SUBTARGET_OPTIONS +/* Define this to change the optimizations performed by default. */ +#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) optimization_options(LEVEL,SIZE) + +/* Specs for the compiler proper */ + +#ifndef CC1_CPU_SPEC +#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_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 +#if TARGET_CPU_DEFAULT == 2 +#define CPP_CPU_DEFAULT_SPEC "%(cpp_586)" +#else +#if TARGET_CPU_DEFAULT == 3 +#define CPP_CPU_DEFAULT_SPEC "%(cpp_686)" +#else +#define CPP_CPU_DEFAULT_SPEC "" +#endif +#endif +#endif +#endif /* CPP_CPU_DEFAULT_SPEC */ + +#ifndef CPP_CPU_SPEC +#define CPP_CPU_SPEC "\ +-Asystem(unix) -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*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}" +#endif + +#ifndef CC1_SPEC +#define CC1_SPEC "%(cc1_spec) " +#endif + +/* 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. */ + +#ifndef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS +#endif + +#define EXTRA_SPECS \ + { "cpp_486", CPP_486_SPEC}, \ + { "cpp_586", CPP_586_SPEC}, \ + { "cpp_686", CPP_686_SPEC}, \ + { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \ + { "cpp_cpu", CPP_CPU_SPEC }, \ + { "cc1_cpu", CC1_CPU_SPEC }, \ + SUBTARGET_EXTRA_SPECS /* target machine storage layout */ @@ -265,6 +429,79 @@ extern int target_flags; aligned on 64 bit boundaries. */ #define BIGGEST_ALIGNMENT (TARGET_ALIGN_DOUBLE ? 64 : 32) +/* If defined, a C expression to compute the alignment given to a + constant that is being placed in memory. CONSTANT is the constant + 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. + + The typical use of this macro is to increase alignment for string + constants to be word aligned so that `strcpy' calls that copy + constants can be done inline. */ + +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + (TREE_CODE (EXP) == REAL_CST \ + ? ((TYPE_MODE (TREE_TYPE (EXP)) == DFmode && (ALIGN) < 64) \ + ? 64 \ + : (TYPE_MODE (TREE_TYPE (EXP)) == XFmode && (ALIGN) < 128) \ + ? 128 \ + : (ALIGN)) \ + : TREE_CODE (EXP) == STRING_CST \ + ? ((TREE_STRING_LENGTH (EXP) >= 31 && (ALIGN) < 256) \ + ? 256 \ + : (ALIGN)) \ + : (ALIGN)) + +/* If defined, a C expression to compute the alignment for a static + 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. Another is to + cause character arrays to be word-aligned so that `strcpy' calls + that copy constants to character arrays can be done inline. */ + +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ((AGGREGATE_TYPE_P (TYPE) \ + && TYPE_SIZE (TYPE) \ + && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && (TREE_INT_CST_LOW (TYPE_SIZE (TYPE)) >= 256 \ + || TREE_INT_CST_HIGH (TYPE_SIZE (TYPE))) && (ALIGN) < 256) \ + ? 256 \ + : 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 @@ -278,12 +515,14 @@ extern int target_flags; #define MAX_CODE_ALIGN 6 /* 64 byte alignment */ /* Align loop starts for optimal branching. */ -#define ASM_OUTPUT_LOOP_ALIGN(FILE) ASM_OUTPUT_ALIGN (FILE, i386_align_loops) +#define LOOP_ALIGN(LABEL) (i386_align_loops) +#define LOOP_ALIGN_MAX_SKIP (i386_align_loops_string ? 0 : 7) /* This is how to align an instruction for optimal branching. On i486 we'll get better performance by aligning on a cache line (i.e. 16 byte) boundary. */ -#define ASM_OUTPUT_ALIGN_CODE(FILE) ASM_OUTPUT_ALIGN ((FILE), i386_align_jumps) +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps) +#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (i386_align_jumps_string ? 0 : 7) /* Standard register usage. */ @@ -292,6 +531,7 @@ extern int target_flags; for details. */ #define STACK_REGS +#define IS_STACK_MODE(mode) (mode==DFmode || mode==SFmode || mode==XFmode) /* Number of actual hardware registers. The hardware registers are assigned numbers for the compiler @@ -409,31 +649,23 @@ extern int target_flags; for cross-compiler testing. */ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ - ((REGNO) < 2 ? 1 \ - : (REGNO) < 4 ? 1 \ + ((REGNO) < 4 ? 1 \ : FP_REGNO_P (REGNO) \ ? (((int) GET_MODE_CLASS (MODE) == (int) MODE_FLOAT \ || (int) GET_MODE_CLASS (MODE) == (int) MODE_COMPLEX_FLOAT) \ - && GET_MODE_UNIT_SIZE (MODE) <= 12) \ - : (int) (MODE) != (int) QImode) + && GET_MODE_UNIT_SIZE (MODE) <= (LONG_DOUBLE_TYPE_SIZE == 96 ? 12 : 8))\ + : (int) (MODE) != (int) QImode ? 1 \ + : (reload_in_progress | reload_completed) == 1) /* 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. */ -#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) == (MODE2)) - -/* A C expression returning the cost of moving data from a register of class - CLASS1 to one of CLASS2. - - On the i386, copying between floating-point and fixed-point - registers is expensive. */ - -#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ - (((FLOAT_CLASS_P (CLASS1) && ! FLOAT_CLASS_P (CLASS2)) \ - || (! FLOAT_CLASS_P (CLASS1) && FLOAT_CLASS_P (CLASS2))) ? 10 \ - : 2) +#define MODES_TIEABLE_P(MODE1, MODE2) \ + ((MODE1) == (MODE2) \ + || ((MODE1) == SImode && (MODE2) == HImode \ + || (MODE1) == HImode && (MODE2) == SImode)) /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -459,7 +691,7 @@ extern int target_flags; Zero means the frame pointer need not be set up (and parms may be accessed via the stack pointer) in functions that seem suitable. This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 +#define FRAME_POINTER_REQUIRED (TARGET_OMIT_LEAF_FRAME_POINTER && !leaf_function_p ()) /* Base register for access to arguments of the function. */ #define ARG_POINTER_REGNUM 16 @@ -562,16 +794,16 @@ enum reg_class of length N_REG_CLASSES. */ #define REG_CLASS_CONTENTS \ -{ 0, \ - 0x1, 0x2, 0x4, 0x8, /* AREG, DREG, CREG, BREG */ \ - 0x3, /* AD_REGS */ \ - 0xf, /* Q_REGS */ \ - 0x10, 0x20, /* SIREG, DIREG */ \ - 0x07f, /* INDEX_REGS */ \ - 0x100ff, /* GENERAL_REGS */ \ - 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \ - 0xff00, /* FLOAT_REGS */ \ - 0x1ffff } +{ {0}, \ + {0x1}, {0x2}, {0x4}, {0x8}, /* AREG, DREG, CREG, BREG */ \ + {0x3}, /* AD_REGS */ \ + {0xf}, /* Q_REGS */ \ + {0x10}, {0x20}, /* SIREG, DIREG */ \ + {0x7f}, /* INDEX_REGS */ \ + {0x100ff}, /* GENERAL_REGS */ \ + {0x0100}, {0x0200}, /* FP_TOP_REG, FP_SECOND_REG */ \ + {0xff00}, /* FLOAT_REGS */ \ + {0x1ffff}} /* The same information, inverted: Return the class number of the smallest class containing @@ -584,7 +816,7 @@ enum reg_class rtl to be used as spill registers but prevents the compiler from extending the lifetime of these registers. */ -#define SMALL_REGISTER_CLASSES +#define SMALL_REGISTER_CLASSES 1 #define QI_REG_P(X) \ (REG_P (X) && REGNO (X) < 4) @@ -658,15 +890,25 @@ enum reg_class (C) == 'L' ? (VALUE) == 0xffff : \ (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 3 : \ (C) == 'N' ? (VALUE) >= 0 && (VALUE) <= 255 :\ + (C) == 'O' ? (VALUE) >= 0 && (VALUE) <= 32 : \ 0) /* 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. */ + 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. */ #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? standard_80387_constant_p (VALUE) : 0) + (((reload_completed || !flag_pic || !flag_omit_frame_pointer) && (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 @@ -791,14 +1033,14 @@ enum reg_class If the precise function being called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), \ + gen_rtx_REG (TYPE_MODE (VALTYPE), \ VALUE_REGNO (TYPE_MODE (VALTYPE))) /* 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, VALUE_REGNO (MODE)) + gen_rtx_REG (MODE, VALUE_REGNO (MODE)) /* Define the size of the result block used for communication between untyped_call and untyped_return. The block contains a DImode value @@ -825,7 +1067,7 @@ typedef struct i386_args { for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \ +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ (init_cumulative_args (&CUM, FNTYPE, LIBNAME)) /* Update the data in CUM to advance over an argument @@ -858,6 +1100,14 @@ typedef struct i386_args { #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)) +/* This macro is invoked just before the start of a function. + It is used here to output code for -fpic that will load the + return address into %ebx. */ + +#undef ASM_OUTPUT_FUNCTION_PREFIX +#define ASM_OUTPUT_FUNCTION_PREFIX(FILE, FNNAME) \ + asm_output_function_prefix (FILE, FNNAME) + /* This macro generates the assembly code for function entry. FILE is a stdio stream to output the code to. SIZE is an int: how many units of temporary storage to allocate. @@ -887,27 +1137,94 @@ typedef struct i386_args { } \ } -/* A C statement or compound statement to output to FILE some - assembler code to initialize basic-block profiling for the current - object module. This code should call the subroutine - `__bb_init_func' once per object module, passing it as its sole - argument the address of a block allocated in the object module. - The name of the block is a local symbol made with this statement: +/* 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. + + profile_block_flag == 0, no option used: + + No profiling done. + + 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'. + +*/ + +/* 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'. - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + 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. - 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. + BLOCK_OR_LABEL may be used to generate a label number as a + branch destination in case `__bb_init_func' will not be called. - The first word of this block is a flag which will be nonzero if the - object module has already been initialized. So test this word - first, and do not call `__bb_init_func' if the flag is nonzero. */ + 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: + +*/ #undef FUNCTION_BLOCK_PROFILER -#define FUNCTION_BLOCK_PROFILER(STREAM, LABELNO) \ +#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \ do \ { \ static int num_func = 0; \ @@ -915,74 +1232,264 @@ do \ char block_table[80], false_label[80]; \ \ ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \ - ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \ \ - xops[0] = const0_rtx; \ - xops[1] = gen_rtx (SYMBOL_REF, VOIDmode, block_table); \ - xops[2] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, false_label)); \ - xops[3] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, "__bb_init_func")); \ - xops[4] = gen_rtx (MEM, Pmode, xops[1]); \ + xops[1] = gen_rtx_SYMBOL_REF (VOIDmode, block_table); \ xops[5] = stack_pointer_rtx; \ - xops[6] = GEN_INT (4); \ - xops[7] = gen_rtx (REG, Pmode, 0); /* eax */ \ + xops[7] = gen_rtx_REG (Pmode, 0); /* eax */ \ \ CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \ - CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \ - \ - output_asm_insn (AS2(cmp%L4,%0,%4), xops); \ - output_asm_insn (AS1(jne,%2), xops); \ \ - if (!flag_pic) \ - output_asm_insn (AS1(push%L1,%1), xops); \ - else \ + switch (profile_block_flag) \ { \ - output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ - output_asm_insn (AS1 (push%L7,%7), xops); \ - } \ \ - output_asm_insn (AS1(call,%P3), xops); \ - output_asm_insn (AS2(add%L0,%6,%5), xops); \ - ASM_OUTPUT_INTERNAL_LABEL (STREAM, "LPBZ", num_func); \ - num_func++; \ + case 2: \ + \ + xops[2] = GEN_INT ((BLOCK_OR_LABEL)); \ + xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_init_trace_func")); \ + xops[6] = GEN_INT (8); \ + \ + output_asm_insn (AS1(push%L2,%2), xops); \ + if (!flag_pic) \ + output_asm_insn (AS1(push%L1,%1), xops); \ + else \ + { \ + output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ + output_asm_insn (AS1 (push%L7,%7), xops); \ + } \ + \ + output_asm_insn (AS1(call,%P3), xops); \ + output_asm_insn (AS2(add%L0,%6,%5), xops); \ + \ + break; \ + \ + default: \ + \ + ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \ + \ + xops[0] = const0_rtx; \ + xops[2] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, false_label)); \ + xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_init_func")); \ + xops[4] = gen_rtx_MEM (Pmode, xops[1]); \ + xops[6] = GEN_INT (4); \ + \ + CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \ + \ + output_asm_insn (AS2(cmp%L4,%0,%4), xops); \ + output_asm_insn (AS1(jne,%2), xops); \ + \ + if (!flag_pic) \ + output_asm_insn (AS1(push%L1,%1), xops); \ + else \ + { \ + output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ + output_asm_insn (AS1 (push%L7,%7), xops); \ + } \ + \ + output_asm_insn (AS1(call,%P3), xops); \ + output_asm_insn (AS2(add%L0,%6,%5), xops); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, "LPBZ", num_func); \ + num_func++; \ + \ + break; \ + \ + } \ } \ while (0) +/* 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. -/* A C statement or compound statement to increment the count - associated with the basic block number BLOCKNO. Basic blocks are - numbered separately from zero within each compilation. The count - associated with block number BLOCKNO is at index BLOCKNO in a - vector of words; the name of this array is a local symbol made - with this statement: + `__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. - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); + The basic block number is given by BLOCKNO. - 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 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(STREAM, BLOCKNO) \ +#define BLOCK_PROFILER(FILE, BLOCKNO) \ do \ { \ - rtx xops[1], cnt_rtx; \ + rtx xops[8], cnt_rtx; \ char counts[80]; \ + char *block_table = counts; \ \ - ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \ - cnt_rtx = gen_rtx (SYMBOL_REF, VOIDmode, counts); \ - SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \ + switch (profile_block_flag) \ + { \ \ - if (BLOCKNO) \ - cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \ + case 2: \ \ - if (flag_pic) \ - cnt_rtx = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, cnt_rtx); \ + ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \ + \ + xops[1] = gen_rtx_SYMBOL_REF (VOIDmode, block_table); \ + xops[2] = GEN_INT ((BLOCKNO)); \ + xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_trace_func")); \ + xops[4] = gen_rtx_SYMBOL_REF (VOIDmode, "__bb"); \ + xops[5] = plus_constant (xops[4], 4); \ + xops[0] = gen_rtx_MEM (SImode, xops[4]); \ + xops[6] = gen_rtx_MEM (SImode, xops[5]); \ + \ + CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \ + \ + fprintf(FILE, "\tpushf\n"); \ + output_asm_insn (AS2(mov%L0,%2,%0), xops); \ + if (flag_pic) \ + { \ + xops[7] = gen_rtx_REG (Pmode, 0); /* eax */ \ + output_asm_insn (AS1(push%L7,%7), xops); \ + output_asm_insn (AS2(lea%L7,%a1,%7), xops); \ + output_asm_insn (AS2(mov%L6,%7,%6), xops); \ + output_asm_insn (AS1(pop%L7,%7), xops); \ + } \ + else \ + output_asm_insn (AS2(mov%L6,%1,%6), xops); \ + output_asm_insn (AS1(call,%P3), xops); \ + fprintf(FILE, "\tpopf\n"); \ + \ + break; \ + \ + default: \ + \ + ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \ + cnt_rtx = gen_rtx_SYMBOL_REF (VOIDmode, counts); \ + SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \ \ - xops[0] = gen_rtx (MEM, SImode, cnt_rtx); \ - output_asm_insn (AS1(inc%L0,%0), xops); \ + if (BLOCKNO) \ + cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \ + \ + if (flag_pic) \ + cnt_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, cnt_rtx); \ + \ + xops[0] = gen_rtx_MEM (SImode, cnt_rtx); \ + output_asm_insn (AS1(inc%L0,%0), xops); \ + \ + break; \ + \ + } \ } \ while (0) +/* 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. +*/ + +#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \ +do \ + { \ + rtx xops[1]; \ + \ + xops[0] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_trace_ret")); \ + \ + output_asm_insn (AS1(call,%P0), xops); \ + \ + } \ +while (0) + +/* The function `__bb_trace_func' is called in every basic block + and is not allowed to change the machine state. Saving (restoring) + the state can either be done in the BLOCK_PROFILER macro, + before calling function (rsp. after returning from function) + `__bb_trace_func', or it can be done inside the function by + defining the macros: + + MACHINE_STATE_SAVE(ID) + MACHINE_STATE_RESTORE(ID) + + In the latter case care must be taken, that the prologue code + of function `__bb_trace_func' does not already change the + state prior to saving it with MACHINE_STATE_SAVE. + + The parameter `ID' is a string identifying a unique macro use. + + On the i386 the initialization code at the begin of + function `__bb_trace_func' contains a `sub' instruction + therefore we handle save and restore of the flag register + in the BLOCK_PROFILER macro. */ + +#define MACHINE_STATE_SAVE(ID) \ + asm (" pushl %eax"); \ + asm (" pushl %ecx"); \ + asm (" pushl %edx"); \ + asm (" pushl %esi"); + +#define MACHINE_STATE_RESTORE(ID) \ + asm (" popl %esi"); \ + asm (" popl %edx"); \ + asm (" popl %ecx"); \ + asm (" popl %eax"); + /* 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. @@ -1008,14 +1515,19 @@ while (0) off the end. This happens if the function ends in an "exit" call, or if a `return' insn is emitted directly into the function. */ -#define FUNCTION_EPILOGUE(FILE, SIZE) \ +#if 0 +#define FUNCTION_BEGIN_EPILOGUE(FILE) \ do { \ rtx last = get_last_insn (); \ if (last && GET_CODE (last) == NOTE) \ last = prev_nonnote_insn (last); \ - if (! last || GET_CODE (last) != BARRIER) \ - function_epilogue (FILE, SIZE); \ +/* if (! last || GET_CODE (last) != BARRIER) \ + function_epilogue (FILE, SIZE);*/ \ } while (0) +#endif + +#define FUNCTION_EPILOGUE(FILE, SIZE) \ + function_epilogue (FILE, SIZE) /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. */ @@ -1046,8 +1558,8 @@ do { \ #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ { \ - 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 (SImode, plus_constant (TRAMP, 1)), CXT); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), FNADDR); \ } /* Definitions for register eliminations. @@ -1094,8 +1606,9 @@ do { \ \ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ if ((regs_ever_live[regno] && ! call_used_regs[regno]) \ - || (current_function_uses_pic_offset_table \ - && regno == PIC_OFFSET_TABLE_REGNUM)) \ + || ((current_function_uses_pic_offset_table \ + || current_function_uses_const_pool) \ + && flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)) \ offset += 4; \ \ (OFFSET) = offset + get_frame_size (); \ @@ -1239,12 +1752,13 @@ do { \ #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ { \ - rtx orig_x = (X); \ (X) = legitimize_address (X, OLDX, MODE); \ if (memory_address_p (MODE, X)) \ goto WIN; \ } +#define REWRITE_ADDRESS(x) rewrite_address(x) + /* Nonzero if the constant value X is a legitimate general operand when generating PIC code. It is given that flag_pic is on and that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ @@ -1279,6 +1793,15 @@ do \ { \ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \ + \ + if (TARGET_DEBUG_ADDR \ + && TREE_CODE_CLASS (TREE_CODE (DECL)) == 'd') \ + { \ + fprintf (stderr, "Encode %s, public = %d\n", \ + IDENTIFIER_POINTER (DECL_NAME (DECL)), \ + TREE_PUBLIC (DECL)); \ + } \ + \ SYMBOL_REF_FLAG (XEXP (rtl, 0)) \ = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ || ! TREE_PUBLIC (DECL)); \ @@ -1349,10 +1872,11 @@ while (0) for the index in the tablejump instruction. */ #define CASE_VECTOR_MODE Pmode -/* Define this if the tablejump instruction expects the table - to contain offsets from the address of the table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE */ +/* Define as C expression which evaluates to nonzero if the tablejump + instruction expects the table to contain offsets from the address of the + table. + Do not define this if the table should contain absolute addresses. */ +/* #define CASE_VECTOR_PC_RELATIVE 1 */ /* Specify the tree operation to be used to convert reals to integers. This should be changed to take advantage of fist --wfs ?? @@ -1369,22 +1893,23 @@ while (0) in one reasonably fast instruction. */ #define MOVE_MAX 4 -/* MOVE_RATIO is the number of move instructions that is better than a - block move. Make this large on i386, since the block move is very - inefficient with small blocks, and the hard register needs of the - block move require much reload work. */ -#define MOVE_RATIO 5 +/* 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. -/* Define this if zero-extension is slow (more than one real instruction). */ -/* #define SLOW_ZERO_EXTEND */ + If you don't define this, a reasonable default is used. -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 + Make this large on i386, since the block move is very inefficient with small + blocks, and the hard register needs of the block move require much reload + work. */ + +#define MOVE_RATIO 5 /* Define if shifts truncate the shift count which implies one can omit a sign-extension or zero-extension of a shift count. */ -/* One i386, shifts do truncate the count. But bit opcodes don't. */ +/* On i386, shifts do truncate the count. But bit opcodes don't. */ /* #define SHIFT_COUNT_TRUNCATED */ @@ -1411,70 +1936,194 @@ while (0) is a byte address (for indexing purposes) so give the MEM rtx a byte's mode. */ #define FUNCTION_MODE QImode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on the 386 because a CALL with a constant address is - not much slower than one with a register address. On a 486, - it is faster to call with a constant address than indirect. */ -#define NO_FUNCTION_CSE - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. */ - -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MULT: \ - return COSTS_N_INSNS (20); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (20); \ - case ASHIFTRT: \ - case LSHIFTRT: \ - case ASHIFT: \ - return (4 + rtx_cost (XEXP (X, 0), OUTER_CODE) \ - + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ - case PLUS: \ - if (GET_CODE (XEXP (X, 0)) == MULT \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && (INTVAL (XEXP (XEXP (X, 0), 1)) == 2 \ - || INTVAL (XEXP (XEXP (X, 0), 1)) == 4 \ - || INTVAL (XEXP (XEXP (X, 0), 1)) == 8)) \ - return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \ - + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ - break; - - -/* 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, - return it with a return statement. Otherwise, break from the switch. */ + +/* A part of a C `switch' statement that describes the relative costs + of constant RTL expressions. It must contain `case' labels for + expression codes `const_int', `const', `symbol_ref', `label_ref' + and `const_double'. Each case must ultimately reach a `return' + statement to return the relative cost of the use of that kind of + constant value in an expression. The cost may depend on the + precise value of the constant, which is available for examination + in X, and the rtx code of the expression in which it is contained, + found in OUTER_CODE. + + CODE is the expression code--redundant, since it can be obtained + with `GET_CODE (X)'. */ #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ case CONST_INT: \ + return (unsigned) INTVAL (RTX) < 256 ? 0 : 1; \ case CONST: \ case LABEL_REF: \ case SYMBOL_REF: \ - return flag_pic && SYMBOLIC_CONST (RTX) ? 2 : 0; \ + return flag_pic && SYMBOLIC_CONST (RTX) ? 2 : 1; \ + \ case CONST_DOUBLE: \ { \ int code; \ if (GET_MODE (RTX) == VOIDmode) \ return 2; \ + \ code = standard_80387_constant_p (RTX); \ return code == 1 ? 0 : \ code == 2 ? 1 : \ 2; \ } -/* Compute the cost of an address. This is meant to approximate the size - and/or execution delay of an insn using that address. If the cost is - approximated by the RTL complexity, including CONST_COSTS above, as - is usually the case for CISC machines, this macro should not be defined. - For aggressively RISCy machines, only one insn format is allowed, so - this macro should be a constant. The value of this macro only matters - for valid addresses. +/* Delete the definition here when TOPLEVEL_COSTS_N_INSNS gets added to cse.c */ +#define TOPLEVEL_COSTS_N_INSNS(N) {total = COSTS_N_INSNS (N); break;} + +/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. + This can be used, for example, to indicate how costly a multiply + instruction is. In writing this macro, you can use the construct + `COSTS_N_INSNS (N)' to specify a cost equal to N fast + instructions. OUTER_CODE is the code of the expression in which X + is contained. + + This macro is optional; do not define it if the default cost + assumptions are adequate for the target machine. */ + +#define RTX_COSTS(X,CODE,OUTER_CODE) \ + case ASHIFT: \ + if (GET_CODE (XEXP (X, 1)) == CONST_INT \ + && GET_MODE (XEXP (X, 0)) == SImode) \ + { \ + HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \ + \ + if (value == 1) \ + return COSTS_N_INSNS (ix86_cost->add) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + if (value == 2 || value == 3) \ + return COSTS_N_INSNS (ix86_cost->lea) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + } \ + /* fall through */ \ + \ + case ROTATE: \ + case ASHIFTRT: \ + case LSHIFTRT: \ + case ROTATERT: \ + if (GET_MODE (XEXP (X, 0)) == DImode) \ + { \ + if (GET_CODE (XEXP (X, 1)) == CONST_INT) \ + { \ + if (INTVAL (XEXP (X, 1)) > 32) \ + return COSTS_N_INSNS(ix86_cost->shift_const + 2); \ + return COSTS_N_INSNS(ix86_cost->shift_const * 2); \ + } \ + return ((GET_CODE (XEXP (X, 1)) == AND \ + ? COSTS_N_INSNS(ix86_cost->shift_var * 2) \ + : COSTS_N_INSNS(ix86_cost->shift_var * 6 + 2)) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE)); \ + } \ + return COSTS_N_INSNS (GET_CODE (XEXP (X, 1)) == CONST_INT \ + ? ix86_cost->shift_const \ + : ix86_cost->shift_var) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + case MULT: \ + if (GET_CODE (XEXP (X, 1)) == CONST_INT) \ + { \ + unsigned HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \ + int nbits = 0; \ + \ + if (value == 2) \ + return COSTS_N_INSNS (ix86_cost->add) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + if (value == 4 || value == 8) \ + return COSTS_N_INSNS (ix86_cost->lea) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + while (value != 0) \ + { \ + nbits++; \ + value >>= 1; \ + } \ + \ + if (nbits == 1) \ + return COSTS_N_INSNS (ix86_cost->shift_const) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + return COSTS_N_INSNS (ix86_cost->mult_init \ + + nbits * ix86_cost->mult_bit) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + } \ + \ + else /* This is arbitrary */ \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \ + + 7 * ix86_cost->mult_bit); \ + \ + case DIV: \ + case UDIV: \ + case MOD: \ + case UMOD: \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->divide); \ + \ + case PLUS: \ + if (GET_CODE (XEXP (X, 0)) == REG \ + && GET_MODE (XEXP (X, 0)) == SImode \ + && GET_CODE (XEXP (X, 1)) == PLUS) \ + return COSTS_N_INSNS (ix86_cost->lea); \ + \ + /* fall through */ \ + case AND: \ + case IOR: \ + case XOR: \ + case MINUS: \ + if (GET_MODE (X) == DImode) \ + return COSTS_N_INSNS (ix86_cost->add) * 2 \ + + (rtx_cost (XEXP (X, 0), OUTER_CODE) \ + << (GET_MODE (XEXP (X, 0)) != DImode)) \ + + (rtx_cost (XEXP (X, 1), OUTER_CODE) \ + << (GET_MODE (XEXP (X, 1)) != DImode)); \ + case NEG: \ + case NOT: \ + if (GET_MODE (X) == DImode) \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2) \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->add) + + +/* An expression giving the cost of an addressing mode that contains + ADDRESS. If not defined, the cost is computed from the ADDRESS + expression and the `CONST_COSTS' values. + + For most CISC machines, the default cost is a good approximation + of the true cost of the addressing mode. However, on RISC + machines, all instructions normally have the same length and + execution time. Hence all addresses will have equal costs. + + In cases where more than one form of an address is known, the form + with the lowest cost will be used. If multiple forms have the + same, lowest, cost, the one that is the most complex will be used. + + For example, suppose an address that is equal to the sum of a + register and a constant is used twice in the same basic block. + When this macro is not defined, the address will be computed in a + register and memory references will be indirect through that + register. On machines where the cost of the addressing mode + containing the sum is no higher than that of a simple indirect + reference, this will produce an additional instruction and + possibly require an additional register. Proper specification of + this macro eliminates this overhead for such machines. + + Similar use of this macro is made in strength reduction of loops. + + ADDRESS need not be valid as an address. In such a case, the cost + is not relevant and can be any value; invalid addresses need not be + assigned a different cost. + + On machines where an address involving more than one register is as + cheap as an address computation involving only one register, + defining `ADDRESS_COST' to reflect this can cause two registers to + be live over a region of code where only one would have been if + `ADDRESS_COST' were not defined in that manner. This effect should + be considered in the definition of this macro. Equivalent costs + should probably only be given to addresses with different numbers + of registers on machines with lots of registers. + + This macro will normally either not be defined or be defined as a + constant. For i386, it is better to use a complex address than let gcc copy the address into a reg and make a new pseudo. But not if the address @@ -1487,6 +2136,193 @@ while (0) && REG_P (XEXP (RTX, 0)))) ? 0 \ : REG_P (RTX) ? 1 \ : 2) + +/* A C expression for the cost of moving data of mode M between a + register and memory. A value of 2 is the default; this cost is + relative to those in `REGISTER_MOVE_COST'. + + If moving between registers and memory is more expensive than + between two registers, you should define this macro to express the + relative cost. + + On the i386, copying between floating-point and fixed-point + registers is expensive. */ + +#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ + (((FLOAT_CLASS_P (CLASS1) && ! FLOAT_CLASS_P (CLASS2)) \ + || (! FLOAT_CLASS_P (CLASS1) && FLOAT_CLASS_P (CLASS2))) ? 10 \ + : 2) + + +/* A C expression for the cost of moving data of mode M between a + register and memory. A value of 2 is the default; this cost is + relative to those in `REGISTER_MOVE_COST'. + + If moving between registers and memory is more expensive than + between two registers, you should define this macro to express the + relative cost. */ + +/* #define MEMORY_MOVE_COST(M,C,I) 2 */ + +/* A C expression for the cost of a branch instruction. A value of 1 + is the default; other values are interpreted relative to that. */ + +#define BRANCH_COST i386_branch_cost + +/* Define this macro as a C expression which is nonzero if accessing + less than a word of memory (i.e. a `char' or a `short') is no + faster than accessing a word of memory, i.e., if such access + require more than one instruction or if there is no difference in + cost between byte and (aligned) word loads. + + When this macro is not defined, the compiler will access a field by + finding the smallest containing object; when it is defined, a + fullword load will be used if alignment permits. Unless bytes + accesses are faster than word accesses, using word accesses is + preferable since it may eliminate subsequent memory access if + subsequent accesses occur to other fields in the same word of the + structure, but to different bytes. */ + +#define SLOW_BYTE_ACCESS 0 + +/* Nonzero if access to memory by shorts is slow and undesirable. */ +#define SLOW_SHORT_ACCESS 0 + +/* Define this macro if zero-extension (of a `char' or `short' to an + `int') can be done faster if the destination is a register that is + known to be zero. + + If you define this macro, you must have instruction patterns that + recognize RTL structures like this: + + (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...) + + and likewise for `HImode'. */ + +/* #define SLOW_ZERO_EXTEND */ + +/* Define this macro to be the value 1 if unaligned accesses have a + cost many times greater than aligned accesses, for example if they + are emulated in a trap handler. + + When this macro is non-zero, the compiler will act as if + `STRICT_ALIGNMENT' were non-zero when generating code for block + moves. This can cause significantly more instructions to be + produced. Therefore, do not set this macro non-zero if unaligned + accesses only add a cycle or two to the time for a memory access. + + If the value of this macro is always zero, it need not be defined. */ + +/* #define SLOW_UNALIGNED_ACCESS 0 */ + +/* Define this macro to inhibit strength reduction of memory + addresses. (On some machines, such strength reduction seems to do + harm rather than good.) */ + +/* #define DONT_REDUCE_ADDR */ + +/* Define this macro if it is as good or better to call a constant + function address than to call an address kept in a register. + + Desirable on the 386 because a CALL with a constant address is + faster than one with a register address. */ + +#define NO_FUNCTION_CSE + +/* Define this macro if it is as good or better for a function to call + itself with an explicit address than to call an address kept in a + register. */ + +#define NO_RECURSIVE_FUNCTION_CSE + +/* A C statement (sans semicolon) to update the integer variable COST + based on the relationship between INSN that is dependent on + DEP_INSN through the dependence LINK. The default is to make no + adjustment to COST. This can be used for example to specify to + the scheduler that an output- or anti-dependence does not incur + 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; \ + } \ + } + + +#define ADJUST_BLOCKAGE(last_insn,insn,blockage) \ +{ \ + if (is_fp_store (last_insn) && is_fp_insn (insn) \ + && NEXT_INSN (last_insn) && NEXT_INSN (NEXT_INSN (last_insn)) \ + && NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn))) \ + && (GET_CODE (NEXT_INSN (last_insn)) == INSN) \ + && (GET_CODE (NEXT_INSN (NEXT_INSN (last_insn))) == JUMP_INSN) \ + && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn)))) == NOTE) \ + && (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn)))) \ + == NOTE_INSN_LOOP_END)) \ + { \ + (blockage) = 3; \ + } \ +} + /* Add any extra modes needed to represent the condition code. @@ -1519,6 +2355,10 @@ extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); /* Here we define machine-dependent flags and fields in cc_status (see `conditions.h'). */ +/* Set if the cc value was actually from the 80387 and + we are testing eax directly (i.e. no sahf) */ +#define CC_TEST_AX 020000 + /* Set if the cc value is actually in the 80387, so a floating point conditional branch must be output. */ #define CC_IN_80387 04000 @@ -1527,6 +2367,10 @@ extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); the state of equality is indicated by zero in the carry bit. */ #define CC_Z_IN_NOT_C 010000 +/* Set if the CC value was actually from the 80387 and loaded directly + into the eflags instead of via eax/sahf. */ +#define CC_FCOMI 040000 + /* Store in cc_status the expressions that the condition codes will describe after execution of an instruction whose pattern is EXP. @@ -1572,10 +2416,10 @@ extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); /* Table of additional register names to use in user input. */ #define ADDITIONAL_REGISTER_NAMES \ -{ "eax", 0, "edx", 1, "ecx", 2, "ebx", 3, \ - "esi", 4, "edi", 5, "ebp", 6, "esp", 7, \ - "al", 0, "dl", 1, "cl", 2, "bl", 3, \ - "ah", 0, "dh", 1, "ch", 2, "bh", 3 } +{ { "eax", 0 }, { "edx", 1 }, { "ecx", 2 }, { "ebx", 3 }, \ + { "esi", 4 }, { "edi", 5 }, { "ebp", 6 }, { "esp", 7 }, \ + { "al", 0 }, { "dl", 1 }, { "cl", 2 }, { "bl", 3 }, \ + { "ah", 0 }, { "dh", 1 }, { "ch", 2 }, { "bh", 3 } } /* Note we are omitting these since currently I don't know how to get gcc to use these, since they want the same but different @@ -1609,6 +2453,22 @@ number as al, and ax. (n) == 7 ? 5 : \ (n) + 4) +/* Before the prologue, RA is at 0(%esp). */ +#define INCOMING_RETURN_ADDR_RTX \ + gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM)) + +/* After the prologue, RA is at -4(AP) in the current frame. */ +#define RETURN_ADDR_RTX(COUNT, FRAME) \ + ((COUNT) == 0 \ + ? gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT(-4)))\ + : gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, (FRAME), GEN_INT(4)))) + +/* PC is dbx register 8; let's use that column for RA. */ +#define DWARF_FRAME_RETURN_COLUMN 8 + +/* Before the prologue, the top of the frame is at 4(%esp). */ +#define INCOMING_FRAME_SP_OFFSET 4 + /* This is how to output the definition of a user-level label named NAME, such as the label on a static function or variable NAME. */ @@ -1620,10 +2480,7 @@ number as al, and ax. #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ do { long l[2]; \ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "%s 0x%x,0x%x\n", ASM_LONG, l[0], l[1]); \ - else \ - fprintf (FILE, "%s 0x%lx,0x%lx\n", ASM_LONG, l[0], l[1]); \ + fprintf (FILE, "%s 0x%lx,0x%lx\n", ASM_LONG, l[0], l[1]); \ } while (0) /* This is how to output a `long double' extended real constant. */ @@ -1632,10 +2489,7 @@ do { long l[2]; \ #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ do { long l[3]; \ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "%s 0x%x,0x%x,0x%x\n", ASM_LONG, l[0], l[1], l[2]); \ - else \ - fprintf (FILE, "%s 0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \ + fprintf (FILE, "%s 0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \ } while (0) /* This is how to output an assembler line defining a `float' constant. */ @@ -1643,10 +2497,7 @@ do { long l[3]; \ #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ do { long l; \ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - if (sizeof (int) == sizeof (long)) \ - fprintf ((FILE), "%s 0x%x\n", ASM_LONG, l); \ - else \ - fprintf ((FILE), "%s 0x%lx\n", ASM_LONG, l); \ + fprintf ((FILE), "%s 0x%lx\n", ASM_LONG, l); \ } while (0) /* Store in OUTPUT a string (made with alloca) containing @@ -1698,13 +2549,13 @@ do { long l; \ It need not be very fast code. */ #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tpushl e%s\n", reg_names[REGNO]) + fprintf (FILE, "\tpushl %%e%s\n", reg_names[REGNO]) /* This is how to output an insn to pop a register from the stack. It need not be very fast code. */ #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tpopl e%s\n", reg_names[REGNO]) + fprintf (FILE, "\tpopl %%e%s\n", reg_names[REGNO]) /* This is how to output an element of a case-vector that is absolute. */ @@ -1717,7 +2568,7 @@ do { long l; \ forward reference the differences. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.word %s%d-%s%d\n",LPREFIX, VALUE,LPREFIX, REL) /* Define the parentheses used to group arithmetic operations @@ -1746,9 +2597,13 @@ do { long l; \ 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. - b -- print the operand as if it's a byte (QImode) even if it isn't. - c -- don't print special prefixes before constant operands. */ + P -- if PIC, print an @PLT suffix. + X -- don't print any sort of PIC '@' suffix for a symbol. + J -- print jump insn for arithmetic_comparison_operator. + s -- ??? something to do with double shifts. not actually used, afaik. + C -- print a conditional move suffix corresponding to the op code. + c -- likewise, but reverse the condition. + F,f -- likewise, but for floating-point. */ #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ((CODE) == '*') @@ -1853,13 +2708,30 @@ extern char *qi_high_reg_name[]; we can use for operand syntax in the extended asm */ #define ASM_OPERAND_LETTER '#' - #define RET return "" -#define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx)) +#define AT_SP(mode) (gen_rtx_MEM ((mode), stack_pointer_rtx)) + +/* Helper macros to expand a binary/unary operator if needed */ +#define IX86_EXPAND_BINARY_OPERATOR(OP, MODE, OPERANDS) \ +do { \ + if (!ix86_expand_binary_operator (OP, MODE, OPERANDS)) \ + FAIL; \ +} while (0) + +#define IX86_EXPAND_UNARY_OPERATOR(OP, MODE, OPERANDS) \ +do { \ + if (!ix86_expand_unary_operator (OP, MODE, OPERANDS,)) \ + FAIL; \ +} while (0) + /* Functions in i386.c */ extern void override_options (); extern void order_regs_for_local_alloc (); +extern char *output_strlen_unroll (); +extern struct rtx_def *i386_sext16_if_const (); +extern int i386_aligned_p (); +extern int i386_cc_probably_useless_p (); extern int i386_valid_decl_attribute_p (); extern int i386_valid_type_attribute_p (); extern int i386_return_pops_args (); @@ -1868,6 +2740,7 @@ extern void init_cumulative_args (); 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 (); @@ -1880,6 +2753,10 @@ extern int symbolic_operand (); extern int call_insn_operand (); extern int expander_call_insn_operand (); extern int symbolic_reference_mentioned_p (); +extern int ix86_expand_binary_operator (); +extern int ix86_binary_operator_ok (); +extern int ix86_expand_unary_operator (); +extern int ix86_unary_operator_ok (); extern void emit_pic_move (); extern void function_prologue (); extern int simple_386_epilogue (); @@ -1902,17 +2779,40 @@ extern void save_386_machine_status (); extern void restore_386_machine_status (); extern void clear_386_stack_locals (); extern struct rtx_def *assign_386_stack_local (); +extern int is_mul (); +extern int is_div (); +extern int last_to_set_cc (); +extern int doesnt_set_condition_code (); +extern int sets_condition_code (); +extern int str_immediate_operand (); +extern int is_fp_insn (); +extern int is_fp_dest (); +extern int is_fp_store (); +extern int agi_dependent (); +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 (); + +#ifdef NOTYET +extern struct rtx_def *copy_all_rtx (); +extern void rewrite_address (); +#endif /* Variables in i386.c */ +extern char *ix86_cpu_string; /* for -mcpu= */ +extern char *ix86_arch_string; /* for -march= */ extern char *i386_reg_alloc_order; /* register allocation order */ 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_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_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) */ extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */ @@ -1921,11 +2821,12 @@ extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */ extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */ /* External variables used */ -extern int optimize; /* optimization level */ -extern int obey_regdecls; /* TRUE if stupid register allocation */ +extern int optimize; /* optimization level */ +extern int obey_regdecls; /* TRUE if stupid register allocation */ /* External functions used */ extern struct rtx_def *force_operand (); + /* Local variables: diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md index ff01196..f85992f 100644 --- a/contrib/gcc/config/i386/i386.md +++ b/contrib/gcc/config/i386/i386.md @@ -1,5 +1,5 @@ -;; GCC machine description for Intel X86. -;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc. +; GCC machine description for Intel X86. +;; Copyright (C) 1988, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; This file is part of GNU CC. @@ -17,8 +17,7 @@ ;; 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. - +;; Boston, MA 02111-1307, USA. */ ;; The original PO technology requires these to be ordered by speed, ;; so that assigner will pick the fastest. @@ -37,8 +36,8 @@ ;; 'L' Print the opcode suffix for a 32-bit integer opcode. ;; 'W' Print the opcode suffix for a 16-bit integer opcode. ;; 'B' Print the opcode suffix for an 8-bit integer opcode. -;; 'S' Print the opcode suffix for a 32-bit float opcode. ;; 'Q' Print the opcode suffix for a 64-bit float opcode. +;; 'S' Print the opcode suffix for a 32-bit float opcode. ;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode. ;; 'J' Print the appropriate jump operand. @@ -59,6 +58,72 @@ ;; operand 0 is the argument for `sin'. ;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. ;; operand 0 is the argument for `cos'. +;; 3 This is part of a `stack probe' operation. The mode of the UNSPEC is +;; always SImode. operand 0 is the size of the stack allocation. +;; 4 This is the source of a fake SET of the frame pointer which is used to +;; prevent insns referencing it being scheduled across the initial +;; decrement of the stack pointer. +;; 5 This is a `bsf' operation. + +;; 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" + (const_string "integer")) + +;; Functional units + +; (define_function_unit NAME MULTIPLICITY SIMULTANEITY +; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) + +; pentiumpro has a reservation station with 5 ports +; port 0 has integer, float add, integer divide, float divide, float +; multiply, and shifter units. +; port 1 has integer, and jump units. +; port 2 has the load address generation unit +; ports 3 and 4 have the store address generation units + +; pentium has two integer pipelines, the main u pipe and the secondary v pipe. +; and a float pipeline + +;; Floating point + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpop") (eq_attr "cpu" "i386,i486")) + 5 5) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpop") (eq_attr "cpu" "pentium,pentiumpro")) + 3 0) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentium")) + 7 0) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentiumpro")) + 5 0) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "idiv") (eq_attr "cpu" "pentiumpro")) + 10 10) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "imul") (eq_attr "cpu" "pentiumpro")) + 6 0) + +(define_function_unit "fp" 1 0 + (eq_attr "type" "fpdiv") + 10 10) + +(define_function_unit "fp" 1 0 + (eq_attr "type" "fld") + 1 0) + +(define_function_unit "integer" 1 0 + (and (eq_attr "type" "integer") (eq_attr "cpu" "!i386")) + 2 0) + ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". ;; But restricting MEM here would mean that gcc could not remove a redundant @@ -72,6 +137,12 @@ ;; actually generating RTL. The bCOND or sCOND (emitted immediately ;; after the tstM or cmp) will actually emit the tstM or cmpM. +;; Processor type -- this attribute must exactly match the processor_type +;; enumeration in i386.h. + +(define_attr "cpu" "i386,i486,pentium,pentiumpro" + (const (symbol_ref "ix86_cpu"))) + (define_insn "tstsi_1" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "rm"))] @@ -93,6 +164,7 @@ { i386_compare_gen = gen_tstsi_1; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -117,6 +189,7 @@ { i386_compare_gen = gen_tsthi_1; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -141,6 +214,7 @@ { i386_compare_gen = gen_tstqi_1; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -174,6 +248,7 @@ { i386_compare_gen = gen_tstsf_cc; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -207,6 +282,7 @@ { i386_compare_gen = gen_tstdf_cc; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -228,7 +304,7 @@ return output_fp_cc0_set (insn); }") -;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode +;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode ;; isn't IEEE compliant. (define_expand "tstxf" @@ -240,6 +316,7 @@ { i386_compare_gen = gen_tstxf_cc; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -251,15 +328,7 @@ (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" - "* -{ - if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) - { - cc_status.flags |= CC_REVERSED; - return AS2 (cmp%L0,%0,%1); - } - return AS2 (cmp%L0,%1,%0); -}") + "* return AS2 (cmp%L0,%1,%0);") (define_expand "cmpsi" [(set (cc0) @@ -282,15 +351,7 @@ (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" - "* -{ - if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) - { - cc_status.flags |= CC_REVERSED; - return AS2 (cmp%W0,%0,%1); - } - return AS2 (cmp%W0,%1,%0); -}") + "* return AS2 (cmp%W0,%1,%0);") (define_expand "cmphi" [(set (cc0) @@ -313,15 +374,7 @@ (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" - "* -{ - if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) - { - cc_status.flags |= CC_REVERSED; - return AS2 (cmp%B0,%0,%1); - } - return AS2 (cmp%B0,%1,%0); -}") + "* return AS2 (cmp%B0,%1,%0);") (define_expand "cmpqi" [(set (cc0) @@ -346,11 +399,10 @@ (define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" - [(match_operand:XF 0 "nonimmediate_operand" "f") - (match_operand:XF 1 "nonimmediate_operand" "f")])) + [(match_operand:XF 0 "register_operand" "f") + (match_operand:XF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "TARGET_80387" "* return output_float_compare (insn, operands);") (define_insn "" @@ -386,6 +438,16 @@ (define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" + [(float_extend:XF + (match_operand:DF 0 "nonimmediate_operand" "fm")) + (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_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm"))])) @@ -395,6 +457,16 @@ (define_insn "" [(set (cc0) + (match_operator 2 "VOIDmode_compare_op" + [(float_extend:XF + (match_operand:SF 0 "nonimmediate_operand" "fm")) + (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) (compare:CCFPEQ (match_operand:XF 0 "register_operand" "f") (match_operand:XF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] @@ -453,6 +525,16 @@ (define_insn "" [(set (cc0) + (match_operator 2 "VOIDmode_compare_op" + [(float_extend:DF + (match_operand:SF 0 "register_operand" "f")) + (match_operand:DF 1 "nonimmediate_operand" "fm")])) + (clobber (match_scratch:HI 3 "=a"))] + "TARGET_80387" + "* return output_float_compare (insn, operands);") + +(define_insn "" + [(set (cc0) (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] @@ -520,7 +602,7 @@ (define_expand "cmpxf" [(set (cc0) (compare (match_operand:XF 0 "register_operand" "") - (match_operand:XF 1 "nonimmediate_operand" "")))] + (match_operand:XF 1 "register_operand" "")))] "TARGET_80387" " { @@ -534,28 +616,30 @@ (define_expand "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "nonimmediate_operand" "")))] + (match_operand:DF 1 "general_operand" "")))] "TARGET_80387" " { i386_compare_gen = gen_cmpdf_cc; i386_compare_gen_eq = gen_cmpdf_ccfpeq; i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; + i386_compare_op1 = (immediate_operand (operands[1], DFmode)) + ? copy_to_mode_reg (DFmode, operands[1]) : operands[1]; DONE; }") (define_expand "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "nonimmediate_operand" "")))] + (match_operand:SF 1 "general_operand" "")))] "TARGET_80387" " { i386_compare_gen = gen_cmpsf_cc; i386_compare_gen_eq = gen_cmpsf_ccfpeq; i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; + i386_compare_op1 = (immediate_operand (operands[1], SFmode)) + ? copy_to_mode_reg (SFmode, operands[1]) : operands[1]; DONE; }") @@ -573,11 +657,7 @@ (match_operand:XF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" - " -{ - if (! register_operand (operands[1], XFmode)) - operands[1] = copy_to_mode_reg (XFmode, operands[1]); -}") + "") (define_expand "cmpdf_cc" [(parallel [(set (cc0) @@ -624,7 +704,7 @@ (define_insn "" [(set (cc0) (and:SI (match_operand:SI 0 "general_operand" "%ro") - (match_operand:SI 1 "general_operand" "ri")))] + (match_operand:SI 1 "nonmemory_operand" "ri")))] "" "* { @@ -682,7 +762,7 @@ (define_insn "" [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "%ro") - (match_operand:HI 1 "general_operand" "ri")))] + (match_operand:HI 1 "nonmemory_operand" "ri")))] "" "* { @@ -715,6 +795,12 @@ } } + /* use 32-bit test instruction if there are no sign issues */ + if (GET_CODE (operands[1]) == CONST_INT + && !(INTVAL (operands[1]) & ~0x7fff) + && i386_aligned_p (operands[0])) + return AS2 (test%L0,%1,%k0); + if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%W0,%1,%0); @@ -723,8 +809,8 @@ (define_insn "" [(set (cc0) - (and:QI (match_operand:QI 0 "general_operand" "%qm") - (match_operand:QI 1 "general_operand" "qi")))] + (and:QI (match_operand:QI 0 "nonimmediate_operand" "%qm") + (match_operand:QI 1 "nonmemory_operand" "qi")))] "" "* { @@ -741,24 +827,23 @@ (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "general_operand" "g"))] - "TARGET_386" - "push%L0 %1") - -;; On a 486, it is faster to move MEM to a REG and then push, rather than -;; push MEM directly. + (match_operand:SI 1 "nonmemory_operand" "rn"))] + "flag_pic" + "* return AS1 (push%L0,%1);") (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "nonmemory_operand" "ri"))] - "!TARGET_386 && TARGET_MOVE" - "push%L0 %1") + "!flag_pic" + "* return AS1 (push%L0,%1);") + +;; On a 386, it is faster to push MEM directly. (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "general_operand" "ri"))] - "!TARGET_386 && !TARGET_MOVE" - "push%L0 %1") + (match_operand:SI 1 "memory_operand" "m"))] + "TARGET_PUSH_MEMORY" + "* return AS1 (push%L0,%1);") ;; General case of fullword move. @@ -790,8 +875,10 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,r") - (match_operand:SI 1 "general_operand" "ri,m"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + (match_operand:SI 1 "general_operand" "rn,im"))] + "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)) + && flag_pic" "* { rtx link; @@ -810,29 +897,50 @@ /* Fastest way to change a 0 to a 1. */ return AS1 (inc%L0,%0); - if (flag_pic && SYMBOLIC_CONST (operands[1])) + if (SYMBOLIC_CONST (operands[1])) return AS2 (lea%L0,%a1,%0); return AS2 (mov%L0,%1,%0); }") (define_insn "" - [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "general_operand" "g"))] - "TARGET_386" - "push%W0 %1") + [(set (match_operand:SI 0 "general_operand" "=g,r") + (match_operand:SI 1 "general_operand" "ri,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])) + return AS2 (xor%L0,%0,%0); + + if (operands[1] == const1_rtx + && (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)) + && GET_CODE (XEXP (link, 0)) != NOTE + /* Make sure cross jumping didn't happen here. */ + && no_labels_between_p (XEXP (link, 0), insn) + /* Make sure the reg hasn't been clobbered. */ + && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) + /* Fastest way to change a 0 to a 1. */ + return AS1 (inc%L0,%0); + + return AS2 (mov%L0,%1,%0); +}") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "nonmemory_operand" "ri"))] - "!TARGET_386 && TARGET_MOVE" - "push%W0 %1") + "" + "* return AS1 (push%W0,%1);") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "general_operand" "ri"))] - "!TARGET_386 && !TARGET_MOVE" - "push%W0 %1") + (match_operand:HI 1 "memory_operand" "m"))] + "TARGET_PUSH_MEMORY" + "* return AS1 (push%W0,%1);") ;; On i486, an incl and movl are both faster than incw and movw. @@ -876,10 +984,21 @@ if (REG_P (operands[0])) { - if (REG_P (operands[1])) - return AS2 (mov%L0,%k1,%k0); - else if (CONSTANT_P (operands[1])) - return AS2 (mov%L0,%1,%k0); + if (i386_aligned_p (operands[1])) + { + operands[1] = i386_sext16_if_const (operands[1]); + return AS2 (mov%L0,%k1,%k0); + } + if (TARGET_PENTIUMPRO) + { + /* movzwl is faster than movw on the Pentium Pro, + * although not as fast as an aligned movl. */ +#ifdef INTEL_SYNTAX + return AS2 (movzx,%1,%k0); +#else + return AS2 (movz%W0%L0,%1,%k0); +#endif + } } return AS2 (mov%W0,%1,%0); @@ -932,27 +1051,17 @@ ;; the amount pushed up to a halfword. (define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "immediate_operand" "n"))] + (match_operand:QI 1 "const_int_operand" "n"))] "" - "* return AS1 (push%W0,%1);") - -(define_insn "" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "nonimmediate_operand" "q"))] - "!TARGET_MOVE" - "* -{ - operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); - return AS1 (push%W0,%1); -}") + "* return AS1(push%W0,%1);") (define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "register_operand" "q"))] - "TARGET_MOVE" + "" "* { - operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); + operands[1] = gen_rtx_REG (HImode, REGNO (operands[1])); return AS1 (push%W0,%1); }") @@ -978,14 +1087,14 @@ }") (define_insn "" - [(set (match_operand:QI 0 "general_operand" "=q,*r,qm") - (match_operand:QI 1 "general_operand" "*g,q,qn"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,*r,qm") + (match_operand:QI 1 "general_operand" "*g,*rn,qn"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) - return AS2 (xor%B0,%0,%0); + return AS2 (xor%L0,%k0,%k0); if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) @@ -996,8 +1105,14 @@ && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%B0,%0); + { + /* Fastest way to change a 0 to a 1. + If inc%B0 isn't allowed, use inc%L0. */ + if (NON_QI_REG_P (operands[0])) + return AS1 (inc%L0,%k0); + else + return AS1 (inc%B0,%0); + } /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) @@ -1032,7 +1147,7 @@ }") (define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q")) + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (match_operand:QI 1 "general_operand" "*qn,m"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* @@ -1042,6 +1157,7 @@ return AS2 (xor%B0,%0,%0); if (operands[1] == const1_rtx + && ! 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. */ && ! INSN_DELETED_P (XEXP (link, 0)) @@ -1063,43 +1179,10 @@ return AS2 (mov%B0,%1,%0); }") -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode)) - ? gen_movsf_push - : gen_movsf_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a register, - indicate we need the pic register loaded. This could be optimized into stores - of constants if the target eventually moves to memory, but better safe than - sorry. */ - if (flag_pic - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - current_function_uses_pic_offset_table = 1; - } -}") - -(define_insn "movsf_push_nomove" +(define_insn "movsf_push" [(set (match_operand:SF 0 "push_operand" "=<,<") - (match_operand:SF 1 "general_operand" "gF,f"))] - "!TARGET_MOVE" + (match_operand:SF 1 "general_operand" "*rfF,m"))] + "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed" "* { if (STACK_REG_P (operands[1])) @@ -1119,64 +1202,62 @@ output_asm_insn (AS1 (fstp%S0,%0), xops); else output_asm_insn (AS1 (fst%S0,%0), xops); + RET; } - return AS1 (push%L1,%1); + + return AS1 (push%L0,%1); }") -(define_insn "movsf_push" - [(set (match_operand:SF 0 "push_operand" "=<,<,<,<") - (match_operand:SF 1 "general_operand" "rF,f,m,m")) - (clobber (match_scratch:SI 2 "=X,X,r,X"))] +(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_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] "" - "* + " { - if (STACK_REG_P (operands[1])) + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) { - rtx xops[3]; + operands[1] = force_reg (SFmode, operands[1]); + } - if (! STACK_TOP_P (operands[1])) - abort (); + /* 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. */ + 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])) + { + rtx insn, note, fp_const; - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (4); - xops[2] = stack_pointer_rtx; + fp_const = force_const_mem (SFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; - output_asm_insn (AS2 (sub%L2,%1,%2), xops); + insn = emit_insn (gen_rtx_SET (SFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp%S0,%0), xops); + if (note) + XEXP (note, 0) = operands[1]; else - output_asm_insn (AS1 (fst%S0,%0), xops); - RET; - } - - else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG) - return AS1 (push%L1,%1); - - else - { - output_asm_insn (AS2 (mov%L2,%1,%2), operands); - return AS1 (push%L2,%2); + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn)); } }") -;; Special memory<->memory pattern that combine will recreate from the -;; moves to pseudos. -(define_insn "movsf_mem" - [(set (match_operand:SF 0 "memory_operand" "=m") - (match_operand:SF 1 "memory_operand" "m")) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "* -{ - output_asm_insn (AS2 (mov%L2,%1,%2), operands); - return AS2 (mov%L0,%2,%0); -}") - ;; For the purposes of regclass, prefer FLOAT_REGS. -(define_insn "movsf_normal" - [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm") +(define_insn "" + [(set (match_operand:SF 0 "nonimmediate_operand" "=*rfm,*rf,f,!*rm") (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* @@ -1203,7 +1284,7 @@ if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1228,7 +1309,9 @@ /* Handle all SFmode moves not involving the 387 */ return singlemove_string (operands); -}") +}" + [(set_attr "type" "fld")]) + (define_insn "swapsf" [(set (match_operand:SF 0 "register_operand" "f") @@ -1244,50 +1327,17 @@ return AS1 (fxch,%0); }") -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode)) - ? gen_movdf_push - : gen_movdf_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a register, - indicate we need the pic register loaded. This could be optimized into stores - of constants if the target eventually moves to memory, but better safe than - sorry. */ - if (flag_pic - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - current_function_uses_pic_offset_table = 1; - } -}") - -(define_insn "movdf_push_nomove" +(define_insn "movdf_push" [(set (match_operand:DF 0 "push_operand" "=<,<") - (match_operand:DF 1 "general_operand" "gF,f"))] - "!TARGET_MOVE" + (match_operand:DF 1 "general_operand" "*rfF,o"))] + "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed" "* { if (STACK_REG_P (operands[1])) { rtx xops[3]; - xops[0] = AT_SP (SFmode); + xops[0] = AT_SP (DFmode); xops[1] = GEN_INT (8); xops[2] = stack_pointer_rtx; @@ -1300,56 +1350,65 @@ RET; } - else - return output_move_double (operands); + + if (which_alternative == 1) + return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 0, 0); + + return output_move_double (operands); }") -(define_insn "movdf_push" - [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<") - (match_operand:DF 1 "general_operand" "rF,f,o,o,o")) - (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) - (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] +(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_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] "" - "* + " { - if (STACK_REG_P (operands[1])) + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) { - rtx xops[3]; + operands[1] = force_reg (DFmode, operands[1]); + } - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (8); - xops[2] = stack_pointer_rtx; + /* 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. */ + 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])) + { + rtx insn, note, fp_const; - output_asm_insn (AS2 (sub%L2,%1,%2), xops); + fp_const = force_const_mem (DFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp%Q0,%0), xops); - else - output_asm_insn (AS1 (fst%Q0,%0), xops); + insn = emit_insn (gen_rtx_SET (DFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - RET; + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn)); } - - else if (GET_CODE (operands[1]) != MEM) - return output_move_double (operands); - - else - return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4); }") -(define_insn "movdf_mem" - [(set (match_operand:DF 0 "memory_operand" "=o,o") - (match_operand:DF 1 "memory_operand" "o,o")) - (clobber (match_scratch:SI 2 "=&r,&r")) - (clobber (match_scratch:SI 3 "=&r,X"))] - "" - "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);") - ;; For the purposes of regclass, prefer FLOAT_REGS. -(define_insn "movdf_normal" - [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm") +(define_insn "" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm") (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1374,7 +1433,7 @@ if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1399,7 +1458,10 @@ /* Handle all DFmode moves not involving the 387 */ return output_move_double (operands); -}") +}" + [(set_attr "type" "fld")]) + + (define_insn "swapdf" [(set (match_operand:DF 0 "register_operand" "f") @@ -1415,109 +1477,87 @@ return AS1 (fxch,%0); }") -(define_expand "movxf" - [(set (match_operand:XF 0 "general_operand" "") - (match_operand:XF 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode)) - ? gen_movxf_push - : gen_movxf_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a register, - indicate we need the pic register loaded. This could be optimized into stores - of constants if the target eventually moves to memory, but better safe than - sorry. */ - if (flag_pic - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - current_function_uses_pic_offset_table = 1; - } -}") - - -(define_insn "movxf_push_nomove" +(define_insn "movxf_push" [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_operand" "gF,f"))] - "!TARGET_MOVE" + (match_operand:XF 1 "general_operand" "*rfF,o"))] + "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed" "* { if (STACK_REG_P (operands[1])) { rtx xops[3]; - xops[0] = AT_SP (SFmode); + xops[0] = AT_SP (XFmode); xops[1] = GEN_INT (12); xops[2] = stack_pointer_rtx; output_asm_insn (AS2 (sub%L2,%1,%2), xops); + output_asm_insn (AS1 (fstp%T0,%0), xops); if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fld%T0,%0), xops); RET; } - else - return output_move_double (operands); + + if (which_alternative == 1) + return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 0, 0); + + return output_move_double (operands); }") -(define_insn "movxf_push" - [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<") - (match_operand:XF 1 "general_operand" "rF,f,o,o,o")) - (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) - (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] +(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_expand "movxf" + [(set (match_operand:XF 0 "general_operand" "") + (match_operand:XF 1 "general_operand" ""))] "" - "* + " { - if (STACK_REG_P (operands[1])) + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) { - rtx xops[3]; - - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (12); - xops[2] = stack_pointer_rtx; + operands[1] = force_reg (XFmode, operands[1]); + } - output_asm_insn (AS2 (sub%L2,%1,%2), xops); - output_asm_insn (AS1 (fstp%T0,%0), xops); - if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fld%T0,%0), xops); + /* 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. */ + 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])) + { + rtx insn, note, fp_const; - RET; - } + fp_const = force_const_mem (XFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; - else if (GET_CODE (operands[1]) != MEM - || GET_CODE (operands[2]) != REG) - return output_move_double (operands); + insn = emit_insn (gen_rtx_SET (XFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - else - return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4); + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn)); + } }") -(define_insn "movxf_mem" - [(set (match_operand:XF 0 "memory_operand" "=o,o") - (match_operand:XF 1 "memory_operand" "o,o")) - (clobber (match_scratch:SI 2 "=&r,&r")) - (clobber (match_scratch:SI 3 "=&r,X"))] - "" - "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);") -(define_insn "movxf_normal" - [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm") +(define_insn "" + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm") (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1542,7 +1582,7 @@ if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1570,7 +1610,7 @@ return output_move_double (operands); }") -(define_insn "swapxf" +(define_insn "swapxf" [(set (match_operand:XF 0 "register_operand" "f") (match_operand:XF 1 "register_operand" "f")) (set (match_dup 1) @@ -1585,36 +1625,40 @@ }") (define_insn "" - [(set (match_operand:DI 0 "push_operand" "=<,<,<,<") - (match_operand:DI 1 "general_operand" "riF,o,o,o")) - (clobber (match_scratch:SI 2 "=X,&r,&r,X")) - (clobber (match_scratch:SI 3 "=X,&r,X,X"))] + [(set (match_operand:DI 0 "push_operand" "=<") + (match_operand:DI 1 "general_operand" "riF"))] "" - "* -{ - if (GET_CODE (operands[1]) != MEM) - return output_move_double (operands); + "* return output_move_double (operands);") - else - return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4); -}") +(define_insn "" + [(set (match_operand:DI 0 "push_operand" "=<") + (match_operand:DI 1 "memory_operand" "o"))] + "TARGET_PUSH_MEMORY" + "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode),0,0);") -(define_insn "movdi" - [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm") - (match_operand:DI 1 "general_operand" "o,o,m,riF")) - (clobber (match_scratch:SI 2 "=&r,&r,X,X")) - (clobber (match_scratch:SI 3 "=&r,X,X,X"))] +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] "" - "* + " { - rtx low[2], high[2], xop[6]; - - if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - return output_move_double (operands); - else - return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4); + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (DImode, operands[1]); + } }") +(define_insn "" + [(set (match_operand:DI 0 "general_operand" "=g,r") + (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);") + ;;- conversion instructions ;;- NONE @@ -1623,21 +1667,39 @@ ;; See comments by `andsi' for when andl is faster than movzx. (define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rm")))] + [(set (match_operand:SI 0 "register_operand" "=r,&r,?r") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))] "" "* -{ - if ((!TARGET_386 || REGNO (operands[0]) == 0) + { + rtx xops[2]; + + if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) { - rtx xops[2]; xops[0] = operands[0]; xops[1] = GEN_INT (0xffff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; } + if (TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])) + { + output_asm_insn (AS2 (xor%L0,%0,%0),operands); + output_asm_insn (AS2 (mov%W0,%1,%w0),operands); + RET; + } + + if (TARGET_ZERO_EXTEND_WITH_AND) + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xffff); + if (i386_aligned_p (operands[1])) + output_asm_insn (AS2 (mov%L0,%k1,%k0),operands); + else + output_asm_insn (AS2 (mov%W0,%1,%w0),operands); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + RET; + } #ifdef INTEL_SYNTAX return AS2 (movzx,%1,%0); @@ -1646,23 +1708,62 @@ #endif }") +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));") + + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "memory_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) + (match_dup 1)) + (set (match_dup 0) + (and:SI (match_dup 0) + (const_int 65535)))] + "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));") + (define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=r") - (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:HI 0 "register_operand" "=q,&q,?r") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))] "" "* -{ - if ((!TARGET_386 || REGNO (operands[0]) == 0) - && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) + { + rtx xops[2]; + + if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) + && REG_P (operands[1]) + && REGNO (operands[0]) == REGNO (operands[1])) { - rtx xops[2]; xops[0] = operands[0]; xops[1] = GEN_INT (0xff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; } - + if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0])) + { + if(!reg_overlap_mentioned_p(operands[0],operands[1])) + { + output_asm_insn (AS2 (xor%L0,%k0,%k0), operands); + output_asm_insn (AS2 (mov%B0,%1,%b0), operands); + } + else + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xff); + output_asm_insn (AS2 (mov%B0,%1,%b0),operands); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + } + RET; + } + #ifdef INTEL_SYNTAX return AS2 (movzx,%1,%0); #else @@ -1670,19 +1771,86 @@ #endif }") +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + + +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "memory_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) + (match_dup 1)) + (set (match_dup 0) + (and:HI (match_dup 0) + (const_int 255)))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND" + [(set (match_dup 0) + (match_dup 2)) + (set (match_dup 0) + (and:HI (match_dup 0) + (const_int 255)))] + "if (GET_CODE (operands[1]) == SUBREG && SUBREG_WORD (operands[1]) == 0) + operands[1] = SUBREG_REG (operands[1]); + if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG + || REGNO (operands[0]) == REGNO (operands[1])) + FAIL; + operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));") + (define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:SI 0 "register_operand" "=q,&q,?r") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))] "" "* -{ - if ((!TARGET_386 || REGNO (operands[0]) == 0) - && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) + { + rtx xops[2]; + + if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) + && REG_P (operands[1]) + && REGNO (operands[0]) == REGNO (operands[1])) + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xff); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + RET; + } + if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0])) + { + if(!reg_overlap_mentioned_p (operands[0], operands[1])) + { + output_asm_insn (AS2 (xor%L0,%0,%0),operands); + output_asm_insn (AS2 (mov%B0,%1,%b0),operands); + } + else + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xff); + output_asm_insn (AS2 (mov%B0,%1,%b0), operands); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + } + RET; + } + + if (TARGET_ZERO_EXTEND_WITH_AND && GET_CODE (operands[1]) == REG) { - rtx xops[2]; xops[0] = operands[0]; xops[1] = GEN_INT (0xff); + operands[1] = gen_rtx_REG (SImode, REGNO (operands[1])); + output_asm_insn (AS2 (mov%L0,%1,%0), operands); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; } @@ -1694,23 +1862,77 @@ #endif }") +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "memory_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) + (match_dup 1)) + (set (match_dup 0) + (and:SI (match_dup 0) + (const_int 255)))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND + && ! reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (match_dup 2)) + (set (match_dup 0) + (and:SI (match_dup 0) + (const_int 255)))] + "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));") + (define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (match_operand:SI 1 "register_operand" "0")))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m") + (zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))] "" "* -{ - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return AS2 (xor%L0,%0,%0); + { + 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; }") ;;- sign extension instructions (define_insn "extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI - (match_operand:SI 1 "register_operand" "0")))] + (sign_extend:DI (match_operand:SI 1 "register_operand" "0")))] "" "* { @@ -1724,7 +1946,7 @@ #endif } - operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); output_asm_insn (AS2 (mov%L0,%0,%1), operands); operands[0] = GEN_INT (31); @@ -1736,9 +1958,8 @@ ;; We use what the Unix assembler expects. (define_insn "extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rm")))] + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] "" "* { @@ -1758,9 +1979,8 @@ }") (define_insn "extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=r") - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:HI 0 "register_operand" "=r") + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "" "* { @@ -1776,9 +1996,8 @@ }") (define_insn "extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (sign_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "" "* { @@ -1788,13 +2007,72 @@ return AS2 (movs%B0%L0,%1,%0); #endif }") + + +;; Truncation of long long -> 32 bit + +(define_expand "truncdisi2" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") + (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + rtx target = gen_reg_rtx (SImode); + emit_insn (gen_truncdisi2 (target, operands[1])); + emit_move_insn (operands[0], target); + DONE; + } +}") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") + (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))] + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "* +{ + rtx low[2], high[2], xops[2]; + + split_di (&operands[1], 1, low, high); + xops[0] = operands[0]; + xops[1] = low[0]; + if (!rtx_equal_p (xops[0], xops[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + RET; +}") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") + (truncate:SI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") + (const_int 32))))] + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "* +{ + rtx low[2], high[2], xops[2]; + + split_di (&operands[1], 1, low, high); + xops[0] = operands[0]; + xops[1] = high[0]; + if (!rtx_equal_p (xops[0], xops[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + RET; +}") + + ;; Conversions between float and double. (define_insn "extendsfdf2" - [(set (match_operand:DF 0 "general_operand" "=fm,f") + [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f") (float_extend:DF - (match_operand:SF 1 "general_operand" "f,fm")))] + (match_operand:SF 1 "nonimmediate_operand" "f,fm")))] "TARGET_80387" "* { @@ -1808,7 +2086,7 @@ if (NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1827,9 +2105,9 @@ }") (define_insn "extenddfxf2" - [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r") + [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r") (float_extend:XF - (match_operand:DF 1 "general_operand" "f,fm,!*r,f")))] + (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))] "TARGET_80387" "* { @@ -1843,7 +2121,7 @@ if (NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1862,9 +2140,9 @@ }") (define_insn "extendsfxf2" - [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r") + [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r") (float_extend:XF - (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))] + (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))] "TARGET_80387" "* { @@ -1878,7 +2156,7 @@ if (NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1939,7 +2217,7 @@ }") (define_insn "truncxfsf2" - [(set (match_operand:SF 0 "general_operand" "=m,!*r") + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r") (float_truncate:SF (match_operand:XF 1 "register_operand" "f,f")))] "TARGET_80387" @@ -1954,7 +2232,7 @@ output_asm_insn (AS1 (fld,%y1), operands); stack_top_dies = 1; } - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } else if (GET_CODE (operands[0]) == MEM) @@ -1972,7 +2250,7 @@ }") (define_insn "truncxfdf2" - [(set (match_operand:DF 0 "general_operand" "=m,!*r") + [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r") (float_truncate:DF (match_operand:XF 1 "register_operand" "f,f")))] "TARGET_80387" @@ -1987,7 +2265,7 @@ output_asm_insn (AS1 (fld,%y1), operands); stack_top_dies = 1; } - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } else if (GET_CODE (operands[0]) == MEM) @@ -2029,7 +2307,7 @@ 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 (SImode, 1); + operands[6] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fixuns_truncdfsi2" @@ -2050,7 +2328,7 @@ 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 (SImode, 1); + operands[6] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fixuns_truncsfsi2" @@ -2071,7 +2349,7 @@ 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 (SImode, 1); + operands[6] = (rtx) assign_386_stack_local (DImode, 1); }") ;; Signed conversion to DImode. @@ -2091,7 +2369,7 @@ 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 (SImode, 1); + operands[4] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncdfdi2" @@ -2109,7 +2387,7 @@ 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 (SImode, 1); + operands[4] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncsfdi2" @@ -2127,37 +2405,37 @@ 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 (SImode, 1); + operands[4] = (rtx) assign_386_stack_local (DImode, 1); }") ;; These match a signed conversion of either DFmode or SFmode to DImode. (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=rm") - (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f")))) + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f")))) (clobber (match_dup 1)) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=rm") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f")))) + [(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:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=rm") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) + [(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:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") @@ -2175,7 +2453,7 @@ " { operands[2] = (rtx) assign_386_stack_local (SImode, 0); - operands[3] = (rtx) assign_386_stack_local (SImode, 1); + operands[3] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncdfsi2" @@ -2189,7 +2467,7 @@ " { operands[2] = (rtx) assign_386_stack_local (SImode, 0); - operands[3] = (rtx) assign_386_stack_local (SImode, 1); + operands[3] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncsfsi2" @@ -2203,32 +2481,32 @@ " { operands[2] = (rtx) assign_386_stack_local (SImode, 0); - operands[3] = (rtx) assign_386_stack_local (SImode, 1); + operands[3] = (rtx) assign_386_stack_local (DImode, 1); }") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(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:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(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:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(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:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") @@ -2271,14 +2549,14 @@ (define_expand "floatdixf2" [(set (match_operand:XF 0 "register_operand" "") (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))] - "TARGET_80387" + "TARGET_80387 && LONG_DOUBLE_TYPE_SIZE == 96" "") ;; This will convert from SImode or DImode to MODE_FLOAT. (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") - (float:XF (match_operand:DI 1 "general_operand" "rm")))] + (float:XF (match_operand:DI 1 "nonimmediate_operand" "rm")))] "TARGET_80387" "* { @@ -2346,7 +2624,7 @@ (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))] + (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))] "TARGET_80387" "* { @@ -2380,11 +2658,11 @@ ;;- add instructions -(define_insn "adddi3" - [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o") - (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o") - (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o"))) - (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))] +(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")))) + (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,&r"))] "" "* { @@ -2392,14 +2670,10 @@ CC_STATUS_INIT; - if (rtx_equal_p (operands[0], operands[2])) - { - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } + split_di (operands, 2, low, high); + high[2] = const0_rtx; + low[2] = operands[2]; - split_di (operands, 3, low, high); if (!rtx_equal_p (operands[0], operands[1])) { xops[0] = high[0]; @@ -2407,7 +2681,7 @@ xops[2] = high[1]; xops[3] = low[1]; - if (GET_CODE (operands[0]) != MEM) + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) { output_asm_insn (AS2 (mov%L1,%3,%1), xops); output_asm_insn (AS2 (mov%L0,%2,%0), xops); @@ -2427,90 +2701,280 @@ } } - 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]; - - output_asm_insn (AS2 (mov%L4,%3,%4), xops); - output_asm_insn (AS2 (add%L1,%4,%1), xops); - output_asm_insn (AS2 (mov%L4,%2,%4), xops); - output_asm_insn (AS2 (adc%L0,%4,%0), xops); - } - - else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) - { - output_asm_insn (AS2 (add%L0,%2,%0), low); - output_asm_insn (AS2 (adc%L0,%2,%0), high); - } - - else - output_asm_insn (AS2 (add%L0,%2,%0), high); - + output_asm_insn (AS2 (add%L0,%2,%0), low); + output_asm_insn (AS2 (adc%L0,%2,%0), high); RET; }") -;; 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. - -(define_insn "addsi3" - [(set (match_operand:SI 0 "general_operand" "=?r,rm,r") - (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0") - (match_operand:SI 2 "general_operand" "ri,ri,rm")))] +(define_insn "addsidi3_2" + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o") + (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r")) + (match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))] "" "* { - if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) - { - if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) - return AS2 (add%L0,%1,%0); + rtx low[3], high[3], xops[7], temp; - if (operands[2] == stack_pointer_rtx) - { - rtx temp; + CC_STATUS_INIT; - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } + split_di (operands, 2, low, high); + high[2] = const0_rtx; + low[2] = operands[2]; - if (operands[2] != stack_pointer_rtx) - { - CC_STATUS_INIT; - operands[1] = SET_SRC (PATTERN (insn)); - return AS2 (lea%L0,%a1,%0); - } + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; - output_asm_insn (AS2 (mov%L0,%1,%0), operands); + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + { + if (rtx_equal_p (low[0], operands[2])) + { + output_asm_insn (AS2 (mov%L0,%2,%0), high); + output_asm_insn (AS2 (add%L0,%1,%0), low); + output_asm_insn (AS2 (adc%L0,%1,%0), high); + RET; + } + if (rtx_equal_p (high[0], operands[2])) + { + if (GET_CODE (operands[0]) != MEM) + { + output_asm_insn (AS2 (mov%L0,%2,%0), low); + output_asm_insn (AS2 (mov%L0,%2,%0), high); + output_asm_insn (AS2 (add%L0,%1,%0), low); + output_asm_insn (AS2 (adc%L0,%1,%0), high); + } + else + { + /* It's too late to ask for a scratch now - but this + will probably not happen too often. */ + output_asm_insn (AS2 (add%L1,%2,%1), low); + output_asm_insn (AS2 (mov%L0,%1,%0), low); + output_asm_insn (AS2 (mov%L1,%2,%1), low); + output_asm_insn (AS2 (mov%L0,%2,%0), high); + output_asm_insn (AS2 (adc%L0,%1,%0), high); + output_asm_insn (AS2 (sub%L1,%0,%1), low); + output_asm_insn (AS1 (neg%L1,%1), low); + } + RET; + } + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (add%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (adc%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + output_asm_insn (AS2 (add%L0,%2,%0), low); + output_asm_insn (AS2 (adc%L0,%2,%0), high); + RET; +}") + +(define_insn "adddi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") + (plus: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"))] + "" + "* +{ + rtx low[3], high[3], xops[7], temp; + + CC_STATUS_INIT; + + 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) + { + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (add%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (adc%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + 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]; + + output_asm_insn (AS2 (mov%L4,%3,%4), xops); + output_asm_insn (AS2 (add%L1,%4,%1), xops); + output_asm_insn (AS2 (mov%L4,%2,%4), xops); + output_asm_insn (AS2 (adc%L0,%4,%0), xops); + } + + else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) + { + output_asm_insn (AS2 (add%L0,%2,%0), low); + output_asm_insn (AS2 (adc%L0,%2,%0), high); + } + + else + output_asm_insn (AS2 (add%L0,%2,%0), high); + + RET; +}") + +;; 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. + +(define_expand "addsi3" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" "")))] + "" + "IX86_EXPAND_BINARY_OPERATOR (PLUS, SImode, operands);") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") + (match_operand:SI 2 "general_operand" "rmi,ri,ri")))] + "ix86_binary_operator_ok (PLUS, SImode, operands)" + "* +{ + if (REG_P (operands[0]) && REG_P (operands[1]) + && (REG_P (operands[2]) || GET_CODE (operands[2]) == CONST_INT) + && REGNO (operands[0]) != REGNO (operands[1])) + { + if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) + return AS2 (add%L0,%1,%0); + + if (operands[2] == stack_pointer_rtx) + { + rtx temp; + + temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; + } + + if (operands[2] != stack_pointer_rtx) + { + CC_STATUS_INIT; + operands[1] = SET_SRC (PATTERN (insn)); + return AS2 (lea%L0,%a1,%0); + } + } + + if (!rtx_equal_p (operands[0], operands[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), operands); + if (operands[2] == const1_rtx) return AS1 (inc%L0,%0); if (operands[2] == constm1_rtx) return AS1 (dec%L0,%0); + /* subl $-128,%ebx is smaller than addl $128,%ebx. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 128) + { + /* This doesn't compute the carry bit in the same way + * as add%L0, but we use inc and dec above and they + * don't set the carry bit at all. If inc/dec don't need + * a CC_STATUS_INIT, this doesn't either... */ + operands[2] = GEN_INT (-128); + return AS2 (sub%L0,%2,%0); + } + return AS2 (add%L0,%2,%0); }") +;; addsi3 is faster, so put this after. + +(define_insn "movsi_lea" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:QI 1 "address_operand" "p"))] + "" + "* +{ + /* Adding a constant to a register is faster with an add. */ + /* ??? can this ever happen? */ + if (GET_CODE (operands[1]) == PLUS + && GET_CODE (XEXP (operands[1], 1)) == CONST_INT + && rtx_equal_p (operands[0], XEXP (operands[1], 0))) + { + operands[1] = XEXP (operands[1], 1); + + if (operands[1] == const1_rtx) + return AS1 (inc%L0,%0); + + if (operands[1] == constm1_rtx) + return AS1 (dec%L0,%0); + + return AS2 (add%L0,%1,%0); + } + + CC_STATUS_INIT; + return AS2 (lea%L0,%a1,%0); +}") + ;; ??? `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 ;; able to handle the operand. But leal always works? -(define_insn "addhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (plus:HI (match_operand:HI 1 "general_operand" "%0,0") - (match_operand:HI 2 "general_operand" "ri,rm")))] +(define_expand "addhi3" + [(set (match_operand:HI 0 "general_operand" "") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" "")))] "" + "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")))] + "ix86_binary_operator_ok (PLUS, HImode, operands)" "* { /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) + if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */ + && QI_REG_P (operands[0]) && GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) & 0xff) == 0) + && (INTVAL (operands[2]) & 0xff) == 0 + && i386_cc_probably_useless_p (insn)) { int byteval = (INTVAL (operands[2]) >> 8) & 0xff; CC_STATUS_INIT; @@ -2524,6 +2988,28 @@ return AS2 (add%B0,%2,%h0); } + /* Use a 32-bit operation when possible, to avoid the prefix penalty. */ + if (REG_P (operands[0]) + && i386_aligned_p (operands[2]) + && i386_cc_probably_useless_p (insn)) + { + CC_STATUS_INIT; + + if (GET_CODE (operands[2]) == CONST_INT) + { + HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]); + + if (intval == 1) + return AS1 (inc%L0,%k0); + + if (intval == 0xffff) + return AS1 (dec%L0,%k0); + + operands[2] = i386_sext16_if_const (operands[2]); + } + return AS2 (add%L0,%k2,%k0); + } + if (operands[2] == const1_rtx) return AS1 (inc%W0,%0); @@ -2535,11 +3021,18 @@ return AS2 (add%W0,%2,%0); }") -(define_insn "addqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (plus:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qmn")))] +(define_expand "addqi3" + [(set (match_operand:QI 0 "general_operand" "") + (plus:QI (match_operand:QI 1 "general_operand" "") + (match_operand:QI 2 "general_operand" "")))] "" + "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")))] + "ix86_binary_operator_ok (PLUS, QImode, operands)" "* { if (operands[2] == const1_rtx) @@ -2563,8 +3056,8 @@ ; ;(define_insn "" ; [(set (match_operand:SI 0 "push_operand" "=<") -; (plus:SI (match_operand:SI 1 "general_operand" "%r") -; (match_operand:SI 2 "general_operand" "ri")))] +; (plus:SI (match_operand:SI 1 "register_operand" "%r") +; (match_operand:SI 2 "nonmemory_operand" "ri")))] ; "" ; "* ;{ @@ -2572,46 +3065,18 @@ ; xops[0] = operands[0]; ; xops[1] = operands[1]; ; xops[2] = operands[2]; -; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx); +; xops[3] = gen_rtx_MEM (SImode, stack_pointer_rtx); ; output_asm_insn (\"push%z1 %1\", xops); ; output_asm_insn (AS2 (add%z3,%2,%3), xops); ; RET; ;}") -;; addsi3 is faster, so put this after. - -(define_insn "movsi_lea" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:QI 1 "address_operand" "p"))] - "" - "* -{ - CC_STATUS_INIT; - /* Adding a constant to a register is faster with an add. */ - /* ??? can this ever happen? */ - if (GET_CODE (operands[1]) == PLUS - && GET_CODE (XEXP (operands[1], 1)) == CONST_INT - && rtx_equal_p (operands[0], XEXP (operands[1], 0))) - { - operands[1] = XEXP (operands[1], 1); - - if (operands[1] == const1_rtx) - return AS1 (inc%L0,%0); - - if (operands[1] == constm1_rtx) - return AS1 (dec%L0,%0); - - return AS2 (add%L0,%1,%0); - } - return AS2 (lea%L0,%a1,%0); -}") - ;; The patterns that match these are at the end of this file. (define_expand "addxf3" [(set (match_operand:XF 0 "register_operand" "") - (plus:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (plus:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") @@ -2631,11 +3096,59 @@ ;;- subtract instructions +(define_insn "subsidi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,&r,!&r,o,o,!o") + (minus:DI (match_operand:DI 1 "general_operand" "0iF,0,roiF,roiF,riF,o,o") + (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,ri,i,r")))) + (clobber (match_scratch:SI 3 "=X,X,X,X,X,&r,&r"))] + "" + "* +{ + rtx low[3], high[3], xops[7]; + + CC_STATUS_INIT; + + split_di (operands, 2, low, high); + high[2] = const0_rtx; + low[2] = operands[2]; + + 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 || GET_CODE (operands[1]) != MEM) + { + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (sub%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (sbb%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + output_asm_insn (AS2 (sub%L0,%2,%0), low); + output_asm_insn (AS2 (sbb%L0,%2,%0), high); + RET; +}") + (define_insn "subdi3" - [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o") - (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o") - (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o"))) - (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))] + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o") + (minus:DI (match_operand:DI 1 "general_operand" "0,0,0iF,or,roiF,roiF") + (match_operand:DI 2 "general_operand" "or,riF,or,iF,roiF,roiF"))) + (clobber (match_scratch:SI 3 "=X,X,&r,&r,X,&r"))] "" "* { @@ -2698,33 +3211,65 @@ RET; }") -(define_insn "subsi3" - [(set (match_operand:SI 0 "general_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "general_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm")))] +(define_expand "subsi3" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (minus:SI (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" "")))] "" + "IX86_EXPAND_BINARY_OPERATOR (MINUS, SImode, operands);") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (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);") -(define_insn "subhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "general_operand" "0,0") +(define_expand "subhi3" + [(set (match_operand:HI 0 "general_operand" "") + (minus:HI (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + "IX86_EXPAND_BINARY_OPERATOR (MINUS, HImode, operands);") + +(define_insn "" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] + "ix86_binary_operator_ok (MINUS, HImode, operands)" + "* +{ + if (REG_P (operands[0]) + && i386_aligned_p (operands[2]) + && i386_cc_probably_useless_p (insn)) + { + CC_STATUS_INIT; + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (sub%L0,%k2,%k0); + } + return AS2 (sub%W0,%2,%0); +}") + +(define_expand "subqi3" + [(set (match_operand:QI 0 "general_operand" "") + (minus:QI (match_operand:QI 1 "general_operand" "") + (match_operand:QI 2 "general_operand" "")))] "" - "* return AS2 (sub%W0,%2,%0);") + "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);") -(define_insn "subqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "general_operand" "0,0") +(define_insn "" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (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);") ;; The patterns that match these are at the end of this file. (define_expand "subxf3" [(set (match_operand:XF 0 "register_operand" "") - (minus:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (minus:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") @@ -2745,22 +3290,15 @@ ;;- multiply instructions ;(define_insn "mulqi3" -; [(set (match_operand:QI 0 "general_operand" "=a") -; (mult:QI (match_operand:QI 1 "general_operand" "%0") -; (match_operand:QI 2 "general_operand" "qm")))] +; [(set (match_operand:QI 0 "register_operand" "=a") +; (mult:QI (match_operand:QI 1 "register_operand" "%0") +; (match_operand:QI 2 "nonimmediate_operand" "qm")))] ; "" ; "imul%B0 %2,%0") -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r") - (mult:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "r")))] - "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" - "* return AS2 (imul%W0,%2,%0);") - (define_insn "mulhi3" - [(set (match_operand:HI 0 "general_operand" "=r,r") - (mult:HI (match_operand:HI 1 "general_operand" "%0,rm") + [(set (match_operand:HI 0 "register_operand" "=r,r") + (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%0,rm") (match_operand:HI 2 "general_operand" "g,i")))] "" "* @@ -2771,18 +3309,12 @@ /* Assembler has weird restrictions. */ return AS2 (imul%W0,%2,%0); return AS3 (imul%W0,%2,%1,%0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=r") - (mult:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "r")))] - "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" - "* return AS2 (imul%L0,%2,%0);") +}" + [(set_attr "type" "imul")]) (define_insn "mulsi3" - [(set (match_operand:SI 0 "general_operand" "=r,r") - (mult:SI (match_operand:SI 1 "general_operand" "%0,rm") + [(set (match_operand:SI 0 "register_operand" "=r,r") + (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm") (match_operand:SI 2 "general_operand" "g,i")))] "" "* @@ -2793,35 +3325,40 @@ /* Assembler has weird restrictions. */ return AS2 (imul%L0,%2,%0); return AS3 (imul%L0,%2,%1,%0); -}") +}" + [(set_attr "type" "imul")]) (define_insn "umulqihi3" - [(set (match_operand:HI 0 "general_operand" "=a") - (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) + [(set (match_operand:HI 0 "register_operand" "=a") + (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] "" - "mul%B0 %2") + "mul%B0 %2" + [(set_attr "type" "imul")]) (define_insn "mulqihi3" - [(set (match_operand:HI 0 "general_operand" "=a") - (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) + [(set (match_operand:HI 0 "register_operand" "=a") + (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] "" - "imul%B0 %2") + "imul%B0 %2" + [(set_attr "type" "imul")]) (define_insn "umulsidi3" [(set (match_operand:DI 0 "register_operand" "=A") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] "TARGET_WIDE_MULTIPLY" - "mul%L0 %2") + "mul%L0 %2" + [(set_attr "type" "imul")]) (define_insn "mulsidi3" [(set (match_operand:DI 0 "register_operand" "=A") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] "TARGET_WIDE_MULTIPLY" - "imul%L0 %2") + "imul%L0 %2" + [(set_attr "type" "imul")]) (define_insn "umulsi3_highpart" [(set (match_operand:SI 0 "register_operand" "=d") @@ -2830,7 +3367,8 @@ (const_int 32)))) (clobber (match_scratch:SI 3 "=a"))] "TARGET_WIDE_MULTIPLY" - "mul%L0 %2") + "mul%L0 %2" + [(set_attr "type" "imul")]) (define_insn "smulsi3_highpart" [(set (match_operand:SI 0 "register_operand" "=d") @@ -2839,27 +3377,28 @@ (const_int 32)))) (clobber (match_scratch:SI 3 "=a"))] "TARGET_WIDE_MULTIPLY" - "imul%L0 %2") + "imul%L0 %2" + [(set_attr "type" "imul")]) ;; The patterns that match these are at the end of this file. (define_expand "mulxf3" [(set (match_operand:XF 0 "register_operand" "") - (mult:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (mult:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") (define_expand "muldf3" [(set (match_operand:DF 0 "register_operand" "") - (mult:DF (match_operand:DF 1 "nonimmediate_operand" "") + (mult:DF (match_operand:DF 1 "register_operand" "") (match_operand:DF 2 "nonimmediate_operand" "")))] "TARGET_80387" "") (define_expand "mulsf3" [(set (match_operand:SF 0 "register_operand" "") - (mult:SF (match_operand:SF 1 "nonimmediate_operand" "") + (mult:SF (match_operand:SF 1 "register_operand" "") (match_operand:SF 2 "nonimmediate_operand" "")))] "TARGET_80387" "") @@ -2867,38 +3406,39 @@ ;;- divide instructions (define_insn "divqi3" - [(set (match_operand:QI 0 "general_operand" "=a") - (div:QI (match_operand:HI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "qm")))] + [(set (match_operand:QI 0 "register_operand" "=a") + (div:QI (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm")))] "" "idiv%B0 %2") (define_insn "udivqi3" - [(set (match_operand:QI 0 "general_operand" "=a") - (udiv:QI (match_operand:HI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "qm")))] + [(set (match_operand:QI 0 "register_operand" "=a") + (udiv:QI (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm")))] "" - "div%B0 %2") + "div%B0 %2" + [(set_attr "type" "idiv")]) ;; The patterns that match these are at the end of this file. (define_expand "divxf3" [(set (match_operand:XF 0 "register_operand" "") - (div:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (div:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") (define_expand "divdf3" [(set (match_operand:DF 0 "register_operand" "") - (div:DF (match_operand:DF 1 "nonimmediate_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - + (div:DF (match_operand:DF 1 "register_operand" "") + (match_operand:DF 2 "nonimmediate_operand" "")))] + "TARGET_80387" + "") + (define_expand "divsf3" [(set (match_operand:SF 0 "register_operand" "") - (div:SF (match_operand:SF 1 "nonimmediate_operand" "") + (div:SF (match_operand:SF 1 "register_operand" "") (match_operand:SF 2 "nonimmediate_operand" "")))] "TARGET_80387" "") @@ -2908,7 +3448,7 @@ (define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=a") (div:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=&d") (mod:SI (match_dup 1) (match_dup 2)))] "" @@ -2920,22 +3460,24 @@ output_asm_insn (\"cltd\", operands); #endif return AS1 (idiv%L0,%2); -}") +}" + [(set_attr "type" "idiv")]) (define_insn "divmodhi4" [(set (match_operand:HI 0 "register_operand" "=a") (div:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "rm"))) + (match_operand:HI 2 "nonimmediate_operand" "rm"))) (set (match_operand:HI 3 "register_operand" "=&d") (mod:HI (match_dup 1) (match_dup 2)))] "" - "cwtd\;idiv%W0 %2") + "cwtd\;idiv%W0 %2" + [(set_attr "type" "idiv")]) ;; ??? Can we make gcc zero extend operand[0]? (define_insn "udivmodsi4" [(set (match_operand:SI 0 "register_operand" "=a") (udiv:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=&d") (umod:SI (match_dup 1) (match_dup 2)))] "" @@ -2943,13 +3485,14 @@ { output_asm_insn (AS2 (xor%L3,%3,%3), operands); return AS1 (div%L0,%2); -}") +}" + [(set_attr "type" "idiv")]) ;; ??? Can we make gcc zero extend operand[0]? (define_insn "udivmodhi4" [(set (match_operand:HI 0 "register_operand" "=a") (udiv:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "rm"))) + (match_operand:HI 2 "nonimmediate_operand" "rm"))) (set (match_operand:HI 3 "register_operand" "=&d") (umod:HI (match_dup 1) (match_dup 2)))] "" @@ -2957,7 +3500,8 @@ { output_asm_insn (AS2 (xor%W0,%3,%3), operands); return AS1 (div%W0,%2); -}") +}" + [(set_attr "type" "idiv")]) /* ;;this should be a valid double division which we may want to add @@ -2965,11 +3509,12 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=a") (udiv:DI (match_operand:DI 1 "register_operand" "a") - (match_operand:SI 2 "general_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=d") (umod:SI (match_dup 1) (match_dup 2)))] "" - "div%L0 %2,%0") + "div%L0 %2,%0" + [(set_attr "type" "idiv")]) */ ;;- and instructions @@ -2989,21 +3534,33 @@ ;; The `r' in `rm' for operand 3 looks redundant, but it causes ;; optional reloads to be generated if op 3 is a pseudo in a stack slot. -;; ??? What if we only change one byte of an offsettable memory reference? (define_insn "andsi3" - [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r") - (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0") - (match_operand:SI 2 "general_operand" "L,K,ri,rm")))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") + (match_operand:SI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + if (!rtx_equal_p (operands[0], operands[1]) + && rtx_equal_p (operands[0], operands[2])) { - if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0]) + rtx tmp; + tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } + switch (GET_CODE (operands[2])) + { + case CONST_INT: + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; + intval = INTVAL (operands[2]); + /* zero-extend 16->32? */ + if (intval == 0xffff && REG_P (operands[0]) && (! REG_P (operands[1]) || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) + && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1]))) { /* ??? tege: Should forget CC_STATUS only if we clobber a remembered operand. Fix that later. */ @@ -3015,11 +3572,12 @@ #endif } - if (INTVAL (operands[2]) == 0xff && REG_P (operands[0]) + /* zero extend 8->32? */ + if (intval == 0xff && REG_P (operands[0]) && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1])) && (! REG_P (operands[1]) || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) + && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1]))) { /* ??? tege: Should forget CC_STATUS only if we clobber a remembered operand. Fix that later. */ @@ -3031,47 +3589,110 @@ #endif } - if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0) - { - CC_STATUS_INIT; + /* Check partial bytes.. non-QI-regs are not available */ + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; - if (INTVAL (operands[2]) == 0xffffff00) + /* only low byte has zero bits? */ + if (~(intval | 0xff) == 0) + { + intval &= 0xff; + if (REG_P (operands[0])) { - operands[2] = const0_rtx; - return AS2 (mov%B0,%2,%b0); + if (intval == 0) + { + CC_STATUS_INIT; + return AS2 (xor%B0,%b0,%b0); + } + + /* we're better off with the 32-bit version if reg != EAX */ + /* the value is sign-extended in 8 bits */ + if (REGNO (operands[0]) != 0 && (intval & 0x80)) + break; } - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); + CC_STATUS_INIT; + + operands[2] = GEN_INT (intval); + + if (intval == 0) + return AS2 (mov%B0,%2,%b0); + return AS2 (and%B0,%2,%b0); } - if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0) + /* only second byte has zero? */ + if (~(intval | 0xff00) == 0) { CC_STATUS_INIT; - if (INTVAL (operands[2]) == 0xffff00ff) + intval = (intval >> 8) & 0xff; + operands[2] = GEN_INT (intval); + if (intval == 0) { - operands[2] = const0_rtx; - return AS2 (mov%B0,%2,%h0); + if (REG_P (operands[0])) + return AS2 (xor%B0,%h0,%h0); + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (mov%B0,%2,%b0); } - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - return AS2 (and%B0,%2,%h0); + if (REG_P (operands[0])) + return AS2 (and%B0,%2,%h0); + + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (and%B0,%2,%b0); + } + + if (REG_P (operands[0])) + break; + + /* third byte has zero bits? */ + if (~(intval | 0xff0000) == 0) + { + intval = (intval >> 16) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 2); +byte_and_operation: + CC_STATUS_INIT; + operands[2] = GEN_INT (intval); + if (intval == 0) + return AS2 (mov%B0,%2,%b0); + return AS2 (and%B0,%2,%b0); + } + + /* fourth byte has zero bits? */ + if (~(intval | 0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_and_operation; } - if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000) + /* Low word is zero? */ + if (intval == 0xffff0000) { +word_zero_and_operation: + CC_STATUS_INIT; operands[2] = const0_rtx; return AS2 (mov%W0,%2,%w0); } + + /* High word is zero? */ + if (intval == 0x0000ffff) + { + operands[0] = adj_offsettable_operand (operands[0], 2); + goto word_zero_and_operation; + } + + default: + break; } return AS2 (and%L0,%2,%0); }") (define_insn "andhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (and:HI (match_operand:HI 1 "general_operand" "%0,0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "* @@ -3110,14 +3731,46 @@ operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); return AS2 (and%B0,%2,%h0); } + + /* use 32-bit ops on registers when there are no sign issues.. */ + if (REG_P (operands[0])) + { + if (!(INTVAL (operands[2]) & ~0x7fff)) + return AS2 (and%L0,%2,%k0); + } + } + + if (REG_P (operands[0]) + && i386_aligned_p (operands[2])) + { + CC_STATUS_INIT; + /* If op[2] is constant, we should zero-extend it and */ + /* make a note that op[0] has been zero-extended, so */ + /* that we could use 32-bit ops on it forthwith, but */ + /* there is no such reg-note available. Instead we do */ + /* a sign extension as that can result in shorter asm */ + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (and%L0,%k2,%k0); + } + + /* Use a 32-bit word with the upper bits set, invalidate CC */ + if (GET_CODE (operands[2]) == CONST_INT + && i386_aligned_p (operands[0])) + { + HOST_WIDE_INT val = INTVAL (operands[2]); + CC_STATUS_INIT; + val |= ~0xffff; + if (val != INTVAL (operands[2])) + operands[2] = GEN_INT (val); + return AS2 (and%L0,%k2,%k0); } return AS2 (and%W0,%2,%0); }") (define_insn "andqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (and:QI (match_operand:QI 1 "general_operand" "%0,0") + [(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);") @@ -3136,10 +3789,10 @@ "and%W0 %1,%0") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=q") + [(set (match_operand:SI 0 "register_operand" "=q") (and:SI (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")) - (match_operand:SI 2 "general_operand" "0")))] + (match_operand:SI 2 "register_operand" "0")))] "GET_CODE (operands[2]) == CONST_INT && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" "and%L0 %1,%0") @@ -3148,134 +3801,278 @@ ;;- Bit set (inclusive or) instructions -;; ??? What if we only change one byte of an offsettable memory reference? +;; This optimizes known byte-wide operations to memory, and in some cases +;; to QI registers.. Note that we don't want to use the QI registers too +;; aggressively, because often the 32-bit register instruction is the same +;; size, and likely to be faster on PentiumPro. (define_insn "iorsi3" - [(set (match_operand:SI 0 "general_operand" "=rm,r") - (ior:SI (match_operand:SI 1 "general_operand" "%0,0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + switch (GET_CODE (operands[2])) { - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & ~0xff) == 0) - { - CC_STATUS_INIT; + case CONST_INT: - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%b0); + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; + + /* don't try to optimize volatile accesses */ + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; - return AS2 (or%B0,%2,%b0); + intval = INTVAL (operands[2]); + if ((intval & ~0xff) == 0) + { + if (REG_P (operands[0])) + { + /* Do low byte access only for %eax or when high bit is set */ + if (REGNO (operands[0]) != 0 && !(intval & 0x80)) + break; + } + +byte_or_operation: + CC_STATUS_INIT; + + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + + if (intval == 0xff) + return AS2 (mov%B0,%2,%b0); + + return AS2 (or%B0,%2,%b0); } - if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) + /* second byte? */ + if ((intval & ~0xff00) == 0) { - CC_STATUS_INIT; - operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); + intval >>= 8; - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%h0); + if (REG_P (operands[0])) + { + CC_STATUS_INIT; + operands[2] = GEN_INT (intval); + if (intval == 0xff) + return AS2 (mov%B0,%2,%h0); + + return AS2 (or%B0,%2,%h0); + } + + operands[0] = adj_offsettable_operand (operands[0], 1); + goto byte_or_operation; + } + + if (REG_P (operands[0])) + break; - return AS2 (or%B0,%2,%h0); + /* third byte? */ + if ((intval & ~0xff0000) == 0) + { + intval >>= 16; + operands[0] = adj_offsettable_operand (operands[0], 2); + goto byte_or_operation; } + + /* fourth byte? */ + if ((intval & ~0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_or_operation; + } + + default: + break; } return AS2 (or%L0,%2,%0); }") (define_insn "iorhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (ior:HI (match_operand:HI 1 "general_operand" "%0,0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + switch (GET_CODE (operands[2])) { - /* Can we ignore the upper byte? */ - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & 0xff00) == 0) - { - CC_STATUS_INIT; - if (INTVAL (operands[2]) & 0xffff0000) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); + case CONST_INT: - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%b0); + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; + + /* don't try to optimize volatile accesses */ + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; + + intval = 0xffff & INTVAL (operands[2]); + + if ((intval & 0xff00) == 0) + { + if (REG_P (operands[0])) + { + /* Do low byte access only for %eax or when high bit is set */ + if (REGNO (operands[0]) != 0 && !(intval & 0x80)) + break; + } + +byte_or_operation: + CC_STATUS_INIT; - return AS2 (or%B0,%2,%b0); + if (intval == 0xff) + return AS2 (mov%B0,%2,%b0); + + return AS2 (or%B0,%2,%b0); } - /* Can we ignore the lower byte? */ - /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) - && (INTVAL (operands[2]) & 0xff) == 0) + /* high byte? */ + if ((intval & 0xff) == 0) { - CC_STATUS_INIT; - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); + intval >>= 8; + operands[2] = GEN_INT (intval); - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%h0); + if (REG_P (operands[0])) + { + CC_STATUS_INIT; + if (intval == 0xff) + return AS2 (mov%B0,%2,%h0); + + return AS2 (or%B0,%2,%h0); + } - return AS2 (or%B0,%2,%h0); + operands[0] = adj_offsettable_operand (operands[0], 1); + + goto byte_or_operation; } + + default: + break; + } + + if (REG_P (operands[0]) + && i386_aligned_p (operands[2])) + { + CC_STATUS_INIT; + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (or%L0,%k2,%k0); + } + + if (GET_CODE (operands[2]) == CONST_INT + && i386_aligned_p (operands[0])) + { + CC_STATUS_INIT; + intval = 0xffff & INTVAL (operands[2]); + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + return AS2 (or%L0,%2,%k0); } return AS2 (or%W0,%2,%0); }") (define_insn "iorqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (ior:QI (match_operand:QI 1 "general_operand" "%0,0") + [(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);") ;;- xor instructions -;; ??? What if we only change one byte of an offsettable memory reference? (define_insn "xorsi3" - [(set (match_operand:SI 0 "general_operand" "=rm,r") - (xor:SI (match_operand:SI 1 "general_operand" "%0,0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + switch (GET_CODE (operands[2])) { - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & ~0xff) == 0) - { - CC_STATUS_INIT; + case CONST_INT: - if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%b0); + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; - return AS2 (xor%B0,%2,%b0); + /* don't try to optimize volatile accesses */ + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; + + intval = INTVAL (operands[2]); + if ((intval & ~0xff) == 0) + { + if (REG_P (operands[0])) + { + /* Do low byte access only for %eax or when high bit is set */ + if (REGNO (operands[0]) != 0 && !(intval & 0x80)) + break; + } + +byte_xor_operation: + CC_STATUS_INIT; + + if (intval == 0xff) + return AS1 (not%B0,%b0); + + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + return AS2 (xor%B0,%2,%b0); } - if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) + /* second byte? */ + if ((intval & ~0xff00) == 0) { - CC_STATUS_INIT; - operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); + intval >>= 8; - if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%h0); + if (REG_P (operands[0])) + { + CC_STATUS_INIT; + if (intval == 0xff) + return AS1 (not%B0,%h0); - return AS2 (xor%B0,%2,%h0); + operands[2] = GEN_INT (intval); + return AS2 (xor%B0,%2,%h0); + } + + operands[0] = adj_offsettable_operand (operands[0], 1); + + goto byte_xor_operation; } + + if (REG_P (operands[0])) + break; + + /* third byte? */ + if ((intval & ~0xff0000) == 0) + { + intval >>= 16; + operands[0] = adj_offsettable_operand (operands[0], 2); + goto byte_xor_operation; + } + + /* fourth byte? */ + if ((intval & ~0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_xor_operation; + } + + default: + break; } return AS2 (xor%L0,%2,%0); }") (define_insn "xorhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (xor:HI (match_operand:HI 1 "general_operand" "%0,0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "* @@ -3305,23 +4102,143 @@ CC_STATUS_INIT; operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%h0); + if (INTVAL (operands[2]) == 0xff) + return AS1 (not%B0,%h0); + + return AS2 (xor%B0,%2,%h0); + } + } + + if (REG_P (operands[0]) + && i386_aligned_p (operands[2])) + { + CC_STATUS_INIT; + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (xor%L0,%k2,%k0); + } + + if (GET_CODE (operands[2]) == CONST_INT + && i386_aligned_p (operands[0])) + { + HOST_WIDE_INT intval; + CC_STATUS_INIT; + intval = 0xffff & INTVAL (operands[2]); + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + return AS2 (xor%L0,%2,%k0); + } + + return AS2 (xor%W0,%2,%0); +}") + +(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);") + +;; 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"))] + "" + "#") + +(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"))] + "" + "#") + +(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"))] + "" + "#") + +(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])); + } - return AS2 (xor%B0,%2,%h0); - } + else + { + emit_insn ((*genfunc) (low[0], low[0], low[2])); + emit_insn ((*genfunc) (high[0], high[0], high[2])); } - return AS2 (xor%W0,%2,%0); + DONE; }") -(define_insn "xorqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (xor:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qm")))] - "" - "* return AS2 (xor%B0,%2,%0);") - ;;- negation instructions (define_insn "negdi2" @@ -3345,50 +4262,50 @@ }") (define_insn "negsi2" - [(set (match_operand:SI 0 "general_operand" "=rm") - (neg:SI (match_operand:SI 1 "general_operand" "0")))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] "" "neg%L0 %0") (define_insn "neghi2" - [(set (match_operand:HI 0 "general_operand" "=rm") - (neg:HI (match_operand:HI 1 "general_operand" "0")))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] "" "neg%W0 %0") (define_insn "negqi2" - [(set (match_operand:QI 0 "general_operand" "=qm") - (neg:QI (match_operand:QI 1 "general_operand" "0")))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))] "" "neg%B0 %0") (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "general_operand" "0")))] + (neg:SF (match_operand:SF 1 "register_operand" "0")))] "TARGET_80387" "fchs") (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "general_operand" "0")))] + (neg:DF (match_operand:DF 1 "register_operand" "0")))] "TARGET_80387" "fchs") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] + (neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" "fchs") (define_insn "negxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (match_operand:XF 1 "general_operand" "0")))] + (neg:XF (match_operand:XF 1 "register_operand" "0")))] "TARGET_80387" "fchs") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] + (neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] "TARGET_80387" "fchs") @@ -3396,44 +4313,48 @@ (define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") - (abs:SF (match_operand:SF 1 "general_operand" "0")))] + (abs:SF (match_operand:SF 1 "register_operand" "0")))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (match_operand:DF 1 "general_operand" "0")))] + (abs:DF (match_operand:DF 1 "register_operand" "0")))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] + (abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "absxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (match_operand:XF 1 "general_operand" "0")))] + (abs:XF (match_operand:XF 1 "register_operand" "0")))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] + (abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] + (sqrt:DF (match_operand:DF 1 "register_operand" "0")))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") @@ -3441,14 +4362,13 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (float_extend:DF - (match_operand:SF 1 "general_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (match_operand:SF 1 "register_operand" "0"))))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "sqrtxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (sqrt:XF (match_operand:XF 1 "general_operand" "0")))] + (sqrt:XF (match_operand:XF 1 "register_operand" "0")))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") @@ -3456,94 +4376,84 @@ (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF - (match_operand:DF 1 "general_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (match_operand:DF 1 "register_operand" "0"))))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF - (match_operand:SF 1 "general_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (match_operand:SF 1 "register_operand" "0"))))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "sindf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "sinsf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "sinxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "cosdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") (define_insn "cossf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") (define_insn "cosxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") ;;- one complement instructions (define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "general_operand" "=rm") - (not:SI (match_operand:SI 1 "general_operand" "0")))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] "" "not%L0 %0") (define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "general_operand" "=rm") - (not:HI (match_operand:HI 1 "general_operand" "0")))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] "" "not%W0 %0") (define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "general_operand" "=qm") - (not:QI (match_operand:QI 1 "general_operand" "0")))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))] "" "not%B0 %0") @@ -3565,8 +4475,7 @@ ;; separately, making all shifts emit pairs of shift double and normal ;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to ;; support a 63 bit shift, each shift where the count is in a reg expands -;; to three pairs. If the overall shift is by N bits, then the first two -;; pairs shift by N / 2 and the last pair by N & 1. +;; to a pair of shifts, a branch, a shift by 32 and a label. ;; If the shift count is a constant, we need never emit more than one ;; shift pair, instead using moves and sign extension for counts greater @@ -3596,7 +4505,7 @@ [(set (match_operand:DI 0 "register_operand" "=&r") (ashift:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] - "" + "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" "* { rtx xops[4], low[1], high[1]; @@ -3631,35 +4540,29 @@ (define_insn "ashldi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c"))) - (clobber (match_dup 2))] + (match_operand:QI 2 "register_operand" "c")))] "" "* { - rtx xops[4], low[1], high[1]; + rtx xops[5], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; - xops[1] = const1_rtx; + xops[1] = GEN_INT (32); xops[2] = low[0]; xops[3] = high[0]; - - output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ - - output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); - output_asm_insn (AS2 (sal%L2,%0,%2), xops); - output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); - output_asm_insn (AS2 (sal%L2,%0,%2), xops); - - xops[1] = GEN_INT (7); /* shift count & 1 */ - - output_asm_insn (AS2 (shr%B0,%1,%0), xops); + xops[4] = gen_label_rtx (); output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); output_asm_insn (AS2 (sal%L2,%0,%2), xops); - + output_asm_insn (AS2 (test%B0,%1,%b0), xops); + output_asm_insn (AS1 (je,%X4), xops); + output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ + output_asm_insn (AS2 (xor%L2,%2,%2), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (xops[4])); RET; }") @@ -3668,15 +4571,15 @@ ;; is smaller - use leal for now unless the shift count is 1. (define_insn "ashlsi3" - [(set (match_operand:SI 0 "general_operand" "=r,rm") - (ashift:SI (match_operand:SI 1 "general_operand" "r,0") + [(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")))] "" "* { if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) { - if (!TARGET_386 && INTVAL (operands[2]) == 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); @@ -3690,8 +4593,8 @@ 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]))); + operands[1] = gen_rtx_MULT (SImode, operands[1], + GEN_INT (1 << INTVAL (operands[2]))); return AS2 (lea%L0,%a1,%0); } } @@ -3706,8 +4609,8 @@ }") (define_insn "ashlhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (ashift:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -3722,8 +4625,8 @@ }") (define_insn "ashlqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (ashift:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -3759,11 +4662,36 @@ DONE; }") +(define_insn "ashldi3_32" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m") + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") + (const_int 32)))] + "" + "* +{ + rtx low[2], high[2], xops[4]; + + split_di (operands, 2, low, high); + xops[0] = high[0]; + xops[1] = low[1]; + xops[2] = low[0]; + xops[3] = const0_rtx; + if (!rtx_equal_p (xops[0], xops[1])) + 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_insn "ashrdi3_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] - "" + "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" "* { rtx xops[4], low[1], high[1]; @@ -3800,41 +4728,36 @@ (define_insn "ashrdi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c"))) - (clobber (match_dup 2))] + (match_operand:QI 2 "register_operand" "c")))] "" "* { - rtx xops[4], low[1], high[1]; + rtx xops[5], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; - xops[1] = const1_rtx; + xops[1] = GEN_INT (32); xops[2] = low[0]; xops[3] = high[0]; - - output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ - - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%0,%3), xops); - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%0,%3), xops); - - xops[1] = GEN_INT (7); /* shift count & 1 */ - - output_asm_insn (AS2 (shr%B0,%1,%0), xops); + xops[4] = gen_label_rtx (); output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); output_asm_insn (AS2 (sar%L3,%0,%3), xops); - + output_asm_insn (AS2 (test%B0,%1,%b0), xops); + output_asm_insn (AS1 (je,%X4), xops); + xops[1] = GEN_INT (31); + output_asm_insn (AS2 (mov%L2,%3,%2), xops); + output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (xops[4])); RET; }") (define_insn "ashrsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -3846,8 +4769,8 @@ }") (define_insn "ashrhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -3859,8 +4782,8 @@ }") (define_insn "ashrqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -3895,11 +4818,36 @@ DONE; }") +(define_insn "lshrdi3_32" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m") + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") + (const_int 32)))] + "" + "* +{ + rtx low[2], high[2], xops[4]; + + split_di (operands, 2, low, high); + xops[0] = low[0]; + xops[1] = high[1]; + xops[2] = high[0]; + xops[3] = const0_rtx; + if (!rtx_equal_p (xops[0], xops[1])) + 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_insn "lshrdi3_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] - "" + "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" "* { rtx xops[4], low[1], high[1]; @@ -3935,41 +4883,35 @@ (define_insn "lshrdi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c"))) - (clobber (match_dup 2))] + (match_operand:QI 2 "register_operand" "c")))] "" "* { - rtx xops[4], low[1], high[1]; + rtx xops[5], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; - xops[1] = const1_rtx; + xops[1] = GEN_INT (32); xops[2] = low[0]; xops[3] = high[0]; - - output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ - - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (shr%L3,%0,%3), xops); - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (shr%L3,%0,%3), xops); - - xops[1] = GEN_INT (7); /* shift count & 1 */ - - output_asm_insn (AS2 (shr%B0,%1,%0), xops); + xops[4] = gen_label_rtx (); output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); output_asm_insn (AS2 (shr%L3,%0,%3), xops); - + output_asm_insn (AS2 (test%B0,%1,%b0), xops); + output_asm_insn (AS1 (je,%X4), xops); + output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ + output_asm_insn (AS2 (xor%L3,%3,%3), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (xops[4])); RET; }") (define_insn "lshrsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -3981,8 +4923,8 @@ }") (define_insn "lshrhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -3994,8 +4936,8 @@ }") (define_insn "lshrqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -4009,8 +4951,8 @@ ;;- rotate instructions (define_insn "rotlsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (rotate:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -4022,8 +4964,8 @@ }") (define_insn "rotlhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (rotate:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -4035,8 +4977,8 @@ }") (define_insn "rotlqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (rotate:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -4048,8 +4990,8 @@ }") (define_insn "rotrsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -4061,8 +5003,8 @@ }") (define_insn "rotrhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -4074,8 +5016,8 @@ }") (define_insn "rotrqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (rotatert:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -4090,11 +5032,13 @@ ;; This usually looses. But try a define_expand to recognize a few case ;; we can do efficiently, such as accessing the "high" QImode registers, ;; %ah, %bh, %ch, %dh. +;; ??? Note this has a botch on the mode of operand 0, which needs to be +;; fixed if this is ever enabled. (define_insn "insv" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r") - (match_operand:SI 1 "general_operand" "i") - (match_operand:SI 2 "general_operand" "i")) - (match_operand:SI 3 "general_operand" "ri"))] + (match_operand:SI 1 "immediate_operand" "i") + (match_operand:SI 2 "immediate_operand" "i")) + (match_operand:SI 3 "nonmemory_operand" "ri"))] "" "* { @@ -4110,7 +5054,7 @@ } else { - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0])); + operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); if (INTVAL (operands[2])) output_asm_insn (AS2 (ror%L0,%2,%0), operands); output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); @@ -4130,7 +5074,7 @@ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "immediate_operand" "") (match_operand:SI 2 "immediate_operand" "")) - (match_operand:QI 3 "general_operand" "ri"))] + (match_operand:QI 3 "nonmemory_operand" "ri"))] "" " { @@ -4143,22 +5087,6 @@ && ! INTVAL (operands[1]) == 1) FAIL; }") - -;; ??? Are these constraints right? -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo") - (const_int 8) - (const_int 8)) - (match_operand:QI 1 "general_operand" "qn"))] - "" - "* -{ - if (REG_P (operands[0])) - return AS2 (mov%B0,%1,%h0); - - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (mov%B0,%1,%0); -}") */ ;; On i386, the register count for a bit operation is *not* truncated, @@ -4173,11 +5101,11 @@ ;; General bit set and clear. (define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm") + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm") (const_int 1) - (match_operand:SI 2 "general_operand" "r")) + (match_operand:SI 2 "register_operand" "r")) (match_operand:SI 3 "const_int_operand" "n"))] - "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" + "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4191,11 +5119,11 @@ ;; Bit complement. See comments on previous pattern. ;; ??? Is this really worthwhile? (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (xor:SI (ashift:SI (const_int 1) - (match_operand:SI 1 "general_operand" "r")) - (match_operand:SI 2 "general_operand" "0")))] - "TARGET_386 && GET_CODE (operands[1]) != CONST_INT" + (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "nonimmediate_operand" "0")))] + "TARGET_USE_BIT_TEST && GET_CODE (operands[1]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4204,11 +5132,11 @@ }") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") - (xor:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "0") (ashift:SI (const_int 1) - (match_operand:SI 2 "general_operand" "r"))))] - "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" + (match_operand:SI 2 "register_operand" "r"))))] + "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4229,7 +5157,7 @@ (define_insn "" [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") (const_int 1) - (match_operand:SI 1 "general_operand" "r")))] + (match_operand:SI 1 "register_operand" "r")))] "GET_CODE (operands[1]) != CONST_INT" "* { @@ -4272,7 +5200,7 @@ ;; The CPU may access unspecified bytes around the actual target byte. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm") + [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n")))] "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])" @@ -4403,7 +5331,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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); @@ -4435,7 +5364,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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\"); @@ -4467,7 +5397,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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\"); @@ -4499,7 +5430,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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); @@ -4553,6 +5485,14 @@ 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\"; }") @@ -4585,6 +5525,14 @@ 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\"; }") @@ -4607,9 +5555,17 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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); }") @@ -4651,9 +5607,17 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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\"); }") @@ -4695,9 +5659,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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\"); }") @@ -4739,8 +5710,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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); }") @@ -4778,6 +5757,13 @@ 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\"; }") @@ -4793,6 +5779,13 @@ 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\"; }") @@ -4805,9 +5798,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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); }") @@ -4829,8 +5829,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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 (je,%l0); + } OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); }") @@ -4853,9 +5861,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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\"); }") @@ -4877,9 +5892,17 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + 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); }") @@ -4901,7 +5924,7 @@ "jmp %l0") (define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "general_operand" "rm"))] + [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))] "" "* { @@ -4929,7 +5952,7 @@ (define_insn "" [(set (pc) (if_then_else (match_operator 0 "arithmetic_comparison_operator" - [(plus:SI (match_operand:SI 1 "general_operand" "+r,m") + [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m") (match_operand:SI 2 "general_operand" "rmi,ri")) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -4944,7 +5967,7 @@ if (operands[2] == constm1_rtx) output_asm_insn (AS1 (dec%L1,%1), operands); - else if (operands[1] == const1_rtx) + else if (operands[2] == const1_rtx) output_asm_insn (AS1 (inc%L1,%1), operands); else @@ -4956,7 +5979,7 @@ (define_insn "" [(set (pc) (if_then_else (match_operator 0 "arithmetic_comparison_operator" - [(minus:SI (match_operand:SI 1 "general_operand" "+r,m") + [(minus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m") (match_operand:SI 2 "general_operand" "rmi,ri")) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -4980,6 +6003,110 @@ return AS1 (%J0,%l3); }") +(define_insn "" + [(set (pc) + (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = const1_rtx; + output_asm_insn (AS2 (sub%L0,%2,%0), operands); + return \"jnc %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = const1_rtx; + output_asm_insn (AS2 (sub%L0,%2,%0), operands); + return \"jc %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (dec%L0,%0), operands); + return \"jnz %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (dec%L0,%0), operands); + return \"jz %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (inc%L0,%0), operands); + return \"jnz %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (inc%L0,%0), operands); + return \"jz %l1\"; +}") + ;; Implement switch statements when generating PIC code. Switches are ;; implemented by `tablejump' when not using -fpic. @@ -4987,10 +6114,12 @@ (define_expand "casesi" [(set (match_dup 5) - (minus:SI (match_operand:SI 0 "general_operand" "") + (match_operand:SI 0 "general_operand" "")) + (set (match_dup 6) + (minus:SI (match_dup 5) (match_operand:SI 1 "general_operand" ""))) (set (cc0) - (compare:CC (match_dup 5) + (compare:CC (match_dup 6) (match_operand:SI 2 "general_operand" ""))) (set (pc) (if_then_else (gtu (cc0) @@ -5000,14 +6129,15 @@ (parallel [(set (pc) (minus:SI (reg:SI 3) - (mem:SI (plus:SI (mult:SI (match_dup 5) + (mem:SI (plus:SI (mult:SI (match_dup 6) (const_int 4)) (label_ref (match_operand 3 "" "")))))) - (clobber (match_scratch:SI 6 ""))])] + (clobber (match_scratch:SI 7 ""))])] "flag_pic" " { operands[5] = gen_reg_rtx (SImode); + operands[6] = gen_reg_rtx (SImode); current_function_uses_pic_offset_table = 1; }") @@ -5061,12 +6191,12 @@ output_asm_insn (AS2 (mov%L2,%3,%2), xops); output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); output_asm_insn (AS1 (jmp,%*%2), xops); - ASM_OUTPUT_ALIGN_CODE (asm_out_file); + ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps); RET; }") (define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "general_operand" "rm")) + [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm")) (use (label_ref (match_operand 1 "" "")))] "" "* @@ -5312,9 +6442,10 @@ coprocessor registers as containing a possible return value, simply pretend the untyped call returns a complex long double value. */ + emit_call_insn (TARGET_80387 - ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG), - operands[0], const0_rtx) + ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG), + operands[0], const0_rtx) : gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) @@ -5329,34 +6460,163 @@ point. */ emit_insn (gen_blockage ()); - DONE; + DONE; +}") + +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] + "" + "") + +;; 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. +;; See comments for simple_386_epilogue in i386.c. + +(define_expand "return" + [(return)] + "ix86_can_use_return_insn_p ()" + "") + +(define_insn "return_internal" + [(return)] + "reload_completed" + "ret") + +(define_insn "return_pop_internal" + [(return) + (use (match_operand:SI 0 "const_int_operand" ""))] + "reload_completed" + "ret %0") + +(define_insn "nop" + [(const_int 0)] + "" + "nop") + +(define_expand "prologue" + [(const_int 1)] + "" + " +{ + ix86_expand_prologue (); + DONE; +}") + +;; The use of UNSPEC here is currently not necessary - a simple SET of ebp +;; to itself would be enough. But this way we are safe even if some optimizer +;; becomes too clever in the future. +(define_insn "prologue_set_stack_ptr" + [(set (reg:SI 7) + (minus:SI (reg:SI 7) (match_operand:SI 0 "immediate_operand" "i"))) + (set (reg:SI 6) (unspec:SI [(reg:SI 6)] 4))] + "" + "* +{ + rtx xops [2]; + + xops[0] = operands[0]; + xops[1] = stack_pointer_rtx; + output_asm_insn (AS2 (sub%L1,%0,%1), xops); + RET; +}") + +(define_insn "prologue_set_got" + [(set (match_operand:SI 0 "" "") + (unspec_volatile + [(plus:SI (match_dup 0) + (plus:SI (match_operand:SI 1 "symbolic_operand" "") + (minus:SI (pc) (match_operand 2 "" ""))))] 1))] + "" + "* +{ + char buffer[64]; + + if (TARGET_DEEP_BRANCH_PREDICTION) + { + sprintf (buffer, \"addl %s,%%0\", XSTR (operands[1], 0)); + output_asm_insn (buffer, operands); + } + else + { + sprintf (buffer, \"addl %s+[.-%%X2],%%0\", XSTR (operands[1], 0)); + output_asm_insn (buffer, operands); + } + RET; +}") + +(define_insn "prologue_get_pc" + [(set (match_operand:SI 0 "" "") + (unspec_volatile [(plus:SI (pc) (match_operand 1 "" ""))] 2))] + "" + "* +{ + 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; }") -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] +(define_insn "prologue_get_pc_and_set_got" + [(unspec_volatile [(match_operand:SI 0 "" "")] 3)] "" - "") + "* +{ + operands[1] = gen_label_rtx (); + output_asm_insn (AS1 (call,%X1), operands); + 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); + RET; +}") -;; 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. -;; See comments for simple_386_epilogue in i386.c. +(define_expand "epilogue" + [(const_int 1)] + "" + " +{ + ix86_expand_epilogue (); + DONE; +}") -(define_insn "return" - [(return)] - "simple_386_epilogue ()" +(define_insn "epilogue_set_stack_ptr" + [(set (reg:SI 7) (reg:SI 6)) + (clobber (reg:SI 6))] + "" "* { - function_epilogue (asm_out_file, get_frame_size ()); - RET; + rtx xops [2]; + + xops[0] = frame_pointer_rtx; + xops[1] = stack_pointer_rtx; + output_asm_insn (AS2 (mov%L0,%0,%1), xops); + RET; }") -(define_insn "nop" - [(const_int 0)] +(define_insn "leave" + [(const_int 2) + (clobber (reg:SI 6)) + (clobber (reg:SI 7))] "" - "nop") + "leave") + +(define_insn "pop" + [(set (match_operand:SI 0 "register_operand" "r") + (mem:SI (reg:SI 7))) + (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))] + "" + "* +{ + output_asm_insn (AS1 (pop%L0,%P0), operands); + RET; +}") (define_expand "movstrsi" [(parallel [(set (match_operand:BLK 0 "memory_operand" "") @@ -5380,8 +6640,8 @@ operands[5] = addr0; operands[6] = addr1; - operands[0] = gen_rtx (MEM, BLKmode, addr0); - operands[1] = gen_rtx (MEM, BLKmode, addr1); + operands[0] = change_address (operands[0], VOIDmode, addr0); + operands[1] = change_address (operands[1], VOIDmode, addr1); }") ;; It might seem that operands 0 & 1 could use predicate register_operand. @@ -5426,6 +6686,73 @@ RET; }") +(define_expand "clrstrsi" + [(set (match_dup 3) (const_int 0)) + (parallel [(set (match_operand:BLK 0 "memory_operand" "") + (const_int 0)) + (use (match_operand:SI 1 "const_int_operand" "")) + (use (match_operand:SI 2 "const_int_operand" "")) + (use (match_dup 3)) + (clobber (match_scratch:SI 4 "")) + (clobber (match_dup 5))])] + "" + " +{ + rtx addr0, addr1; + + if (GET_CODE (operands[1]) != CONST_INT) + FAIL; + + addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); + + operands[3] = gen_reg_rtx (SImode); + operands[5] = addr0; + + operands[0] = gen_rtx_MEM (BLKmode, addr0); +}") + +;; It might seem that operand 0 could use predicate register_operand. +;; But strength reduction might offset the MEM expression. So we let +;; reload put the address into %edi. + +(define_insn "" + [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) + (const_int 0)) + (use (match_operand:SI 1 "const_int_operand" "n")) + (use (match_operand:SI 2 "immediate_operand" "i")) + (use (match_operand:SI 3 "register_operand" "a")) + (clobber (match_scratch:SI 4 "=&c")) + (clobber (match_dup 0))] + "" + "* +{ + rtx xops[2]; + + output_asm_insn (\"cld\", operands); + if (GET_CODE (operands[1]) == CONST_INT) + { + if (INTVAL (operands[1]) & ~0x03) + { + xops[0] = GEN_INT ((INTVAL (operands[1]) >> 2) & 0x3fffffff); + xops[1] = operands[4]; + + output_asm_insn (AS2 (mov%L1,%0,%1), xops); +#ifdef INTEL_SYNTAX + output_asm_insn (\"rep stosd\", xops); +#else + output_asm_insn (\"rep\;stosl\", xops); +#endif + } + if (INTVAL (operands[1]) & 0x02) + output_asm_insn (\"stosw\", operands); + if (INTVAL (operands[1]) & 0x01) + output_asm_insn (\"stosb\", operands); + } + else + abort (); + RET; +}") + (define_expand "cmpstrsi" [(parallel [(set (match_operand:SI 0 "general_operand" "") (compare:SI (match_operand:BLK 1 "general_operand" "") @@ -5447,8 +6774,8 @@ operands[5] = addr1; operands[6] = addr2; - operands[1] = gen_rtx (MEM, BLKmode, addr1); - operands[2] = gen_rtx (MEM, BLKmode, addr2); + operands[1] = gen_rtx_MEM (BLKmode, addr1); + operands[2] = gen_rtx_MEM (BLKmode, addr2); }") @@ -5464,7 +6791,7 @@ ;; code to handle zero-length compares. (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=&r") + [(set (match_operand:SI 0 "register_operand" "=&r") (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S")) (mem:BLK (match_operand:SI 2 "address_operand" "D")))) (use (match_operand:SI 3 "register_operand" "c")) @@ -5475,7 +6802,7 @@ "" "* { - rtx xops[4], label; + rtx xops[2], label; label = gen_label_rtx (); @@ -5485,16 +6812,13 @@ output_asm_insn (\"je %l0\", &label); xops[0] = operands[0]; - xops[1] = gen_rtx (MEM, QImode, - gen_rtx (PLUS, SImode, operands[1], constm1_rtx)); - xops[2] = gen_rtx (MEM, QImode, - gen_rtx (PLUS, SImode, operands[2], constm1_rtx)); - xops[3] = operands[3]; - - output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops); - output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops); - - output_asm_insn (AS2 (sub%L0,%3,%0), xops); + xops[1] = const1_rtx; + output_asm_insn (AS2 (sbb%L0,%0,%0), xops); + if (QI_REG_P (xops[0])) + output_asm_insn (AS2 (or%B0,%1,%b0), xops); + else + output_asm_insn (AS2 (or%L0,%1,%0), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); RET; }") @@ -5515,7 +6839,7 @@ cc_status.flags |= CC_NOT_SIGNED; - xops[0] = gen_rtx (REG, QImode, 0); + xops[0] = gen_rtx_REG (QImode, 0); xops[1] = CONST0_RTX (QImode); output_asm_insn (\"cld\", operands); @@ -5523,101 +6847,64 @@ return \"repz\;cmps%B2\"; }") -(define_expand "ffssi2" - [(set (match_dup 2) - (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "")) - (const_int -1))) - (set (match_operand:SI 0 "general_operand" "") - (plus:SI (match_dup 2) (const_int 1)))] - "" - "operands[2] = gen_reg_rtx (SImode);") - + ;; Note, you cannot optimize away the branch following the bsfl by assuming ;; that the destination is not modified if the input is 0, since not all ;; x86 implementations do this. -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=&r") - (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm")) - (const_int -1)))] +(define_expand "ffssi2" + [(set (match_operand:SI 0 "general_operand" "") + (ffs:SI (match_operand:SI 1 "general_operand" "")))] "" - "* + " { - rtx xops[3]; - static int ffssi_label_number; - char buffer[30]; + rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode); - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = constm1_rtx; - output_asm_insn (AS2 (bsf%L0,%1,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"jnz %sLFFSSI%d\", - LOCAL_LABEL_PREFIX, ffssi_label_number); -#else - sprintf (buffer, \"jnz %sLFFSSI%d\", - \"\", ffssi_label_number); -#endif - output_asm_insn (buffer, xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"%sLFFSSI%d:\", - LOCAL_LABEL_PREFIX, ffssi_label_number); -#else - sprintf (buffer, \"%sLFFSSI%d:\", - \"\", ffssi_label_number); -#endif - output_asm_insn (buffer, xops); + emit_insn (gen_ffssi_1 (temp, operands[1])); + emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0); + emit_jump_insn (gen_bne (label)); + emit_move_insn (temp, constm1_rtx); + emit_label (label); + temp = expand_binop (SImode, add_optab, temp, const1_rtx, + operands[0], 0, OPTAB_WIDEN); - ffssi_label_number++; - return \"\"; + if (temp != operands[0]) + emit_move_insn (operands[0], temp); + DONE; }") -(define_expand "ffshi2" - [(set (match_dup 2) - (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" "")) - (const_int -1))) - (set (match_operand:HI 0 "general_operand" "") - (plus:HI (match_dup 2) (const_int 1)))] +(define_insn "ffssi_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))] "" - "operands[2] = gen_reg_rtx (HImode);") + "* return AS2 (bsf%L0,%1,%0);") -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=&r") - (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm")) - (const_int -1)))] +(define_expand "ffshi2" + [(set (match_operand:SI 0 "general_operand" "") + (ffs:HI (match_operand:HI 1 "general_operand" "")))] "" - "* + " { - rtx xops[3]; - static int ffshi_label_number; - char buffer[30]; + rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode); - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = constm1_rtx; - output_asm_insn (AS2 (bsf%W0,%1,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"jnz %sLFFSHI%d\", - LOCAL_LABEL_PREFIX, ffshi_label_number); -#else - sprintf (buffer, \"jnz %sLFFSHI%d\", - \"\", ffshi_label_number); -#endif - output_asm_insn (buffer, xops); - output_asm_insn (AS2 (mov%W0,%2,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"%sLFFSHI%d:\", - LOCAL_LABEL_PREFIX, ffshi_label_number); -#else - sprintf (buffer, \"%sLFFSHI%d:\", - \"\", ffshi_label_number); -#endif - output_asm_insn (buffer, xops); + emit_insn (gen_ffshi_1 (temp, operands[1])); + emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0); + emit_jump_insn (gen_bne (label)); + emit_move_insn (temp, constm1_rtx); + emit_label (label); + temp = expand_binop (HImode, add_optab, temp, const1_rtx, + operands[0], 0, OPTAB_WIDEN); - ffshi_label_number++; - return \"\"; + if (temp != operands[0]) + emit_move_insn (operands[0], temp); + DONE; }") + +(define_insn "ffshi_1" + [(set (match_operand:HI 0 "register_operand" "=r") + (unspec:HI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))] + "" + "* return AS2 (bsf%W0,%1,%0);") ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and @@ -5633,81 +6920,171 @@ [(match_operand:DF 1 "nonimmediate_operand" "0,fm") (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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") (match_operator:DF 3 "binary_387_op" - [(float:DF (match_operand:SI 1 "general_operand" "rm")) - (match_operand:DF 2 "general_operand" "0")]))] + [(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);") + "* 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 "nonimmediate_operand" "0,f") - (match_operand:XF 2 "nonimmediate_operand" "f,0")]))] + [(match_operand:XF 1 "register_operand" "0,f") + (match_operand:XF 2 "register_operand" "f,0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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") (match_operator:XF 3 "binary_387_op" - [(float:XF (match_operand:SI 1 "general_operand" "rm")) - (match_operand:XF 2 "general_operand" "0")]))] + [(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);") + "* 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 "general_operand" "fm,0")) - (match_operand:XF 2 "general_operand" "0,f")]))] + [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + (match_operand:XF 2 "register_operand" "0,f")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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") (match_operator:XF 3 "binary_387_op" - [(match_operand:XF 1 "general_operand" "0") - (float:XF (match_operand:SI 2 "general_operand" "rm"))]))] + [(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);") + "* 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 "general_operand" "0,f") + [(match_operand:XF 1 "register_operand" "0,f") (float_extend:XF - (match_operand:SF 2 "general_operand" "fm,0"))]))] + (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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" - [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0")) - (match_operand:DF 2 "general_operand" "0,f")]))] + [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + (match_operand:DF 2 "register_operand" "0,f")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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") (match_operator:DF 3 "binary_387_op" - [(match_operand:DF 1 "general_operand" "0") - (float:DF (match_operand:SI 2 "general_operand" "rm"))]))] + [(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);") + "* 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 "general_operand" "0,f") + [(match_operand:DF 1 "register_operand" "0,f") (float_extend:DF - (match_operand:SF 2 "general_operand" "fm,0"))]))] + (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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,f") @@ -5715,38 +7092,106 @@ [(match_operand:SF 1 "nonimmediate_operand" "0,fm") (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* 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" - [(float:SF (match_operand:SI 1 "general_operand" "rm")) - (match_operand:SF 2 "general_operand" "0")]))] + [(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);") + "* 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 "general_operand" "0") - (float:SF (match_operand:SI 2 "general_operand" "rm"))]))] + [(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);") + "* 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) (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" "")) - (match_operand:QI 2 "register_operand" "") + (match_operand:QI 2 "immediate_operand" "") (match_operand:SI 3 "immediate_operand" "")] 0)) (clobber (match_dup 1))]) (set (match_dup 5) (not:SI (match_dup 4))) (set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_dup 5) - (const_int 1)))] + (plus:SI (match_dup 5) + (const_int -1)))] "" " { + if (TARGET_UNROLL_STRLEN && operands[2] == const0_rtx && optimize > 1) + { + rtx address; + rtx scratch; + + /* well it seems that some optimizer does not combine a call like + foo(strlen(bar), strlen(bar)); + when the move and the subtraction is done here. It does calculate + the length just once when these instructions are done inside of + output_strlen_unroll(). But I think since &bar[strlen(bar)] is + often used and I use one fewer register for the lifetime of + output_strlen_unroll() this is better. */ + scratch = gen_reg_rtx (SImode); + address = force_reg (SImode, XEXP (operands[1], 0)); + + /* move address to scratch-register + this is done here because the i586 can do the following and + in the same cycle with the following move. */ + if (GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) < 4) + emit_insn (gen_movsi (scratch, address)); + + emit_insn (gen_movsi (operands[0], address)); + + if(TARGET_USE_Q_REG) + emit_insn (gen_strlensi_unroll5 (operands[0], + operands[3], + scratch, + operands[0])); + else + emit_insn (gen_strlensi_unroll4 (operands[0], + operands[3], + scratch, + operands[0])); + + /* gen_strlensi_unroll[45] returns the address of the zero + at the end of the string, like memchr(), so compute the + length by subtracting the startaddress. */ + emit_insn (gen_subsi3 (operands[0], operands[0], address)); + DONE; + } + operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); operands[4] = gen_reg_rtx (SImode); operands[5] = gen_reg_rtx (SImode); @@ -5759,7 +7204,7 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=&c") (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D")) - (match_operand:QI 2 "register_operand" "a") + (match_operand:QI 2 "immediate_operand" "a") (match_operand:SI 3 "immediate_operand" "i")] 0)) (clobber (match_dup 1))] "" @@ -5773,3 +7218,601 @@ output_asm_insn (AS2 (mov%L0,%1,%0), xops); return \"repnz\;scas%B2\"; }") + +/* Conditional move define_insns. */ + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "nonimmediate_operand" "") + (match_operand:SI 3 "nonimmediate_operand" "")))] + "TARGET_CMOVE" + " +{ + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE" + "#") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" + "#") + +(define_split + [(set (match_operand:SI 0 "register_operand" "=r,r") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:SI 0 "register_operand" "=r,r") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 2 "nonimmediate_operand" "rm,0") + (match_operand:SI 3 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + "* return output_int_conditional_move (which_alternative, operands);") + +(define_expand "movhicc" + [(set (match_operand:HI 0 "register_operand" "") + (if_then_else:HI (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "nonimmediate_operand" "")))] + "TARGET_CMOVE" + " +{ + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); +}") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE" + "#") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" + "#") + +(define_split + [(set (match_operand:HI 0 "register_operand" "=r,r") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:HI 0 "register_operand" "=r,r") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:HI 2 "nonimmediate_operand" "rm,0") + (match_operand:HI 3 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + "* return output_int_conditional_move (which_alternative, operands);") + +(define_expand "movsfcc" + [(set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "register_operand" "") + (match_operand:SF 3 "register_operand" "")))] + "TARGET_CMOVE" + " +{ + rtx temp; + + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + /* The floating point conditional move instructions don't directly + support conditions resulting from a signed integer comparison. */ + + switch (GET_CODE (operands[1])) + { + case LT: + case LE: + case GE: + case GT: + temp = emit_store_flag (gen_reg_rtx (QImode), + GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, + VOIDmode, 0, 0); + + if (!temp) + FAIL; + + operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); + break; + + default: + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); + break; + } +}") + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:SF 4 "register_operand" "f,f,0,0") + (match_operand:SF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:SF 4 "register_operand" "f,f,0,0") + (match_operand:SF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_split + [(set (match_operand:SF 0 "register_operand" "=f,f") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:SF 0 "register_operand" "=f,f") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SF 2 "register_operand" "f,0") + (match_operand:SF 3 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + "* return output_fp_conditional_move (which_alternative, operands);") + +(define_expand "movdfcc" + [(set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (match_operand 1 "comparison_operator" "") + (match_operand:DF 2 "register_operand" "") + (match_operand:DF 3 "register_operand" "")))] + "TARGET_CMOVE" + " +{ + rtx temp; + + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + /* The floating point conditional move instructions don't directly + support conditions resulting from a signed integer comparison. */ + + switch (GET_CODE (operands[1])) + { + case LT: + case LE: + case GE: + case GT: + temp = emit_store_flag (gen_reg_rtx (QImode), + GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, + VOIDmode, 0, 0); + + if (!temp) + FAIL; + + operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); + break; + + default: + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); + break; + } +}") + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:DF 4 "register_operand" "f,f,0,0") + (match_operand:DF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:DF 4 "register_operand" "f,f,0,0") + (match_operand:DF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_split + [(set (match_operand:DF 0 "register_operand" "=f,f") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:DF 0 "register_operand" "=f,f") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:DF 2 "register_operand" "f,0") + (match_operand:DF 3 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + "* return output_fp_conditional_move (which_alternative, operands);") + +(define_expand "movxfcc" + [(set (match_operand:XF 0 "register_operand" "") + (if_then_else:XF (match_operand 1 "comparison_operator" "") + (match_operand:XF 2 "register_operand" "") + (match_operand:XF 3 "register_operand" "")))] + "TARGET_CMOVE" + " +{ + rtx temp; + + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + /* The floating point conditional move instructions don't directly + support conditions resulting from a signed integer comparison. */ + + switch (GET_CODE (operands[1])) + { + case LT: + case LE: + case GE: + case GT: + temp = emit_store_flag (gen_reg_rtx (QImode), + GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, + VOIDmode, 0, 0); + + if (!temp) + FAIL; + + operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); + break; + + default: + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); + break; + } +}") + +(define_insn "" + [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:XF 4 "register_operand" "f,f,0,0") + (match_operand:XF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_insn "" + [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:XF 4 "register_operand" "f,f,0,0") + (match_operand:XF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_split + [(set (match_operand:XF 0 "register_operand" "=f,f") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:XF 0 "register_operand" "=f,f") + (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")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:XF 0 "register_operand" "=f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:XF 2 "register_operand" "f,0") + (match_operand:XF 3 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + "* return output_fp_conditional_move (which_alternative, operands);") + +(define_expand "movdicc" + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (match_operand 1 "comparison_operator" "") + (match_operand:DI 2 "nonimmediate_operand" "") + (match_operand:DI 3 "nonimmediate_operand" "")))] + "TARGET_CMOVE" + " +{ + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); +}") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0") + (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))] + "TARGET_CMOVE" + "#") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0") + (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" + "#") + +(define_split + [(set (match_operand:DI 0 "register_operand" "=&r,&r") + (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")))] + "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)))] + "") + +(define_split + [(set (match_operand:DI 0 "register_operand" "=&r,&r") + (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")))] + "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);") + +(define_insn "strlensi_unroll" + [(set (match_operand:SI 0 "register_operand" "=&r,&r") + (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "r,r")) + (match_operand:SI 2 "immediate_operand" "i,i")] 0)) + (clobber (match_scratch:SI 3 "=&q,&r"))] + "optimize > 1" + "* return output_strlen_unroll (operands);") + +;; the only difference between the following patterns is the register preference +;; on a pentium using a q-register saves one clock cycle per 4 characters + +(define_insn "strlensi_unroll4" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0,0")) + (match_operand:SI 1 "immediate_operand" "i,i") + (match_operand:SI 2 "register_operand" "+q,!r")] 0)) + (clobber (match_dup 2))] + "(TARGET_USE_ANY_REG && optimize > 1)" + "* return output_strlen_unroll (operands);") + +(define_insn "strlensi_unroll5" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0")) + (match_operand:SI 1 "immediate_operand" "i") + (match_operand:SI 2 "register_operand" "+q")] 0)) + (clobber (match_dup 2))] + "(TARGET_USE_Q_REG && optimize > 1)" + "* return output_strlen_unroll (operands);" +) + +(define_insn "allocate_stack_worker" + [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3) + (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) + (clobber (match_dup 0))] + "TARGET_STACK_PROBE" + "* return AS1(call,__alloca);") + +(define_expand "allocate_stack" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (reg:SI 7) (match_operand:SI 1 "general_operand" ""))) + (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 1)))] + "TARGET_STACK_PROBE" + " +{ +#ifdef CHECK_STACK_LIMIT + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) < CHECK_STACK_LIMIT) + emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, + operands[1])); + else +#endif + emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode, + operands[1]))); + + emit_move_insn (operands[0], virtual_stack_dynamic_rtx); + DONE; +}") + +(define_expand "exception_receiver" + [(const_int 0)] + "flag_pic" + " +{ + load_pic_register (1); + DONE; +}") diff --git a/contrib/gcc/config/i386/isc.h b/contrib/gcc/config/i386/isc.h index cf8c5f6..5c39896 100644 --- a/contrib/gcc/config/i386/isc.h +++ b/contrib/gcc/config/i386/isc.h @@ -19,7 +19,7 @@ #define LIB_SPEC "%{shlib:-lc_s} %{posix:-lcposix} %{Xp:-lcposix} -lc -lg" #undef CPP_SPEC -#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{Xp:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} %{Xp:-D_POSIX_SOURCE}" /* ISC 2.2 uses `char' for `wchar_t'. */ #undef WCHAR_TYPE @@ -37,7 +37,7 @@ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ @@ -87,3 +87,7 @@ } \ fputs ("\"\n", FILE); \ } while (0) + +/* Work around assembler forward label references generated in exception + handling code. */ +#define DWARF2_UNWIND_INFO 0 diff --git a/contrib/gcc/config/i386/linux-aout.h b/contrib/gcc/config/i386/linux-aout.h index 7e46c68..de81d87 100644 --- a/contrib/gcc/config/i386/linux-aout.h +++ b/contrib/gcc/config/i386/linux-aout.h @@ -1,5 +1,5 @@ -/* Definitions for Intel 386 running Linux - Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. +/* Definitions for Intel 386 running Linux-based GNU systems using a.out. + Copyright (C) 1992, 1994, 1995, 1997, 1998 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. @@ -25,17 +25,16 @@ Boston, MA 02111-1307, USA. */ #include #include /* some common stuff */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Dlinux -Asystem(posix)" #undef CPP_SPEC -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#endif +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #undef SIZE_TYPE #define SIZE_TYPE "unsigned int" @@ -57,9 +56,8 @@ Boston, MA 02111-1307, USA. */ #if 1 /* We no longer link with libc_p.a or libg.a by default. If you - * want to profile or debug the Linux C library, please add - * -lc_p or -ggdb to LDFLAGS at the link time, respectively. - */ + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ #define LIB_SPEC \ "%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" #else diff --git a/contrib/gcc/config/i386/linux-oldld.h b/contrib/gcc/config/i386/linux-oldld.h index c3066ba..4e3085b 100644 --- a/contrib/gcc/config/i386/linux-oldld.h +++ b/contrib/gcc/config/i386/linux-oldld.h @@ -1,5 +1,6 @@ -/* Definitions for Intel 386 running Linux with pre-BFD a.out linkers - Copyright (C) 1995 Free Software Foundation, Inc. +/* Definitions for Intel 386 running Linux-based GNU systems with pre-BFD + a.out linkers. + Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. Contributed by Michael Meissner (meissner@cygnus.com) This file is part of GNU CC. @@ -25,17 +26,16 @@ Boston, MA 02111-1307, USA. */ #include #include /* some common stuff */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Dlinux -Asystem(posix)" #undef CPP_SPEC -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#endif +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #undef SIZE_TYPE #define SIZE_TYPE "unsigned int" @@ -57,9 +57,8 @@ Boston, MA 02111-1307, USA. */ #if 1 /* We no longer link with libc_p.a or libg.a by default. If you - * want to profile or debug the Linux C library, please add - * -lc_p or -ggdb to LDFLAGS at the link time, respectively. - */ + want to profile or debug the GNU/Linux C library, please add + lc_p or -ggdb to LDFLAGS at the link time, respectively. */ #define LIB_SPEC \ "%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" #else diff --git a/contrib/gcc/config/i386/linux.h b/contrib/gcc/config/i386/linux.h index a0b49ba..8e84bb5 100644 --- a/contrib/gcc/config/i386/linux.h +++ b/contrib/gcc/config/i386/linux.h @@ -1,5 +1,5 @@ -/* Definitions for Intel 386 running Linux with ELF format - Copyright (C) 1994, 1995 Free Software Foundation, Inc. +/* Definitions for Intel 386 running Linux-based GNU systems with ELF format. + Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Contributed by Eric Youngdale. Modified for stabs-in-ELF by H.J. Lu. @@ -37,16 +37,19 @@ Boston, MA 02111-1307, USA. */ #undef DEFAULT_PCC_STRUCT_RETURN #define DEFAULT_PCC_STRUCT_RETURN 1 +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + /* 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. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) /* Copy this from the svr4 specifications... */ /* Define the register numbers to be used in Dwarf debugging information. @@ -147,44 +150,19 @@ 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 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -Asystem(posix)" #undef CPP_SPEC #ifdef USE_GNULIBC_1 -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" #endif -#else /* not USE_GNULIBC_1 */ -#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" -#endif /* not USE_GNULIBC_1 */ -#undef LIBGCC_SPEC -#define LIBGCC_SPEC "-lgcc" - -#undef LIB_SPEC -#ifdef USE_GNULIBC_1 -#if 1 -/* We no longer link with libc_p.a or libg.a by default. If you - * want to profile or debug the Linux 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 \ - "%{!shared: \ - %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ - %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" -#endif -#else -#define LIB_SPEC \ - "%{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ - %{profile:-lc_p} %{!profile: -lc}}" -#endif /* not USE_GNULIBC_1 */ +#undef CC1_SPEC +#define CC1_SPEC "%(cc1_cpu) %{profile:-p}" /* Provide a LINK_SPEC appropriate for Linux. Here we provide support for the special GCC options -static and -shared, which allow us to @@ -221,7 +199,7 @@ Boston, MA 02111-1307, USA. */ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \ %{static:-static}}}" #endif -#else /* not USE_GNULIBC_1 */ +#else #define LINK_SPEC "-m elf_i386 %{shared:-shared} \ %{!shared: \ %{!ibcs: \ @@ -229,7 +207,28 @@ Boston, MA 02111-1307, USA. */ %{rdynamic:-export-dynamic} \ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ %{static:-static}}}" -#endif /* not USE_GNULIBC_1 */ +#endif /* Get perform_* macros to build libgcc.a. */ #include "i386/perform.h" + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< + +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. */ + +/* I believe in reuse... */ +#include "i386/linux.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Di386 -Dmoss -Asystem(posix) -Acpu(i386) -Amachine(i386)" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtn.o%s" + +#undef LINK_SPEC + diff --git a/contrib/gcc/config/i386/netbsd.h b/contrib/gcc/config/i386/netbsd.h index 180ff35..5978aec 100644 --- a/contrib/gcc/config/i386/netbsd.h +++ b/contrib/gcc/config/i386/netbsd.h @@ -30,13 +30,6 @@ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 -#define HANDLE_SYSV_PRAGMA - -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - #undef ASM_APP_ON #define ASM_APP_ON "#APP\n" @@ -51,18 +44,25 @@ i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 +#define JUMP_TABLES_IN_TEXT_SECTION 1 /* Don't default to pcc-struct-return, because gcc is the only compiler, and we want to retain compatibility with older gcc versions. */ #define DEFAULT_PCC_STRUCT_RETURN 0 +/* i386 netbsd still uses old binutils that don't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) + /* Profiling routines, partially copied from i386/osfrose.h. */ /* Redefine this to use %eax instead of %edx. */ @@ -78,3 +78,8 @@ fprintf (FILE, "\tcall mcount\n"); \ } \ } + +/* Until they use ELF or something that handles dwarf2 unwinds + and initialization stuff better. */ +#define DWARF2_UNWIND_INFO 0 + diff --git a/contrib/gcc/config/i386/next.h b/contrib/gcc/config/i386/next.h index c0d6d72..65f7402 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 Free Software Foundation, Inc. + Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -124,8 +124,8 @@ Boston, MA 02111-1307, USA. */ GAS requires the %cl argument, so override unx386.h. */ -#undef AS3_SHIFT_DOUBLE -#define AS3_SHIFT_DOUBLE(a,b,c,d) AS3 (a,b,c,d) +#undef SHIFT_DOUBLE_OMITS_COUNT +#define SHIFT_DOUBLE_OMITS_COUNT 0 /* Print opcodes the way that GAS expects them. */ #define GAS_MNEMONICS 1 @@ -216,7 +216,7 @@ Boston, MA 02111-1307, USA. */ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE \ ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ @@ -224,3 +224,10 @@ Boston, MA 02111-1307, USA. */ == void_type_node))) ? (SIZE) : 0) /* END Calling Convention CHANGES */ + +/* NeXT still uses old binutils that don't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) diff --git a/contrib/gcc/config/i386/openbsd.h b/contrib/gcc/config/i386/openbsd.h new file mode 100644 index 0000000..1b56262 --- /dev/null +++ b/contrib/gcc/config/i386/openbsd.h @@ -0,0 +1,130 @@ +/* Configuration for an OpenBSD i386 target. + + 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 is tested by i386gas.h. */ +#define YES_UNDERSCORES + +#include + +/* Get perform_* macros to build libgcc.a. */ +#include + +/* Get generic OpenBSD definitions. */ +#define OBSD_OLD_GAS +#include + +/* Run-time target specifications */ +#define CPP_PREDEFINES "-D__unix__ -D__i386__ -D__OpenBSD__ -Asystem(unix) -Asystem(OpenBSD) -Acpu(i386) -Amachine(i386)" + +/* Layout of source language data types. */ + +/* This must agree with */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +/* Assembler format: overall framework. */ + +#undef ASM_APP_ON +#define ASM_APP_ON "#APP\n" + +#undef ASM_APP_OFF +#define ASM_APP_OFF "#NO_APP\n" + +/* The following macros were originally stolen from i386v4.h. + These have to be defined to get PIC code correct. */ + +/* Assembler format: dispatch tables. */ + +/* 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. */ +#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]\n", LPREFIX, VALUE) + +/* Assembler format: sections. */ + +/* Indicate when jump tables go in the text section. This is + necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Stack & calling: aggregate returns. */ + +/* Don't default to pcc-struct-return, because gcc is the only compiler, and + we want to retain compatibility with older gcc versions. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Assembler format: alignment output. */ + +/* Kludgy test: when gas is upgraded, it will have p2align, and no problems + with nops. */ +#ifndef HAVE_GAS_MAX_SKIP_P2ALIGN +/* i386 OpenBSD still uses an older gas that doesn't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) +#endif + +/* Stack & calling: profiling. */ + +/* OpenBSD's profiler recovers all information from the stack pointer. + The icky part is not here, but in machine/profile.h. */ +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fputs (flag_pic ? "\tcall mcount@PLT\n": "\tcall mcount\n", FILE); + +/* Assembler format: exception region output. */ + +/* All configurations that don't use elf must be explicit about not using + dwarf unwind information. egcs doesn't try too hard to check internal + configuration files... */ +#define DWARF2_UNWIND_INFO 0 + +/* Assembler format: alignment output. */ + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< +#include "i386/sysv4.h" /* Base i386 target machine definitions */ +#define _sys_siglist sys_siglist +extern char *sys_siglist[]; + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 OSF/1)"); + +/* WORD_SWITCH_TAKES_ARG defined in svr4 is not correct. We also + need an extra -soname */ +#undef WORD_SWITCH_TAKES_ARG +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + || !strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ + || !strcmp (STR, "Tbss") || !strcmp (STR, "soname")) + +/* Note, -fpic and -fPIC are equivalent */ +#undef CPP_SPEC +#define CPP_SPEC "\ +%{fpic: -D__SHARED__} %{fPIC: %{!fpic: -D__SHARED__}} \ +%{.S: %{!ansi:%{!traditional:%{!traditional-cpp:%{!ftraditional: -traditional}}}}} \ +%{.S: -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ +%{.cc: -D__LANGUAGE_C_PLUS_PLUS} \ +%{.cxx: -D__LANGUAGE_C_PLUS_PLUS} \ +%{.C: -D__LANGUAGE_C_PLUS_PLUS} \ +%{.m: -D__LANGUAGE_OBJECTIVE_C} \ +%{!.S: -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" + +/* -mmcount or -mno-mcount should be used with -pg or -p */ +#undef CC1_SPEC +#define CC1_SPEC "%{p: %{!mmcount: %{!mno-mcount: -mno-mcount }}} \ +%{!p: %{pg: %{!mmcount: %{!mno-mcount: -mno-mcount }}}}" + +/* Note, -D__NO_UNDERSCORES__ -D__ELF__ are provided in the older version of + OSF/1 gcc. We keep them here, so that old /usr/include/i386/asm.h works. + */ +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-D__NO_UNDERSCORES__ -D__ELF__ -DOSF -DOSF1 -Di386 -Dunix -Asystem(xpg4) -Asystem(osf1) -Acpu(i386) -Amachine(i386)" + +/* current OSF/1 doesn't provide separate crti.o and gcrti.o (and also, crtn.o + and gcrtn.o) for profile. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\ + crti.o%s \ + crtbegin.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +#undef ASM_SPEC +#define ASM_SPEC "%{v*: -v}" + +#undef LINK_SPEC +#define LINK_SPEC "%{v*: -v} \ + %{h*} %{z*} \ + %{dy:-call_shared} %{dn:-static} \ + %{static:-static} \ + %{shared:-shared} \ + %{call_shared:-call_shared} \ + %{symbolic:-Bsymbolic -shared -call_shared} \ + %{!dy: %{!dn: %{!static: %{!shared: %{!symbolic: \ + %{noshrlib: -static } \ + %{!noshrlib: -call_shared}}}}}}" + +#undef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/ccs/gcc/" + +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" + +/* Define this macro meaning that gcc should find the library 'libgcc.a' + by hand, rather than passing the argument '-lgcc' to tell the linker + to do the search */ +#define LINK_LIBGCC_SPECIAL + +/* This goes with LINK_LIBGCC_SPECIAL, we need tell libgcc.a differently */ +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "%{!shared:%{!symbolic:libgcc.a%s}}" + +/* A C statement to output assembler commands which will identify the object + file as having been compile with GNU CC. We don't need or want this for + OSF1. */ +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(FILE) + +/* Identify the front-end which produced this file. To keep symbol + space down, and not confuse kdb, only do this if the language is + not C. */ +#define ASM_IDENTIFY_LANGUAGE(STREAM) \ +{ \ + if (strcmp (lang_identify (), "c") != 0) \ + output_lang_identify (STREAM); \ +} + +/* Specify size_t, ptrdiff_t, and wchar_t types. */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE + +#define SIZE_TYPE "long unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "unsigned int" +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* Turn off long double being 96 bits. */ +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* Work with OSF/1 profile */ +#define MASK_NO_MCOUNT 000200000000 /* profiling uses mcount_ptr */ + +#define TARGET_MCOUNT ((target_flags & MASK_NO_MCOUNT) == 0) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "mcount", -MASK_NO_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. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. + + We override it here to allow for the new profiling code to go before + the prologue and the old mcount code to go after the prologue (and + after %ebx has been set up for ELF shared library support). */ +#if 0 +#define OSF_PROFILE_BEFORE_PROLOGUE \ + (!TARGET_MCOUNT \ + && !current_function_needs_context \ + && (!flag_pic \ + || !frame_pointer_needed \ + || (!current_function_uses_pic_offset_table \ + && !current_function_uses_const_pool))) +#else +#define OSF_PROFILE_BEFORE_PROLOGUE 0 +#endif +#undef FUNCTION_PROLOGUE +#define FUNCTION_PROLOGUE(FILE, SIZE) \ +do \ + { \ + char *prefix = ""; \ + char *lprefix = LPREFIX; \ + int labelno = profile_label_no; \ + \ + if (profile_flag && OSF_PROFILE_BEFORE_PROLOGUE) \ + { \ + if (!flag_pic) \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \ + fprintf (FILE, "\tcall *%s_mcount_ptr\n", prefix); \ + } \ + \ + else \ + { \ + static int call_no = 0; \ + \ + fprintf (FILE, "\tcall %sPc%d\n", lprefix, call_no); \ + fprintf (FILE, "%sPc%d:\tpopl %%eax\n", lprefix, call_no); \ + fprintf (FILE, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n", \ + lprefix, call_no++); \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n", \ + lprefix, labelno); \ + fprintf (FILE, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n", \ + prefix); \ + fprintf (FILE, "\tcall *(%%eax)\n"); \ + } \ + } \ + \ + function_prologue (FILE, SIZE); \ + } \ +while (0) + +/* A C statement or compound statement to output to FILE some assembler code to + call the profiling subroutine `mcount'. Before calling, the assembler code + must load the address of a counter variable into a register where `mcount' + expects to find the address. The name of this variable is `LP' followed by + the number LABELNO, so you would generate the name using `LP%d' in a + `fprintf'. + + The details of how the address should be passed to `mcount' are determined + by your operating system environment, not by GNU CC. To figure them out, + compile a small program for profiling using the system's installed C + compiler and look at the assembler code that results. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ +do \ + { \ + if (!OSF_PROFILE_BEFORE_PROLOGUE) \ + { \ + char *prefix = ""; \ + char *lprefix = LPREFIX; \ + int labelno = LABELNO; \ + \ + /* Note that OSF/rose blew it in terms of calling mcount, \ + since OSF/rose prepends a leading underscore, but mcount's \ + doesn't. At present, we keep this kludge for ELF as well \ + to allow old kernels to build profiling. */ \ + \ + if (flag_pic \ + && !current_function_uses_pic_offset_table \ + && !current_function_uses_const_pool) \ + abort (); \ + \ + if (TARGET_MCOUNT && flag_pic) \ + { \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ + lprefix, labelno); \ + fprintf (FILE, "\tcall *%smcount@GOT(%%ebx)\n", prefix); \ + } \ + \ + else if (TARGET_MCOUNT) \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \ + fprintf (FILE, "\tcall %smcount\n", prefix); \ + } \ + \ + else if (flag_pic && frame_pointer_needed) \ + { \ + fprintf (FILE, "\tmovl 4(%%ebp),%%ecx\n"); \ + fprintf (FILE, "\tpushl %%ecx\n"); \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ + lprefix, labelno); \ + fprintf (FILE, "\tmovl _mcount_ptr@GOT(%%ebx),%%eax\n"); \ + fprintf (FILE, "\tcall *(%%eax)\n"); \ + fprintf (FILE, "\tpopl %%eax\n"); \ + } \ + \ + else if (frame_pointer_needed) \ + { \ + fprintf (FILE, "\tmovl 4(%%ebp),%%ecx\n"); \ + fprintf (FILE, "\tpushl %%ecx\n"); \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \ + fprintf (FILE, "\tcall *_mcount_ptr\n"); \ + fprintf (FILE, "\tpopl %%eax\n"); \ + } \ + \ + else \ + abort (); \ + } \ + } \ +while (0) + +#if defined (CROSS_COMPILE) && defined (HOST_BITS_PER_INT) && defined (HOST_BITS_PER_LONG) && defined (HOST_BITS_PER_LONGLONG) +#if (HOST_BITS_PER_INT==32) && (HOST_BITS_PER_LONG==64) && (HOST_BITS_PER_LONGLONG==64) +#define REAL_ARITHMETIC +#endif +#endif diff --git a/contrib/gcc/config/i386/osf1elfgdb.h b/contrib/gcc/config/i386/osf1elfgdb.h new file mode 100644 index 0000000..af6efa2 --- /dev/null +++ b/contrib/gcc/config/i386/osf1elfgdb.h @@ -0,0 +1,7 @@ +/* Target definitions for GNU compiler for Intel 80386 running OSF/1 1.3+ + with gas and gdb. */ + +/* Use stabs instead of DWARF debug format. */ +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "i386/osf1elf.h" diff --git a/contrib/gcc/config/i386/osfelf.h b/contrib/gcc/config/i386/osfelf.h index 7e71fe9..381ffc2 100644 --- a/contrib/gcc/config/i386/osfelf.h +++ b/contrib/gcc/config/i386/osfelf.h @@ -22,10 +22,10 @@ Boston, MA 02111-1307, USA. */ #include "config/i386/osfrose.h" #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Di386 -Asystem(unix) -Asystem(xpg4) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Asystem(xpg4)" #undef CPP_SPEC -#define CPP_SPEC "\ +#define CPP_SPEC "%(cpp_cpu) \ %{mrose: -D__ROSE__ %{!pic-none: -D__SHARED__}} \ %{!mrose: -D__ELF__ %{fpic: -D__SHARED__}} \ %{mno-underscores: -D__NO_UNDERSCORES__} \ diff --git a/contrib/gcc/config/i386/osfrose.h b/contrib/gcc/config/i386/osfrose.h index 3aae1e1..9cfe187 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 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -36,16 +36,7 @@ Boston, MA 02111-1307, USA. */ -z* options (for the linker). */ #define SWITCH_TAKES_ARG(CHAR) \ - ( (CHAR) == 'D' \ - || (CHAR) == 'U' \ - || (CHAR) == 'o' \ - || (CHAR) == 'e' \ - || (CHAR) == 'T' \ - || (CHAR) == 'u' \ - || (CHAR) == 'I' \ - || (CHAR) == 'm' \ - || (CHAR) == 'L' \ - || (CHAR) == 'A' \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ || (CHAR) == 'h' \ || (CHAR) == 'z') @@ -99,10 +90,10 @@ Boston, MA 02111-1307, USA. */ /* Change default predefines. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Di386 -Asystem(unix) -Asystem(xpg4) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Asystem(xpg4)" #undef CPP_SPEC -#define CPP_SPEC "\ +#define CPP_SPEC "%(cpp_cpu) \ %{!melf: -D__ROSE__ %{!pic-none: -D__SHARED__}} \ %{melf: -D__ELF__ %{fpic: -D__SHARED__}} \ %{mno-underscores: -D__NO_UNDERSCORES__} \ @@ -373,6 +364,12 @@ while (0) fprintf (FILE, "%s%s%d:\n", (TARGET_UNDERSCORES) ? "" : ".", \ PREFIX, NUM) +/* The prefix to add to user-visible assembler symbols. */ + +/* target_flags is not accessible by the preprocessor */ +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "_" + /* This is how to output a reference to a user-level label named NAME. */ #undef ASM_OUTPUT_LABELREF @@ -384,7 +381,7 @@ while (0) i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Output a definition */ @@ -407,10 +404,9 @@ while (0) alignment to be done at such a time. Most machine descriptions do not currently define the macro. */ -#undef ASM_OUTPUT_ALIGN_CODE -#define ASM_OUTPUT_ALIGN_CODE(STREAM) \ - fprintf (STREAM, "\t.align\t%d\n", \ - (!TARGET_LARGE_ALIGN && i386_align_jumps > 2) ? 2 : i386_align_jumps) +#undef LABEL_ALIGN_AFTER_BARRIER +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) \ + ((!TARGET_LARGE_ALIGN && i386_align_jumps > 2) ? 2 : i386_align_jumps) /* A C expression to output text to align the location counter in the way that is desirable at the beginning of a loop. @@ -419,9 +415,8 @@ while (0) alignment to be done at such a time. Most machine descriptions do not currently define the macro. */ -#undef ASM_OUTPUT_LOOP_ALIGN -#define ASM_OUTPUT_LOOP_ALIGN(STREAM) \ - fprintf (STREAM, "\t.align\t%d\n", i386_align_loops) +#undef LOOP_ALIGN +#define LOOP_ALIGN(LABEL) (i386_align_loops) /* A C statement to output to the stdio stream STREAM an assembler command to advance the location counter to a multiple of 2 to the diff --git a/contrib/gcc/config/i386/ptx4-i.h b/contrib/gcc/config/i386/ptx4-i.h new file mode 100644 index 0000000..1537b4a --- /dev/null +++ b/contrib/gcc/config/i386/ptx4-i.h @@ -0,0 +1,247 @@ +/* Target definitions for GNU compiler for Intel 80386 running Dynix/ptx v4 + Copyright (C) 1996 Free Software Foundation, Inc. + + Modified from sysv4.h + Originally written by Ron Guilmette (rfg@netcom.com). + Modified by Tim Wright (timw@sequent.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/i386.h" /* Base i386 target machine definitions */ +#include "i386/att.h" /* Use the i386 AT&T assembler syntax */ +#include "ptx4.h" /* Rest of definitions (non architecture dependent) */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 Sequent Dynix/ptx Version 4)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ + +#undef RETURN_IN_MEMORY +#define RETURN_IN_MEMORY(TYPE) \ + (TYPE_MODE (TYPE) == BLKmode) + +/* Define which macros to predefine. _SEQUENT_ is our extension. */ +/* This used to define X86, but james@bigtex.cactus.org says that + is supposed to be defined optionally by user programs--not by default. */ +#define CPP_PREDEFINES \ + "-Di386 -Dunix -D_SEQUENT_ -Asystem(unix) -Asystem(ptx4) -Acpu(i386) -Amachine(i386)" + +/* This is how to output assembly code to define a `float' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ +do { long value; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \ + else \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \ + } while (0) + +/* This is how to output assembly code to define a `double' constant. + We always have to use a pair of .long pseudo-ops to do this because + the native SVR4 ELF assembler is buggy and it generates incorrect + values when we try to use the .double pseudo-op instead. */ + +#undef ASM_OUTPUT_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ +do { long value[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + } \ + } while (0) + + +#undef ASM_OUTPUT_LONG_DOUBLE +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ +do { long value[3]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[2]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[2]); \ + } \ + } 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); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ + +#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)+3 \ + : (-1)) + +/* 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. */ + +#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]\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 diff --git a/contrib/gcc/config/i386/rtems.h b/contrib/gcc/config/i386/rtems.h new file mode 100644 index 0000000..60e6dc7 --- /dev/null +++ b/contrib/gcc/config/i386/rtems.h @@ -0,0 +1,34 @@ +/* Definitions for rtems targeting an Intel i386 using coff. + Copyright (C) 1996, 1997 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/i386-coff.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(i386) -Amachine(i386)" + +/* Generate calls to memcpy, memcmp and memset. */ +#ifndef TARGET_MEM_FUNCTIONS +#define TARGET_MEM_FUNCTIONS +#endif + diff --git a/contrib/gcc/config/i386/rtemself.h b/contrib/gcc/config/i386/rtemself.h new file mode 100644 index 0000000..d9d9733 --- /dev/null +++ b/contrib/gcc/config/i386/rtemself.h @@ -0,0 +1,169 @@ +/* Definitions for Intel 386 running Linux-based GNU systems with ELF format. + Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + +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 LINUX_DEFAULT_ELF + +/* A lie, I guess, but the general idea behind linux/ELF is that we are + supposed to be outputting something that will assemble under SVr4. + This gets us pretty close. */ +#include /* Base i386 target machine definitions */ +#include /* Use the i386 AT&T assembler syntax */ +#include /* some common stuff */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 RTEMS with ELF)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 1 + +/* 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. */ +#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]\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 (flag_pic) + +/* 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 + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#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)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + +#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"); \ + } \ + else \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tcall mcount\n"); \ + } \ +} + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(i386) -Amachine(i386)" + +/* Get perform_* macros to build libgcc.a. */ +#include "i386/perform.h" + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s" + +#undef ENDFILE_SPEC + diff --git a/contrib/gcc/config/i386/sco.h b/contrib/gcc/config/i386/sco.h index 37dc032..016e0a0 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 Software Foundation, Inc. + Copyright (C) 1988, 1992, 1994, 1995 Free, 1996 Software Foundation, Inc. This file is part of GNU CC. @@ -55,10 +55,10 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC "%{scointl:-DM_INTERNAT}" +#define CPP_SPEC "%(cpp_cpu) %{scointl:-DM_INTERNAT}" /* This spec is used for telling cpp whether char is signed or not. */ @@ -104,7 +104,7 @@ Boston, MA 02111-1307, USA. */ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ diff --git a/contrib/gcc/config/i386/sco4.h b/contrib/gcc/config/i386/sco4.h index fc389b4..5d1ea47 100644 --- a/contrib/gcc/config/i386/sco4.h +++ b/contrib/gcc/config/i386/sco4.h @@ -63,11 +63,11 @@ Boston, MA 02111-1307, USA. */ #undef CPP_PREDEFINES #define CPP_PREDEFINES \ - "-Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" + "-Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC \ - "-D_i386 -D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ +#define CPP_SPEC "%(cpp_cpu) \ + -D_i386 -D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ -D_unix -D_M_UNIX -D_M_XENIX \ -D_M_SYS5 -D_M_SYSV -D_M_SYS3 -D_M_SYSIII \ -D_M_COFF -D_M_BITFIELDS -D_M_WORDSWAP \ diff --git a/contrib/gcc/config/i386/sco4dbx.h b/contrib/gcc/config/i386/sco4dbx.h index 0387c24..3d075b6 100644 --- a/contrib/gcc/config/i386/sco4dbx.h +++ b/contrib/gcc/config/i386/sco4dbx.h @@ -61,11 +61,11 @@ Boston, MA 02111-1307, USA. */ Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Di386 -Dunix -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC \ - "-D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ +#define CPP_SPEC "%(cpp_cpu) \ + -D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ -D_M_UNIX -D_M_XENIX \ -D_M_SYS5 -D_M_SYSV -D_M_SYS3 -D_M_SYSIII \ -D_M_COFF -D_M_BITFIELDS -D_M_WORDSWAP \ diff --git a/contrib/gcc/config/i386/sco5.h b/contrib/gcc/config/i386/sco5.h new file mode 100644 index 0000000..74fb891 --- /dev/null +++ b/contrib/gcc/config/i386/sco5.h @@ -0,0 +1,957 @@ +/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5. + Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Kean Johnston (hug@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. */ + +#include "i386/i386.h" /* Base i386 target definitions */ +#include "i386/att.h" /* Use AT&T i386 assembler syntax */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386, SCO OpenServer 5 Syntax)"); + +#undef LPREFIX +#define LPREFIX ".L" + +#undef ALIGN_ASM_OP +#define ALIGN_ASM_OP "\t.align" + +#undef ASCII_DATA_ASM_OP +#define ASCII_DATA_ASM_OP "\t.ascii" + +#undef ASM_BYTE_OP +#define ASM_BYTE_OP "\t.byte" + +#undef IDENT_ASM_OP +#define IDENT_ASM_OP "\t.ident" + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.comm" + +#undef SET_ASM_OP +#define SET_ASM_OP "\t.set" + +#undef LOCAL_ASM_OP +#define LOCAL_ASM_OP "\t.local" + +#undef INT_ASM_OP +#define INT_ASM_OP "\t.long" + +#undef ASM_SHORT +#define ASM_SHORT "\t.value" + +#undef ASM_LONG +#define ASM_LONG "\t.long" + +#undef ASM_DOUBLE +#define ASM_DOUBLE "\t.double" + +#undef TYPE_ASM_OP +#define TYPE_ASM_OP "\t.type" + +#undef SIZE_ASM_OP +#define SIZE_ASM_OP "\t.size" + +#undef STRING_ASM_OP +#define STRING_ASM_OP "\t.string" + +#undef SKIP_ASM_OP +#define SKIP_ASM_OP "\t.zero" + +#undef GLOBAL_ASM_OP +#define GLOBAL_ASM_OP "\t.globl" + +#undef EH_FRAME_SECTION_ASM_OP +#define EH_FRAME_SECTION_ASM_OP_COFF "\t.section\t.ehfram, \"x\"" +#define EH_FRAME_SECTION_ASM_OP_ELF "\t.section\t.eh_frame, \"aw\"" +#define EH_FRAME_SECTION_ASM_OP \ + ((TARGET_ELF) ? EH_FRAME_SECTION_ASM_OP_ELF : EH_FRAME_SECTION_ASM_OP_COFF) + +/* Avoid problems (long sectino names, forward assembler refs) with DWARF + exception unwinding when we're generating COFF */ +#define DWARF2_UNWIND_INFO \ + ((TARGET_ELF) ? 1 : 0 ) + +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP_COFF "\t.section\t.rodata, \"x\"" +#define CONST_SECTION_ASM_OP_ELF "\t.section\t.rodata" +#define CONST_SECTION_ASM_OP \ + ((TARGET_ELF) ? CONST_SECTION_ASM_OP_ELF : CONST_SECTION_ASM_OP_COFF) + +#undef USE_CONST_SECTION +#define USE_CONST_SECTION_ELF 1 +#define USE_CONST_SECTION_COFF 0 +#define USE_CONST_SECTION \ + ((TARGET_ELF) ? USE_CONST_SECTION_ELF : USE_CONST_SECTION_COFF) + +#undef INIT_SECTION_ASM_OP +#define INIT_SECTION_ASM_OP_ELF "\t.section\t.init" +#define INIT_SECTION_ASM_OP_COFF "\t.section\t.init ,\"x\"" +#define INIT_SECTION_ASM_OP \ + ((TARGET_ELF) ? INIT_SECTION_ASM_OP_ELF : INIT_SECTION_ASM_OP_COFF) + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP_ELF "\t.section\t.ctors,\"aw\"" +#define CTORS_SECTION_ASM_OP_COFF INIT_SECTION_ASM_OP_COFF +#define CTORS_SECTION_ASM_OP \ + ((TARGET_ELF) ? CTORS_SECTION_ASM_OP_ELF : CTORS_SECTION_ASM_OP_COFF) + +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP_ELF "\t.section\t.dtors, \"aw\"" +#define DTORS_SECTION_ASM_OP_COFF FINI_SECTION_ASM_OP_COFF +#define DTORS_SECTION_ASM_OP \ + ((TARGET_ELF) ? DTORS_SECTION_ASM_OP_ELF : DTORS_SECTION_ASM_OP_COFF) + +#undef FINI_SECTION_ASM_OP +#define FINI_SECTION_ASM_OP_ELF "\t.section\t.fini" +#define FINI_SECTION_ASM_OP_COFF "\t.section\t.fini, \"x\"" +#define FINI_SECTION_ASM_OP \ + ((TARGET_ELF) ? FINI_SECTION_ASM_OP_ELF : FINI_SECTION_ASM_OP_COFF) + +#undef BSS_SECTION_ASM_OP +#define BSS_SECTION_ASM_OP "\t.data" + +#undef TEXT_SECTION_ASM_OP +#define TEXT_SECTION_ASM_OP "\t.text" + +#undef DATA_SECTION_ASM_OP +#define DATA_SECTION_ASM_OP "\t.data" + +#undef TYPE_OPERAND_FMT +#define TYPE_OPERAND_FMT "@%s" + +#undef APPLY_RESULT_SIZE +#define APPLY_RESULT_SIZE \ +(TARGET_ELF) ? size : 116 + +#ifndef ASM_DECLARE_RESULT +#define ASM_DECLARE_RESULT(FILE, RESULT) +#endif + +#define SCO_DEFAULT_ASM_COFF(FILE,NAME) \ +do { \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + } while (0) + +#undef ASM_DECLARE_FUNCTION_NAME +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ + do { \ + if (TARGET_ELF) { \ + fprintf (FILE, "%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); \ + } else \ + SCO_DEFAULT_ASM_COFF(FILE, NAME); \ +} while (0) + +#undef ASM_DECLARE_FUNCTION_SIZE +#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ + do { \ + if (TARGET_ELF) { if (!flag_inhibit_size_directive) \ + { \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, (FNAME)); \ + fprintf (FILE, ",.-"); \ + assemble_name (FILE, (FNAME)); \ + putc ('\n', FILE); \ + } } \ + } while (0) + +#undef ASM_DECLARE_OBJECT_NAME +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + if (TARGET_ELF) { \ + fprintf (FILE, "%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, "%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); \ + } else \ + SCO_DEFAULT_ASM_COFF(FILE, NAME); \ + } while (0) + +#undef ASM_FILE_START_1 +#define ASM_FILE_START_1(FILE) + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +do { \ + output_file_directive((FILE),main_input_filename); \ + fprintf ((FILE), "\t.version\t\"01.01\"\n"); \ +} while (0) + +#undef ASM_FILE_END +#define ASM_FILE_END(FILE) \ +do { \ + fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ +} while (0) + +#undef ASM_FINISH_DECLARE_OBJECT +#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ +do { \ + if (TARGET_ELF) { \ + 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, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, name); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + } \ +} while (0) + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ +do { \ + if (TARGET_ELF) \ + sprintf (LABEL, "*.%s%d", (PREFIX), (NUM)); \ + else \ + sprintf (LABEL, ".%s%d", (PREFIX), (NUM)); \ +} while (0) + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ +do { \ + if (TARGET_ELF) \ + fprintf (FILE, "%s _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", ASM_LONG, LPREFIX, VALUE); \ + else \ + fprintf (FILE, "\t.word %s%d-%s%d\n", LPREFIX,VALUE,LPREFIX,REL); \ +} while (0) + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + if (TARGET_ELF) \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ + else \ + fprintf ((FILE), ",%u\n", (SIZE)); \ +} while (0) + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + if (TARGET_ELF) { \ + fprintf ((FILE), "%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ + } else { \ + int align = exact_log2 (ALIGN); \ + if (align > 2) align = 2; \ + if (TARGET_SVR3_SHLIB) \ + data_section (); \ + else \ + bss_section (); \ + ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \ + fprintf ((FILE), "%s\t", "\t.lcomm"); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u\n", (SIZE)); \ + } \ +} while (0) + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ +asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +#undef ESCAPES +#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" + +#undef STRING_LIMIT +#define STRING_LIMIT ((unsigned) 256) + +#undef ASM_OUTPUT_LIMITED_STRING +#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \ + do \ + { \ + register unsigned char *_limited_str = (unsigned char *) (STR); \ + register unsigned ch; \ + fprintf ((FILE), "%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) + + +#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), "%s\t", ASM_BYTE_OP); \ + else \ + fputc (',', (FILE)); \ + fprintf ((FILE), "0x%02x", *_ascii_bytes); \ + bytes_in_chunk += 5; \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\n"); \ +} while (0) + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (TARGET_ELF) { \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ + } else \ + readonly_data_section(); \ +} + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ +do { \ + if (TARGET_ELF) \ + ASM_OUTPUT_ALIGN ((FILE), 2); \ + ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); \ +} while (0) + + +#undef ASM_OUTPUT_CONSTRUCTOR +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ +do { \ + if (TARGET_ELF) { \ + ctors_section (); \ + fprintf (FILE, "%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } else { \ + init_section (); \ + fprintf (FILE, "\tpushl $"); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); } \ + } while (0) + +#undef ASM_OUTPUT_DESTRUCTOR +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ +do { \ + if (TARGET_ELF) { \ + dtors_section (); \ + fprintf (FILE, "%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } else { \ + fini_section (); \ + fprintf (FILE, "%s\t ", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); } \ + } while (0) + + +#undef ASM_OUTPUT_IDENT +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +#undef ASM_GLOBALIZE_LABEL +#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + (fprintf ((FILE), "%s ", GLOBAL_ASM_OP), assemble_name (FILE, NAME), fputs ("\n", FILE)) + +#undef ASM_OUTPUT_EXTERNAL_LIBCALL +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + if (TARGET_ELF) ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM) + +/* The prefix to add to user-visible assembler symbols. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +/* + * Compensate for the difference between ELF and COFF assembler syntax. + * Otherwise, this is cribbed from ../svr4.h. + * We rename 'gcc_except_table' to the shorter name in preparation + * for the day when we're ready to do DWARF2 eh unwinding under COFF + */ +#undef ASM_OUTPUT_SECTION_NAME +#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; \ + char *sname = NAME ; \ + if (strcmp(NAME, ".gcc_except_table") == 0) sname = ".gccexc" ; \ + \ + for (s = sections; s; s = s->next) \ + if (!strcmp (NAME, s->name)) \ + break; \ + \ + if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \ + type = SECT_EXEC, mode = (TARGET_ELF) ? "ax" : "x" ; \ + else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \ + type = SECT_RO, mode = "a"; \ + else \ + type = SECT_RW, mode = (TARGET_ELF) ? "aw" : "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 (FILE, ".section\t%s,\"%s\"%s\n", sname, mode, \ + (TARGET_ELF) ? ",@progbits" : "" ); \ + } \ + else \ + { \ + if (DECL && s->type != type) \ + error_with_decl (DECL, "%s causes a section type conflict"); \ + \ + fprintf (FILE, ".section\t%s\n", sname); \ + } \ +} while (0) + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ +do { \ + if (TARGET_ELF) \ + fprintf (FILE, "%s\t%u\n", SKIP_ASM_OP, (SIZE)); \ + else \ + fprintf ((FILE), "%s\t.,.+%u\n", SET_ASM_OP, (SIZE)); \ +} while (0) + + +#undef CTOR_LIST_BEGIN +#define CTOR_LIST_BEGIN \ +do { \ + asm (CTORS_SECTION_ASM_OP); \ + if (TARGET_ELF) \ + STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) }; \ + else \ + asm ("pushl $0"); \ +} while (0) + +#undef CTOR_LIST_END +#define CTOR_LIST_END \ +do { \ + if (TARGET_ELF) { \ + asm (CTORS_SECTION_ASM_OP); \ + STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (0) }; \ + } else { \ + CTOR_LIST_BEGIN; \ + } \ +} while (0) + +#undef DBX_BLOCKS_FUNCTION_RELATIVE +#define DBX_BLOCKS_FUNCTION_RELATIVE 1 + +#undef DBX_FUNCTION_FIRST +#define DBX_FUNCTION_FIRST 1 + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((TARGET_ELF) ? \ + ((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)+3 \ + : (-1)) \ + : \ + ((n) == 0 ? 0 : \ + (n) == 1 ? 2 : \ + (n) == 2 ? 1 : \ + (n) == 3 ? 3 : \ + (n) == 4 ? 6 : \ + (n) == 5 ? 7 : \ + (n) == 6 ? 4 : \ + (n) == 7 ? 5 : \ + (n) + 4)) + +#undef DWARF_DEBUGGING_INFO +#undef SDB_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO +#undef PREFERRED_DEBUGGING_TYPE + +#define DWARF_DEBUGGING_INFO 1 +#define SDB_DEBUGGING_INFO 1 +#define DBX_DEBUGGING_INFO 1 +#define PREFERRED_DEBUGGING_TYPE \ + ((TARGET_ELF) ? DWARF_DEBUG: SDB_DEBUG) + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + INIT_SECTION_FUNCTION \ + FINI_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#undef CONST_SECTION_FUNCTION +#define CONST_SECTION_FUNCTION \ +void \ +const_section () \ +{ \ + extern void text_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; \ + } \ +} + +#undef FINI_SECTION_FUNCTION +#define FINI_SECTION_FUNCTION \ +void \ +fini_section () \ +{ \ + if ((!TARGET_ELF) && in_section != in_fini) \ + { \ + fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \ + in_section = in_fini; \ + } \ +} + +#undef INIT_SECTION_FUNCTION +#define INIT_SECTION_FUNCTION \ +void \ +init_section () \ +{ \ + if ((!TARGET_ELF) && in_section != in_init) \ + { \ + fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \ + in_section = in_init; \ + } \ +} + +#undef CTORS_SECTION_FUNCTION +#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; \ + } \ +} + +#undef DTORS_SECTION_FUNCTION +#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; \ + } \ +} + +#undef FRAME_POINTER_REQUIRED +#define FRAME_POINTER_REQUIRED \ + ((TARGET_ELF) ? 0 : \ + (current_function_calls_setjmp || current_function_calls_longjmp)) + +#undef JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ELF && flag_pic) + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX \ + ((TARGET_ELF) ? "" : ".") + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX +#define MD_EXEC_PREFIX "/usr/ccs/bin/" +#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" + +#undef NON_SAVING_SETJMP +#define NON_SAVING_SETJMP \ + ((TARGET_ELF) ? 0 : \ + (current_function_calls_setjmp && current_function_calls_longjmp)) + +#undef NO_IMPLICIT_EXTERN_C +#define NO_IMPLICIT_EXTERN_C 1 + +/* JKJ FIXME - examine the ramifications of RETURN_IN_MEMORY and + RETURN_POPS_ARGS */ + +#undef RETURN_POPS_ARGS +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ + ((TARGET_ELF) ? \ + (i386_return_pops_args (FUNDECL, FUNTYPE, SIZE)) : \ + (((FUNDECL) && (TREE_CODE (FUNDECL) == IDENTIFIER_NODE)) ? 0 \ + : (TARGET_RTD \ + && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ + == void_type_node))) ? (SIZE) \ + : 0)) + +#undef SELECT_SECTION +#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 ((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)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else \ + const_section (); \ +} + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ + || (CHAR) == 'h' \ + || (CHAR) == 'R' \ + || (CHAR) == 'Y' \ + || (CHAR) == 'z') + +#undef WORD_SWITCH_TAKES_ARG +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + && strcmp (STR, "Tdata") && strcmp (STR, "Ttext") \ + && strcmp (STR, "Tbss")) + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT 0301 + +#undef HANDLE_SYSV_PRAGMA +#define HANDLE_SYSV_PRAGMA 1 + +#undef SCCS_DIRECTIVE +#define SCCS_DIRECTIVE 1 + +/* + * Define sizes and types + */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 96 +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "long int" +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* + * New for multilib support. Set the default switches for multilib, + * which is -melf. + */ +#define MULTILIB_DEFAULTS { "melf" } + + +/* Please note that these specs may look messy but they are required in + order to emulate the SCO Development system as closely as possible. + With SCO Open Server 5.0, you now get the linker and assembler free, + so that is what these specs are targeted for. These utilities are + very argument sensitive: a space in the wrong place breaks everything. + So RMS, please forgive this mess. It works. + + Parameters which can be passed to gcc, and their SCO equivalents: + GCC Parameter SCO Equivalent + -ansi -a ansi + -posix -a posix + -Xpg4 -a xpg4 + -Xpg4plus -a xpg4plus + -Xods30 -a ods30 + + As with SCO, the default is XPG4 plus mode. SCO also allows you to + specify a C dialect with -Xt, -Xa, -Xc, -Xk and -Xm. These are passed + on to the assembler and linker in the same way that the SCO compiler + does. + + SCO also allows you to compile, link and generate either ELF or COFF + binaries. With gcc, unlike the SCO compiler, the default is ELF. + Specify -mcoff to gcc to produce COFF binaries. -fpic will get the + assembler and linker to produce PIC code. +*/ + +/* Set up assembler flags for PIC and ELF compilations */ +#undef ASM_SPEC + +#if USE_GAS + /* Leave ASM_SPEC undefined so we pick up the master copy from gcc.c + * Undef MD_EXEC_PREFIX becuase we don't know where GAS is, but it's not + * likely in /usr/ccs/bin/ + */ +#undef MD_EXEC_PREFIX +#else + +#define ASM_SPEC \ + "-b %{!mcoff:elf}%{mcoff:coff \ + %{static:%e-static not valid with -mcoff} \ + %{shared:%e-shared not valid with -mcoff} \ + %{symbolic:%e-symbolic not valid with -mcoff}} \ + %{Ym,*} %{Yd,*} %{Wa,*:%*} \ + %{!mcoff:-E%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},ELF %{Qn:} %{!Qy:-Qn}}" +#endif + +/* Use crt1.o as a startup file and crtn.o as a closing file. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{shared: %{!mcoff: crti.o%s}} \ + %{!shared:\ + %{!symbolic: \ + %{pg:gcrt.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}} \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional: \ + %{Xa:values-Xa.o%s} \ + %{!Xa:%{Xc:values-Xc.o%s} \ + %{!Xc:%{Xk:values-Xk.o%s} \ + %{!Xk:%{Xt:values-Xt.o%s} \ + %{!Xt:values-Xa.o%s}}}}}} \ + %{mcoff:crtbeginS.o%s} %{!mcoff:crtbegin.o%s}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!mcoff:crtend.o%s} \ + %{mcoff:crtendS.o%s} \ + %{pg:gcrtn.o%s}%{!pg:crtn.o%s}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-Asystem(svr3)" + +/* You are in a maze of GCC specs ... all alike */ + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) \ + %{fpic:%{mcoff:%e-fpic is not valid with -mcoff}} \ + %{fPIC:%{mcoff:%e-fPIC is not valid with -mcoff}} \ + -D__i386 -D__unix -D_SCO_DS=1 -D_M_I386 -D_M_XENIX -D_M_UNIX \ + %{!Xods30:-D_STRICT_NAMES} \ + %{!ansi:%{!posix:%{!Xods30:-D_SCO_XPG_VERS=4}}} \ + %{ansi:-isystem include/ansi%s -isystem /usr/include/ansi -D_STRICT_ANSI} \ + %{!ansi: \ + %{posix:-isystem include/posix%s -isystem /usr/include/posix \ + -D_POSIX_C_SOURCE=2 -D_POSIX_SOURCE=1} \ + %{!posix:%{Xpg4:-isystem include/xpg4%s -isystem /usr/include/xpg4 \ + -D_XOPEN_SOURCE=1} \ + %{!Xpg4:-D_M_I86 -D_M_I86SM -D_M_INTERNAT -D_M_SDATA -D_M_STEXT \ + -D_M_BITFIELDS -D_M_SYS5 -D_M_SYSV -D_M_SYSIII \ + -D_M_WORDSWAP -Dunix -DM_I386 -DM_UNIX -DM_XENIX \ + %{Xods30:-isystem include/ods_30_compat%s \ + -isystem /usr/include/ods_30_compat \ + -D_SCO_ODS_30 -DM_I86 -DM_I86SM -DM_SDATA -DM_STEXT \ + -DM_BITFIELDS -DM_SYS5 -DM_SYSV -DM_INTERNAT -DM_SYSIII \ + -DM_WORDSWAP}}}} \ + %{scointl:-DM_INTERNAT -D_M_INTERNAT} \ + %{traditional:-D_KR -D_SVID -D_NO_PROTOTYPE} \ + %{!mcoff:-D_SCO_ELF} \ + %{mcoff:-D_M_COFF -D_SCO_COFF} \ + %{!mcoff:%{fpic:-D__PIC__ -D__pic__} \ + %{fPIC:%{!fpic:-D__PIC__ -D__pic__}}} \ + %{Xa:-D_SCO_C_DIALECT=1} \ + %{!Xa:%{Xc:-D_SCO_C_DIALECT=3} \ + %{!Xc:%{Xk:-D_SCO_C_DIALECT=4} \ + %{!Xk:%{Xt:-D_SCO_C_DIALECT=2} \ + %{!Xt:-D_SCO_C_DIALECT=1}}}} \ + %{traditional:-traditional -D_KR -D_NO_PROTOTYPE}" + +#undef LINK_SPEC +#define LINK_SPEC \ + "-b %{!mcoff:elf}%{mcoff:coff \ + %{static:%e-static not valid with -mcoff} \ + %{shared:%e-shared not valid with -mcoff} \ + %{symbolic:%e-symbolic not valid with -mcoff} \ + %{fpic:%e-fpic not valid with -mcoff} \ + %{fPIC:%e-fPIC not valid with -mcoff}} \ + -R%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},%{mcoff:COFF}%{!mcoff:ELF} \ + %{Wl,*%*} %{YP,*} %{YL,*} %{YU,*} \ + %{!YP,*:%{p:-YP,/usr/ccs/libp:/lib/libp:/usr/lib/libp:/usr/ccs/lib:/lib:/usr/lib} \ + %{!p:-YP,/usr/ccs/lib:/lib:/usr/lib}} \ + %{h*} %{static:-dn -Bstatic} %{shared:-G -dy %{!z*:-z text}} \ + %{symbolic:-Bsymbolic -G -dy %{!z*:-z text}} %{z*} %{R*} %{Y*} \ + %{G:-G} %{!mcoff:%{Qn:} %{!Qy:-Qn}}" + +/* The SCO COFF linker gets confused on the difference between "-ofoo" + and "-o foo". So we just always force a single space. */ + +#define SWITCHES_NEED_SPACES "o" + +/* Library spec. If we are not building a shared library, provide the + standard libraries, as per the SCO compiler. */ + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{shared:pic/libgcc.a%s}%{!shared:%{!symbolic:-lcrypt -lgen -lc}}" + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC \ + "%{!shared:-lgcc}" + +#define MASK_COFF 010000000000 /* Mask for elf generation */ +#define TARGET_COFF (target_flags & MASK_COFF) +#define TARGET_ELF (!(target_flags & MASK_COFF)) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "coff", MASK_COFF }, \ + { "elf", -MASK_COFF }, + +#define NO_DOLLAR_IN_LABEL + +/* +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 +set things up accordingly, based on the pre-processor defines for ELF +and COFF. This is insane, but then I guess having one compiler with a +single back-end supporting two vastly different file format types is +a little insane too. But it is not impossible and we get a useful +compiler at the end of the day. Onward we go ... +*/ + +#if defined(CRT_BEGIN) || defined(CRT_END) || defined(IN_LIBGCC2) +# undef OBJECT_FORMAT_ELF +# undef HAVE_ATEXIT +# undef INIT_SECTION_ASM_OP +# undef FINI_SECTION_ASM_OP +# undef CTORS_SECTION_ASM_OP +# undef DTORS_SECTION_ASM_OP +# undef EH_FRAME_SECTION_ASM_OP +# undef CTOR_LIST_BEGIN +# undef CTOR_LIST_END +# undef DO_GLOBAL_CTORS_BODY + +# if defined (_SCO_ELF) +# define OBJECT_FORMAT_ELF +# define HAVE_ATEXIT 1 +# define INIT_SECTION_ASM_OP INIT_SECTION_ASM_OP_ELF +# define FINI_SECTION_ASM_OP FINI_SECTION_ASM_OP_ELF +# define DTORS_SECTION_ASM_OP DTORS_SECTION_ASM_OP_ELF +# define CTORS_SECTION_ASM_OP CTORS_SECTION_ASM_OP_ELF +# define EH_FRAME_SECTION_ASM_OP EH_FRAME_SECTION_ASM_OP_ELF +# else /* ! _SCO_ELF */ +# define INIT_SECTION_ASM_OP INIT_SECTION_ASM_OP_COFF +# define FINI_SECTION_ASM_OP FINI_SECTION_ASM_OP_COFF +# define DTORS_SECTION_ASM_OP DTORS_SECTION_ASM_OP_COFF +# define CTORS_SECTION_ASM_OP CTORS_SECTION_ASM_OP_COFF +# define EH_FRAME_SECTION_ASM_OP "" +# define CTOR_LIST_BEGIN asm (INIT_SECTION_ASM_OP); asm ("pushl $0") +# define CTOR_LIST_END CTOR_LIST_BEGIN +# define DO_GLOBAL_CTORS_BODY \ +do { \ + func_ptr *p, *beg = alloca(0); \ + for (p = beg; *p;) \ + (*p++) (); \ +} while (0) +# endif /* ! _SCO_ELF */ +#endif /* CRT_BEGIN !! CRT_END */ diff --git a/contrib/gcc/config/i386/sco5gas.h b/contrib/gcc/config/i386/sco5gas.h new file mode 100644 index 0000000..de3e5d5 --- /dev/null +++ b/contrib/gcc/config/i386/sco5gas.h @@ -0,0 +1,24 @@ +/* Definitions for Intel x86 running SCO OpenServer, running GNU assembler + 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. */ + + +/* Just set a single flag we can test for inside of sco5.h and include it. */ + +#define USE_GAS 1 diff --git a/contrib/gcc/config/i386/scodbx.h b/contrib/gcc/config/i386/scodbx.h index 1309735..a2581d4 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 Free Software Foundation, Inc. + Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -50,10 +50,10 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC "%{scointl:-DM_INTERNAT}" +#define CPP_SPEC " -Acpu(i386) -Amachine(i386) %{scointl:-DM_INTERNAT}" /* This spec is used for telling cpp whether char is signed or not. */ @@ -75,7 +75,7 @@ Boston, MA 02111-1307, USA. */ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ diff --git a/contrib/gcc/config/i386/seq-gas.h b/contrib/gcc/config/i386/seq-gas.h index 2ee0719..796eaa2 100644 --- a/contrib/gcc/config/i386/seq-gas.h +++ b/contrib/gcc/config/i386/seq-gas.h @@ -39,8 +39,8 @@ GAS requires the %cl argument, so override i386/unix.h. */ -#undef AS3_SHIFT_DOUBLE -#define AS3_SHIFT_DOUBLE(a,b,c,d) AS3 (a,b,c,d) +#undef SHIFT_DOUBLE_OMITS_COUNT +#define SHIFT_DOUBLE_OMITS_COUNT 0 /* Print opcodes the way that GAS expects them. */ #define GAS_MNEMONICS 1 diff --git a/contrib/gcc/config/i386/seq-sysv3.h b/contrib/gcc/config/i386/seq-sysv3.h index e3182ee..9e8388d 100644 --- a/contrib/gcc/config/i386/seq-sysv3.h +++ b/contrib/gcc/config/i386/seq-sysv3.h @@ -40,17 +40,3 @@ /* Assembler pseudo-op for uninitialized shared local variables (.shbss). */ #undef SHARED_BSS_SECTION_ASM_OP #define SHARED_BSS_SECTION_ASM_OP ".section .shbss, \"bs\"" -#undef BSS_SECTION_FUNCTION -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - if (flag_shared_data) \ - fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP); \ - else \ - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} diff --git a/contrib/gcc/config/i386/sol2-c1.asm b/contrib/gcc/config/i386/sol2-c1.asm index 72fdfb8..d08bcbd 100644 --- a/contrib/gcc/config/i386/sol2-c1.asm +++ b/contrib/gcc/config/i386/sol2-c1.asm @@ -1,6 +1,6 @@ ! crt1.s for Solaris 2, x86 -! Copyright (C) 1993 Free Software Foundation, Inc. +! Copyright (C) 1993, 1998 Free Software Foundation, Inc. ! Written By Fred Fish, Nov 1992 ! ! This file is free software; you can redistribute it and/or modify it @@ -149,7 +149,7 @@ _start: ! A dummy profiling support routine for non-profiling executables, ! in case we link in some objects that have been compiled for profiling. - .globl _mcount + .weak _mcount _mcount: ret .type _mcount,@function diff --git a/contrib/gcc/config/i386/sol2-gc1.asm b/contrib/gcc/config/i386/sol2-gc1.asm new file mode 100644 index 0000000..24a1965 --- /dev/null +++ b/contrib/gcc/config/i386/sol2-gc1.asm @@ -0,0 +1,160 @@ +! gcrt1.s for Solaris 2, x86 + +! Copyright (C) 1993 Free Software Foundation, Inc. +! Written By Fred Fish, Nov 1992 +! +! 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, 59 Temple Place - Suite 330, +! Boston, MA 02111-1307, USA. +! +! As a special exception, if you link this library with files +! compiled with GCC to produce an executable, this does not 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 file takes control of the process from the kernel, as specified +! in section 3 of the System V Application Binary Interface, Intel386 +! Processor Supplement. It has been constructed from information obtained +! from the ABI, information obtained from single stepping existing +! Solaris executables through their startup code with gdb, and from +! information obtained by single stepping executables on other i386 SVR4 +! implementations. This file is the first thing linked into any executable. + +! This is a modified crt1.s by J.W.Hawtin 15/8/96, +! to allow program profiling, by calling monstartup on entry and _mcleanup +! on exit + + .file "gcrt1.s" + .ident "GNU C gcrt1.s" + .weak _DYNAMIC + .text + +! Start creating the initial frame by pushing a NULL value for the return +! address of the initial frame, and mark the end of the stack frame chain +! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. +! Initialize the first stack frame pointer in %ebp (the contents of which +! are unspecified at process initialization). + + .globl _start +_start: + pushl $0x0 + pushl $0x0 + movl %esp,%ebp + +! As specified per page 3-32 of the ABI, %edx contains a function +! pointer that should be registered with atexit(), for proper +! shared object termination. Just push it onto the stack for now +! to preserve it. We want to register _cleanup() first. + + pushl %edx + +! Check to see if there is an _cleanup() function linked in, and if +! so, register it with atexit() as the last thing to be run by +! atexit(). + + movl $_mcleanup,%eax + testl %eax,%eax + je .L1 + pushl $_mcleanup + call atexit + addl $0x4,%esp +.L1: + +! Now check to see if we have an _DYNAMIC table, and if so then +! we need to register the function pointer previously in %edx, but +! now conveniently saved on the stack as the argument to pass to +! atexit(). + + movl $_DYNAMIC,%eax + testl %eax,%eax + je .L2 + call atexit +.L2: + +! Register _fini() with atexit(). We will take care of calling _init() +! directly. + + pushl $_fini + call atexit + +! Start profiling + + pushl %ebp + movl %esp,%ebp + pushl $_etext + pushl $_start + call monstartup + addl $8,%esp + popl %ebp + +! Compute the address of the environment vector on the stack and load +! it into the global variable _environ. Currently argc is at 8 off +! the frame pointer. Fetch the argument count into %eax, scale by the +! size of each arg (4 bytes) and compute the address of the environment +! vector which is 16 bytes (the two zero words we pushed, plus argc, +! plus the null word terminating the arg vector) further up the stack, +! off the frame pointer (whew!). + + movl 8(%ebp),%eax + leal 16(%ebp,%eax,4),%edx + movl %edx,_environ + +! Push the environment vector pointer, the argument vector pointer, +! and the argument count on to the stack to set up the arguments +! for _init(), _fpstart(), and main(). Note that the environment +! vector pointer and the arg count were previously loaded into +! %edx and %eax respectively. The only new value we need to compute +! is the argument vector pointer, which is at a fixed address off +! the initial frame pointer. + + pushl %edx + leal 12(%ebp),%edx + pushl %edx + pushl %eax + +! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and +! main(argc, argv, environ). + + call _init + call __fpstart + call main + +! Pop the argc, argv, and environ arguments off the stack, push the +! value returned from main(), and call exit(). + + addl $12,%esp + pushl %eax + call exit + +! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. + + pushl $0x0 + movl $0x1,%eax + lcall $7,$0 + +! If all else fails, just try a halt! + + hlt + .type _start,@function + .size _start,.-_start diff --git a/contrib/gcc/config/i386/sol2.h b/contrib/gcc/config/i386/sol2.h index cc5ebca..8fc3e61 100644 --- a/contrib/gcc/config/i386/sol2.h +++ b/contrib/gcc/config/i386/sol2.h @@ -1,7 +1,6 @@ /* Target definitions for GNU compiler for Intel 80386 running Solaris 2 - Copyright (C) 1993, 1995 Free Software Foundation, Inc. - - Written by Fred Fish (fnf@cygnus.com). + Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Fred Fish (fnf@cygnus.com). This file is part of GNU CC. @@ -31,17 +30,16 @@ Boston, MA 02111-1307, USA. */ executed. This macro forces the assembler to do the padding, since it knows what it is doing. */ -#define FORCE_INIT_SECTION_ALIGN do { asm (ALIGN_ASM_OP ## " 16"); } while (0) +#define FORCE_INIT_SECTION_ALIGN asm (ALIGN_ASM_OP ## " 16") #define FORCE_FINI_SECTION_ALIGN FORCE_INIT_SECTION_ALIGN /* Add "sun" to the list of symbols defined for SVR4. */ #undef CPP_PREDEFINES #define CPP_PREDEFINES \ - "-Di386 -Dunix -D__svr4__ -D__SVR4 -Dsun \ - -Asystem(unix) -Asystem(svr4) -Acpu(i386) -Amachine(i386)" + "-Dunix -D__svr4__ -D__SVR4 -Dsun -Asystem(svr4)" #undef CPP_SPEC -#define CPP_SPEC "\ +#define CPP_SPEC "%(cpp_cpu) \ %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude}" #undef LIB_SPEC @@ -51,10 +49,21 @@ Boston, MA 02111-1307, USA. */ #undef ENDFILE_SPEC #define ENDFILE_SPEC "crtend.o%s %{pg:crtn.o%s}%{!pg:crtn.o%s}" +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\ + %{pg:gmon.o%s} crti.o%s \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}} \ + crtbegin.o%s" + /* This should be the same as in svr4.h, except with -R added. */ #undef LINK_SPEC #define LINK_SPEC \ - "%{h*} %{V} %{v:%{!V:-V}} \ + "%{h*} %{v:-V} \ %{b} %{Wl,*:%*} \ %{static:-dn -Bstatic} \ %{shared:-G -dy -z text} \ @@ -63,12 +72,14 @@ Boston, MA 02111-1307, USA. */ %{YP,*} \ %{R*} \ %{compat-bsd: \ - %{!YP,*:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ - %{!p:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}} \ + %{!YP,*:%{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!pg:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!p:-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} \ - %{!p:-Y P,/usr/ccs/lib:/usr/lib}}} \ + %{!YP,*:%{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!pg:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!p:-Y P,/usr/ccs/lib:/usr/lib}}}} \ %{Qy:} %{!Qn:-Qy}" /* This defines which switch letters take arguments. @@ -76,16 +87,9 @@ Boston, MA 02111-1307, USA. */ #undef SWITCH_TAKES_ARG #define SWITCH_TAKES_ARG(CHAR) \ - ( (CHAR) == 'D' \ - || (CHAR) == 'U' \ - || (CHAR) == 'o' \ - || (CHAR) == 'e' \ - || (CHAR) == 'u' \ - || (CHAR) == 'I' \ - || (CHAR) == 'm' \ - || (CHAR) == 'L' \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ || (CHAR) == 'R' \ - || (CHAR) == 'A' \ || (CHAR) == 'h' \ || (CHAR) == 'z') +#define STDC_0_IN_SYSTEM_HEADERS diff --git a/contrib/gcc/config/i386/sun386.h b/contrib/gcc/config/i386/sun386.h index 6e26807..4d4d66c 100644 --- a/contrib/gcc/config/i386/sun386.h +++ b/contrib/gcc/config/i386/sun386.h @@ -1,5 +1,5 @@ /* Definitions for Sun assembler syntax for the Intel 80386. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -131,10 +131,9 @@ do \ #define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \ sprintf ((BUF), "*.%s%d", (PREFIX), (NUMBER)) -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf (FILE, "%s", NAME) +#define USER_LABEL_PREFIX "" /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. */ diff --git a/contrib/gcc/config/i386/svr3.ifile b/contrib/gcc/config/i386/svr3.ifile index f0bb3a0..32b3ddc 100644 --- a/contrib/gcc/config/i386/svr3.ifile +++ b/contrib/gcc/config/i386/svr3.ifile @@ -28,7 +28,10 @@ SECTIONS vfork = fork; /* I got tired of editing peoples sloppy code */ *(.fini) } - GROUP BIND( NEXT(0x400000) + (ADDR(.text) + (SIZEOF(.text)) % 0x1000)): + .stab BIND(ADDR(.text) + SIZEOF(.text)): { } + .stabstr BIND(ADDR(.stab) + SIZEOF(.stab)): { } + GROUP BIND( NEXT(0x400000) + + (ADDR(.stabstr) + (SIZEOF(.stabstr)) % 0x1000)): { .data : { __CTOR_LIST__ = . ; diff --git a/contrib/gcc/config/i386/svr3dbx.h b/contrib/gcc/config/i386/svr3dbx.h index d3348d5..36c01cc 100644 --- a/contrib/gcc/config/i386/svr3dbx.h +++ b/contrib/gcc/config/i386/svr3dbx.h @@ -46,16 +46,13 @@ Boston, MA 02111-1307, USA. */ /* Align labels, etc. at 4-byte boundaries. For the 486, align to 16-byte boundary for sake of cache. */ -#undef ASM_OUTPUT_ALIGN_CODE -#define ASM_OUTPUT_ALIGN_CODE(FILE) \ - fprintf ((FILE), "\t.align %d,0x90\n", \ - 1 << i386_align_jumps) +#undef LABEL_ALIGN_AFTER_BARRIER +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps) /* Align start of loop at 4-byte boundary. */ -#undef ASM_OUTPUT_LOOP_ALIGN -#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ - fprintf ((FILE), "\t.align %d,0x90\n", 1 << i386_align_loops); +#undef LOOP_ALIGN +#define LOOP_ALIGN(LABEL) (i386_align_loops) /* Additional overrides needed for dbx-in-coff gas, mostly taken from pbb.h */ @@ -66,17 +63,6 @@ Boston, MA 02111-1307, USA. */ */ #define CTOR_LISTS_DEFINED_EXTERNALLY -/* similar to default, but allows for the table defined by ld with svr3.ifile. - nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0. - The old check is left in so that the same macro can be used if and when - a future version of gas does support section directives. */ - -#define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \ - if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \ - for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); \ - for (i = nptrs; i >= 1; i--) \ - __DTOR_LIST__[i] (); } - /* Use crt1.o as a startup file and crtn.o as a closing file. */ /* * The loader directive file svr3.ifile defines how to merge the constructor diff --git a/contrib/gcc/config/i386/svr3gas.h b/contrib/gcc/config/i386/svr3gas.h index 401c766..a288b84 100644 --- a/contrib/gcc/config/i386/svr3gas.h +++ b/contrib/gcc/config/i386/svr3gas.h @@ -1,5 +1,5 @@ /* Definitions for Intel 386 running system V, using gas. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -139,29 +139,17 @@ do { \ #endif /* STACK_GROWS_DOWNWARD */ -/* Add extra sections .init and .fini, in addition to .bss from att386.h. */ +/* Add extra sections .rodata, .init and .fini. */ #undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_bss, in_init, in_fini +#define EXTRA_SECTIONS in_const, in_init, in_fini #undef EXTRA_SECTION_FUNCTIONS #define EXTRA_SECTION_FUNCTIONS \ CONST_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION \ INIT_SECTION_FUNCTION \ FINI_SECTION_FUNCTION -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "\t%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} - #define INIT_SECTION_FUNCTION \ void \ init_section () \ diff --git a/contrib/gcc/config/i386/svr3z.ifile b/contrib/gcc/config/i386/svr3z.ifile index 4fdbb93..4946051 100644 --- a/contrib/gcc/config/i386/svr3z.ifile +++ b/contrib/gcc/config/i386/svr3z.ifile @@ -28,7 +28,10 @@ SECTIONS vfork = fork; /* I got tired of editing peoples sloppy code */ *(.fini) } - GROUP BIND( NEXT(0x400000) + (ADDR(.text) + (SIZEOF(.text)) % 0x1000)): + .stab BIND(ADDR(.text) + SIZEOF(.text)): { } + .stabstr BIND(ADDR(.stab) + SIZEOF(.stab)): { } + GROUP BIND( NEXT(0x400000) + + (ADDR(.stabstr) + (SIZEOF(.stabstr)) % 0x1000)): { .data : { __CTOR_LIST__ = . ; diff --git a/contrib/gcc/config/i386/sysv3.h b/contrib/gcc/config/i386/sysv3.h index 8c5cfc4..ce89889 100644 --- a/contrib/gcc/config/i386/sysv3.h +++ b/contrib/gcc/config/i386/sysv3.h @@ -1,5 +1,5 @@ /* Definitions for Intel 386 running system V. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */ #include "svr3.h" /* Use the ATT assembler syntax. - This overrides at least one macro (ASM_OUTPUT_LABELREF) from svr3.h. */ + This overrides at least one macro (USER_LABEL_PREFIX) from svr3.h. */ #include "i386/att.h" @@ -42,9 +42,9 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ -#define CPP_PREDEFINES "-Dunix -Di386 -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Asystem(svr3)" -#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE}" /* Writing `int' for a bitfield forces int alignment for the structure. */ diff --git a/contrib/gcc/config/i386/sysv4.h b/contrib/gcc/config/i386/sysv4.h index 92fcada..e688f7b 100644 --- a/contrib/gcc/config/i386/sysv4.h +++ b/contrib/gcc/config/i386/sysv4.h @@ -58,7 +58,7 @@ do { long value; \ /* This is how to output assembly code to define a `double' constant. We always have to use a pair of .long pseudo-ops to do this because the native SVR4 ELF assembler is buggy and it generates incorrect - values when we try to use the the .double pseudo-op instead. */ + values when we try to use the .double pseudo-op instead. */ #undef ASM_OUTPUT_DOUBLE #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ @@ -236,10 +236,18 @@ do { long value[3]; \ i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\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 +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) diff --git a/contrib/gcc/config/i386/t-crtpic b/contrib/gcc/config/i386/t-crtpic index f5dd073..ff81a9be 100644 --- a/contrib/gcc/config/i386/t-crtpic +++ b/contrib/gcc/config/i386/t-crtpic @@ -7,3 +7,4 @@ # routines in crtstuff.c. CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/i386/t-dgux b/contrib/gcc/config/i386/t-dgux new file mode 100644 index 0000000..292331f --- /dev/null +++ b/contrib/gcc/config/i386/t-dgux @@ -0,0 +1,4 @@ +# +# target makefile for dgux +# +EXTRA_PARTS=crtbegin.o crtend.o diff --git a/contrib/gcc/config/i386/t-mingw32 b/contrib/gcc/config/i386/t-mingw32 new file mode 100644 index 0000000..fe948c6 --- /dev/null +++ b/contrib/gcc/config/i386/t-mingw32 @@ -0,0 +1,4 @@ +# +# collect2 doesn't work for i386-mingw32* yet. +# +USE_COLLECT2= diff --git a/contrib/gcc/config/i386/t-next b/contrib/gcc/config/i386/t-next index ec6373f..effa695 100644 --- a/contrib/gcc/config/i386/t-next +++ b/contrib/gcc/config/i386/t-next @@ -7,3 +7,6 @@ OTHER_FIXINCLUDES_DIRS= /LocalDeveloper/Headers # is sometimes in /usr/include/ansi/limits.h. LIMITS_H_TEST = [ -f $(SYSTEM_HEADER_DIR)/limits.h -o -f $(SYSTEM_HEADER_DIR)/ansi/limits.h ] + +nextstep.o: $(srcdir)/config/nextstep.c $(CONFIG_H) flags.h tree.h + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/nextstep.c diff --git a/contrib/gcc/config/i386/t-osf b/contrib/gcc/config/i386/t-osf new file mode 100644 index 0000000..c996e0c --- /dev/null +++ b/contrib/gcc/config/i386/t-osf @@ -0,0 +1,2 @@ +# If compiling with the osf gcc, avoid sharing code. +TCFLAGS = -pic-none diff --git a/contrib/gcc/config/i386/t-osf1elf b/contrib/gcc/config/i386/t-osf1elf new file mode 100644 index 0000000..77c7df1 --- /dev/null +++ b/contrib/gcc/config/i386/t-osf1elf @@ -0,0 +1,18 @@ +# Assemble startup files. +crti.o: $(srcdir)/config/i386/osf1-ci.asm $(GCC_PASSES) + sed -e '/^!/d' <$(srcdir)/config/i386/osf1-ci.asm >crti.s + $(GCC_FOR_TARGET) -c -o crti.o crti.s +crtn.o: $(srcdir)/config/i386/osf1-cn.asm $(GCC_PASSES) + sed -e '/^!/d' <$(srcdir)/config/i386/osf1-cn.asm >crtn.s + $(GCC_FOR_TARGET) -c -o crtn.o crtn.s + +# The pushl in CTOR initialization interferes with frame pointer elimination. + +# 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++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fPIC when compiling the +# routines in crtstuff.c. + +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/i386/t-sco5 b/contrib/gcc/config/i386/t-sco5 new file mode 100644 index 0000000..f602066 --- /dev/null +++ b/contrib/gcc/config/i386/t-sco5 @@ -0,0 +1,20 @@ +# The pushl in CTOR initialization interferes with frame pointer elimination. +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +CRTSTUFF_T_CFLAGS_S = -mcoff -fno-omit-frame-pointer + +# +# I am still a little unsure of the multilib architecture. The following +# 4 lines are based on advice from meissner@cygnus.com. +# +MULTILIB_OPTIONS = mcoff/fPIC +MULTILIB_DIRNAMES = coff pic +MULTILIB_EXCEPTIONS = *mcoff*/*fPIC* +MULTILIB_MATCHES = fPIC=fpic +MULTILIB_EXTRA_OPTS = + +LIBGCC=stmp-multilib +INSTALL_LIBGCC=install-multilib + +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-sco5gas b/contrib/gcc/config/i386/t-sco5gas new file mode 100644 index 0000000..2bca87b --- /dev/null +++ b/contrib/gcc/config/i386/t-sco5gas @@ -0,0 +1,20 @@ +# The pushl in CTOR initialization interferes with frame pointer elimination. +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +CRTSTUFF_T_CFLAGS_S = -mcoff -fno-omit-frame-pointer + +# +# I am still a little unsure of the multilib architecture. The following +# 4 lines are based on advice from meissner@cygnus.com. +# +MULTILIB_OPTIONS = fPIC +MULTILIB_DIRNAMES = pic +MULTILIB_EXCEPTIONS = *fPIC* +MULTILIB_MATCHES = fPIC=fpic +MULTILIB_EXTRA_OPTS = + +LIBGCC=stmp-multilib +INSTALL_LIBGCC=install-multilib + +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-sol2 b/contrib/gcc/config/i386/t-sol2 index f79f6ca..5dc59cc 100644 --- a/contrib/gcc/config/i386/t-sol2 +++ b/contrib/gcc/config/i386/t-sol2 @@ -13,20 +13,28 @@ gmon.o: $(srcdir)/config/i386/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) # Apparently Sun believes that assembler files don't need comments, because no # single ASCII character is valid (tried them all). So we manually strip out # the comments with sed. This bug may only be in the Early Access releases. -crt1.o: $(srcdir)/config/i386/sol2-c1.asm +gcrt1.o: $(srcdir)/config/i386/sol2-gc1.asm + sed -e '/^!/d' <$(srcdir)/config/i386/sol2-gc1.asm >gcrt1.s + $(AS) -o gcrt1.o gcrt1.s +crt1.o: $(srcdir)/config/i386/sol2-c1.asm $(GCC_PASSES) sed -e '/^!/d' <$(srcdir)/config/i386/sol2-c1.asm >crt1.s - $(AS) -o crt1.o crt1.s -crti.o: $(srcdir)/config/i386/sol2-ci.asm + $(GCC_FOR_TARGET) -c -o crt1.o crt1.s +crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES) sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s - $(AS) -o crti.o crti.s -crtn.o: $(srcdir)/config/i386/sol2-cn.asm + $(GCC_FOR_TARGET) -c -o crti.o crti.s +crtn.o: $(srcdir)/config/i386/sol2-cn.asm $(GCC_PASSES) sed -e '/^!/d' <$(srcdir)/config/i386/sol2-cn.asm >crtn.s - $(AS) -o crtn.o crtn.s + $(GCC_FOR_TARGET) -c -o crtn.o crtn.s # 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++ # to produce a shared library, but since we don't know ahead of time when # we will be doing that, we just always use -fPIC when compiling the # routines in crtstuff.c. +# +# We must also enable optimization to avoid having any code appear after +# the call & alignment statement, but before we switch back to the +# .text section. -CRTSTUFF_T_CFLAGS = -fPIC +CRTSTUFF_T_CFLAGS = -fPIC -O2 +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/i386/t-winnt b/contrib/gcc/config/i386/t-winnt index e8e1a0a..1e3557c 100644 --- a/contrib/gcc/config/i386/t-winnt +++ b/contrib/gcc/config/i386/t-winnt @@ -1,2 +1,6 @@ winnt.o: $(srcdir)/config/i386/winnt.c - $(CC) -I. -I$(srcdir) -I$(srcdir)/config -c $(srcdir)/config/i386/winnt.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c +oldnames.o: $(srcdir)/config/winnt/oldnames.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/winnt/oldnames.c +spawnv.o: $(srcdir)/config/winnt/spawnv.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/winnt/spawnv.c diff --git a/contrib/gcc/config/i386/unix.h b/contrib/gcc/config/i386/unix.h index f38fe27..47440dd 100644 --- a/contrib/gcc/config/i386/unix.h +++ b/contrib/gcc/config/i386/unix.h @@ -45,7 +45,9 @@ Boston, MA 02111-1307, USA. */ count is in %cl. Some assemblers require %cl as an argument; some don't. This macro controls what to do: by default, don't print %cl. */ -#define AS3_SHIFT_DOUBLE(a,b,c,d) AS2 (a,c,d) +#define SHIFT_DOUBLE_OMITS_COUNT 1 +#define AS3_SHIFT_DOUBLE(a,b,c,d) \ + (SHIFT_DOUBLE_OMITS_COUNT ? AS2 (a,c,d) : AS3 (a,b,c,d)) /* Output the size-letter for an opcode. CODE is the letter used in an operand spec (L, B, W, S or Q). @@ -99,7 +101,6 @@ Boston, MA 02111-1307, USA. */ /* String containing the assembler's comment-starter. */ #define ASM_COMMENT_START "/" -#define COMMENT_BEGIN "/" /* Output to assembler file text saying following lines may contain character constants, extra white space, comments, etc. */ @@ -146,3 +147,45 @@ Boston, MA 02111-1307, USA. */ #define FUNCTION_VALUE_REGNO_P(N) \ ((N) == 0 || ((N)== FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)) +/* Output code to add DELTA to the first argument, and then jump to FUNCTION. + Used for C++ multiple inheritance. */ +#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ +do { \ + tree parm; \ + \ + if (i386_regparm > 0) \ + parm = TYPE_ARG_TYPES (TREE_TYPE (function)); \ + else \ + parm = NULL_TREE; \ + for (; parm; parm = TREE_CHAIN (parm)) \ + if (TREE_VALUE (parm) == void_type_node) \ + break; \ + fprintf (FILE, "\taddl $%d,%s\n", DELTA, \ + parm ? "%eax" \ + : aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) ? "8(%esp)" \ + : "4(%esp)"); \ + \ + if (flag_pic) \ + { \ + rtx xops[2]; \ + xops[0] = pic_offset_table_rtx; \ + xops[1] = (rtx) gen_label_rtx (); \ + \ + if (i386_regparm > 2) \ + abort (); \ + output_asm_insn ("push%L0 %0", xops); \ + 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); \ + 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"); \ + } \ + else \ + { \ + fprintf (FILE, "\tjmp "); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, "\n"); \ + } \ +} while (0) diff --git a/contrib/gcc/config/i386/vxi386.h b/contrib/gcc/config/i386/vxi386.h new file mode 100644 index 0000000..1044286 --- /dev/null +++ b/contrib/gcc/config/i386/vxi386.h @@ -0,0 +1,23 @@ +/* Definitions of target machine for GNU compiler. VxWorks i386 version. + 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 "i386/i386-aout.h" + +#define HANDLE_SYSV_PRAGMA diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c index 3a7ebf1..0058eb7 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 Free Software Foundation, Inc. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,8 +19,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 #include "config.h" +#include "system.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" @@ -28,6 +28,342 @@ Boston, MA 02111-1307, USA. */ #include "tree.h" #include "flags.h" +/* i386/PE specific attribute support. + + i386/PE has two new attributes: + dllexport - for exporting a function/variable that will live in a dll + dllimport - for importing a function/variable from a dll + + Microsoft allows multiple declspecs in one __declspec, separating + them with spaces. We do NOT support this. Instead, use __declspec + multiple times. +*/ + +/* Return nonzero if ATTR is a valid attribute for DECL. + ATTRIBUTES are any existing attributes and ARGS are the arguments + supplied with ATTR. */ + +int +i386_pe_valid_decl_attribute_p (decl, attributes, attr, args) + tree decl; + tree attributes; + tree attr; + tree args; +{ + if (args == NULL_TREE) + { + if (is_attribute_p ("dllexport", attr)) + return 1; + if (is_attribute_p ("dllimport", attr)) + return 1; + } + + return i386_valid_decl_attribute_p (decl, attributes, attr, args); +} + +/* Return nonzero if ATTR is a valid attribute for TYPE. + ATTRIBUTES are any existing attributes and ARGS are the arguments + supplied with ATTR. */ + +int +i386_pe_valid_type_attribute_p (type, attributes, attr, args) + tree type; + tree attributes; + tree attr; + tree args; +{ + if (args == NULL_TREE + && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)) + { + if (is_attribute_p ("dllexport", attr)) + return 1; + if (is_attribute_p ("dllimport", attr)) + return 1; + } + + return i386_valid_type_attribute_p (type, attributes, attr, args); +} + +/* Merge attributes in decls OLD and NEW. + + This handles the following situation: + + __declspec (dllimport) int foo; + int foo; + + The second instance of `foo' nullifies the dllimport. */ + +tree +i386_pe_merge_decl_attributes (old, new) + tree old, new; +{ + tree a; + int delete_dllimport_p; + + old = DECL_MACHINE_ATTRIBUTES (old); + new = DECL_MACHINE_ATTRIBUTES (new); + + /* What we need to do here is remove from `old' dllimport if it doesn't + appear in `new'. dllimport behaves like extern: if a declaration is + marked dllimport and a definition appears later, then the object + is not dllimport'd. */ + + if (lookup_attribute ("dllimport", old) != NULL_TREE + && lookup_attribute ("dllimport", new) == NULL_TREE) + delete_dllimport_p = 1; + else + delete_dllimport_p = 0; + + a = merge_attributes (old, new); + + if (delete_dllimport_p) + { + tree prev,t; + + /* Scan the list for dllimport and delete it. */ + for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t)) + { + if (is_attribute_p ("dllimport", TREE_PURPOSE (t))) + { + if (prev == NULL_TREE) + a = TREE_CHAIN (a); + else + TREE_CHAIN (prev) = TREE_CHAIN (t); + break; + } + } + } + + return a; +} + +/* Return the type that we should use to determine if DECL is + imported or exported. */ + +static tree +associated_type (decl) + tree decl; +{ + tree t = NULL_TREE; + + /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer + to the containing class. So we look at the 'this' arg. */ + if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) + { + /* Artificial methods are not affected by the import/export status of + their class unless they are virtual. */ + if (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl)) + t = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))); + } + else if (DECL_CONTEXT (decl) + && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') + t = DECL_CONTEXT (decl); + + return t; +} + +/* Return non-zero if DECL is a dllexport'd object. */ + +int +i386_pe_dllexport_p (decl) + tree decl; +{ + tree exp; + + if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FUNCTION_DECL) + return 0; + exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl)); + if (exp) + return 1; + + /* Class members get the dllexport status of their class. */ + if (associated_type (decl)) + { + exp = lookup_attribute ("dllexport", + TYPE_ATTRIBUTES (associated_type (decl))); + if (exp) + return 1; + } + + return 0; +} + +/* Return non-zero if DECL is a dllimport'd object. */ + +int +i386_pe_dllimport_p (decl) + tree decl; +{ + tree imp; + + if (TREE_CODE (decl) == FUNCTION_DECL + && TARGET_NOP_FUN_DLLIMPORT) + return 0; + + if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FUNCTION_DECL) + return 0; + imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl)); + if (imp) + return 1; + + /* Class members get the dllimport status of their class. */ + if (associated_type (decl)) + { + imp = lookup_attribute ("dllimport", + TYPE_ATTRIBUTES (associated_type (decl))); + if (imp) + return 1; + } + + return 0; +} + +/* Return non-zero if SYMBOL is marked as being dllexport'd. */ + +int +i386_pe_dllexport_name_p (symbol) + char *symbol; +{ + return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.'; +} + +/* Return non-zero if SYMBOL is marked as being dllimport'd. */ + +int +i386_pe_dllimport_name_p (symbol) + char *symbol; +{ + return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.'; +} + +/* Mark a DECL as being dllexport'd. + Note that we override the previous setting (eg: dllimport). */ + +void +i386_pe_mark_dllexport (decl) + tree decl; +{ + char *oldname, *newname; + rtx rtlname; + tree idp; + + rtlname = XEXP (DECL_RTL (decl), 0); + if (GET_CODE (rtlname) == SYMBOL_REF) + oldname = XSTR (rtlname, 0); + else if (GET_CODE (rtlname) == MEM + && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) + oldname = XSTR (XEXP (rtlname, 0), 0); + else + abort (); + if (i386_pe_dllimport_name_p (oldname)) + oldname += 9; + else if (i386_pe_dllexport_name_p (oldname)) + return; /* already done */ + + newname = alloca (strlen (oldname) + 4); + sprintf (newname, "@e.%s", oldname); + + /* We pass newname through get_identifier to ensure it has a unique + address. RTL processing can sometimes peek inside the symbol ref + and compare the string's addresses to see if two symbols are + identical. */ + idp = get_identifier (newname); + + XEXP (DECL_RTL (decl), 0) = + gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); +} + +/* Mark a DECL as being dllimport'd. */ + +void +i386_pe_mark_dllimport (decl) + tree decl; +{ + char *oldname, *newname; + tree idp; + rtx rtlname, newrtl; + + rtlname = XEXP (DECL_RTL (decl), 0); + if (GET_CODE (rtlname) == SYMBOL_REF) + oldname = XSTR (rtlname, 0); + else if (GET_CODE (rtlname) == MEM + && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) + oldname = XSTR (XEXP (rtlname, 0), 0); + else + abort (); + if (i386_pe_dllexport_name_p (oldname)) + { + error ("`%s' declared as both exported to and imported from a DLL.", + IDENTIFIER_POINTER (DECL_NAME (decl))); + return; + } + else if (i386_pe_dllimport_name_p (oldname)) + { + /* Already done, but force correct linkage since the redeclaration + might have omitted explicit extern. Sigh. */ + if (TREE_CODE (decl) == VAR_DECL + /* ??? Is this test for vtables needed? */ + && !DECL_VIRTUAL_P (decl)) + { + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + } + return; + } + + /* ??? One can well ask why we're making these checks here, + and that would be a good question. */ + + /* Imported variables can't be initialized. Note that C++ classes + are marked initial, so we need to check. */ + if (TREE_CODE (decl) == VAR_DECL + && !DECL_VIRTUAL_P (decl) + && (DECL_INITIAL (decl) + && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))) + { + error_with_decl (decl, "initialized variable `%s' is marked dllimport"); + return; + } + /* Nor can they be static. */ + if (TREE_CODE (decl) == VAR_DECL + /* ??? Is this test for vtables needed? */ + && !DECL_VIRTUAL_P (decl) + && 0 /*???*/) + { + error_with_decl (decl, "static variable `%s' is marked dllimport"); + return; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + if (TREE_CODE (decl) == VAR_DECL + /* ??? Is this test for vtables needed? */ + && !DECL_VIRTUAL_P (decl)) + { + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + } + + newname = alloca (strlen (oldname) + 11); + sprintf (newname, "@i._imp__%s", oldname); + + /* We pass newname through get_identifier to ensure it has a unique + address. RTL processing can sometimes peek inside the symbol ref + and compare the string's addresses to see if two symbols are + identical. */ + idp = get_identifier (newname); + + newrtl = gen_rtx (MEM, Pmode, + gen_rtx (SYMBOL_REF, Pmode, + IDENTIFIER_POINTER (idp))); + XEXP (DECL_RTL (decl), 0) = newrtl; + + /* Can't treat a pointer to this as a constant address */ + DECL_NON_ADDR_CONST_P (decl) = 1; +} + /* Return string which is the former assembler name modified with a suffix consisting of an atsign (@) followed by the number of bytes of arguments */ @@ -37,6 +373,8 @@ 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; @@ -44,13 +382,19 @@ gen_stdcall_suffix (decl) if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) == void_type_node) { - tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); + tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); - while (TREE_VALUE (formal_type) != void_type_node) - { - total += TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); - formal_type = TREE_CHAIN (formal_type); - } + 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); @@ -58,3 +402,169 @@ gen_stdcall_suffix (decl) return IDENTIFIER_POINTER (get_identifier (newsym)); } +/* Cover function to implement ENCODE_SECTION_INFO. */ + +void +i386_pe_encode_section_info (decl) + tree decl; +{ + /* This bit is copied from i386.h. */ + if (optimize > 0 && TREE_CONSTANT (decl) + && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) + { + rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' + ? TREE_CST_RTL (decl) : DECL_RTL (decl)); + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + } + + 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)); + + /* Mark the decl so we can tell from the rtl whether the object is + dllexport'd or dllimport'd. */ + + if (i386_pe_dllexport_p (decl)) + i386_pe_mark_dllexport (decl); + else if (i386_pe_dllimport_p (decl)) + i386_pe_mark_dllimport (decl); + /* It might be that DECL has already been marked as dllimport, but a + subsequent definition nullified that. The attribute is gone but + DECL_RTL still has @i._imp__foo. We need to remove that. Ditto + for the DECL_NON_ADDR_CONST_P flag. */ + else if ((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && DECL_RTL (decl) != NULL_RTX + && GET_CODE (DECL_RTL (decl)) == MEM + && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM + && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF + && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) + { + char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); + tree idp = get_identifier (oldname + 9); + rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); + + XEXP (DECL_RTL (decl), 0) = newrtl; + + DECL_NON_ADDR_CONST_P (decl) = 0; + + /* We previously set TREE_PUBLIC and DECL_EXTERNAL. + We leave these alone for now. */ + } +} + +/* 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); +} + +/* The Microsoft linker requires that every function be marked as + DT_FCN. When using gas on cygwin32, we must emit appropriate .type + directives. */ + +#include "gsyms.h" + +/* Mark a function appropriately. This should only be called for + functions for which we are not emitting COFF debugging information. + FILE is the assembler output file, NAME is the name of the + function, and PUBLIC is non-zero if the function is globally + visible. */ + +void +i386_pe_declare_function_type (file, name, public) + FILE *file; + char *name; + int public; +{ + fprintf (file, "\t.def\t"); + assemble_name (file, name); + fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n", + public ? (int) C_EXT : (int) C_STAT, + (int) DT_FCN << N_BTSHFT); +} + +/* Keep a list of external functions. */ + +struct extern_list +{ + struct extern_list *next; + char *name; +}; + +static struct extern_list *extern_head; + +/* Assemble an external function reference. We need to keep a list of + these, so that we can output the function types at the end of the + assembly. We can't output the types now, because we might see a + definition of the function later on and emit debugging information + for it then. */ + +void +i386_pe_record_external_function (name) + char *name; +{ + struct extern_list *p; + + p = (struct extern_list *) permalloc (sizeof *p); + p->next = extern_head; + p->name = name; + extern_head = p; +} + +/* This is called at the end of assembly. For each external function + which has not been defined, we output a declaration now. */ + +void +i386_pe_asm_file_end (file) + FILE *file; +{ + struct extern_list *p; + + for (p = extern_head; p != NULL; p = p->next) + { + tree decl; + + decl = get_identifier (p->name); + + /* Positively ensure only one declaration for any given symbol. */ + if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)) + { + TREE_ASM_WRITTEN (decl) = 1; + i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl)); + } + } +} diff --git a/contrib/gcc/config/i386/x-dgux b/contrib/gcc/config/i386/x-dgux new file mode 100644 index 0000000..322bfe3 --- /dev/null +++ b/contrib/gcc/config/i386/x-dgux @@ -0,0 +1,11 @@ +# +# host is ix86 running dgux +# +CC = /bin/gcc +X_CFLAGS = -O -mstandard -mlegend +BOOT_CFLAGS = -O2 -g -mstandard -mlegend $(CFLAGS) +CLIB = -lw32 +RANLIB = true +USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) +STMP_FIXPROTO = + diff --git a/contrib/gcc/config/i386/x-osf1elf b/contrib/gcc/config/i386/x-osf1elf new file mode 100644 index 0000000..1467381 --- /dev/null +++ b/contrib/gcc/config/i386/x-osf1elf @@ -0,0 +1,8 @@ +# Defaults for OSF/1 1.3+ +CC = $(OLDCC) +CLIB = -lld +INSTALL = installbsd -c +OLDCC = /usr/ccs/gcc/gcc +X_CFLAGS = -static + +# FIXPROTO_DEFINES = -D_XOPEN_SOURCE diff --git a/contrib/gcc/config/i386/x-osfrose b/contrib/gcc/config/i386/x-osfrose index a419bdb..2c5e3ba 100644 --- a/contrib/gcc/config/i386/x-osfrose +++ b/contrib/gcc/config/i386/x-osfrose @@ -7,8 +7,9 @@ BUILD = CC = $(OLDCC) CLIB = -lld -X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) $(X_DEFINES) -X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(X_DEFINES) $(XCFLAGS) +X_CFLAGS = $(DEB_OPT) $(MSTATS) $(X_DEFINES) +X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(X_DEFINES) $(XCFLAGS) +XCFLAGS = $(SHLIB) CPP_ABORT = # -Dabort=fancy_abort CPPFLAGS = $(CPP_ABORT) $(SYSTEM_INCLUDES) DEB_OPT = $(OPT) $(DEBUG) $(PROFILE) @@ -16,7 +17,6 @@ DEBUG = DEBUG_COLLECT = # -DDEBUG CCLIBFLAGS = -O -DNO_HALF_PIC GCC_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) -B./ -DPOSIX -DNO_HALF_PIC -INSTALL = installbsd -c LDFLAGS = MSTATS = # -mstats OLDCC = /usr/ccs/gcc/gcc @@ -25,7 +25,3 @@ PROFILE = SHLIB = -pic-none SYSTEM_INCLUDES = # -I${BUILD}/usr/include X_DEFINES = -Dvfork=fork - -libdir = /usr/ccs -mandir = /usr/ccs/gcc/$(target)/$(version) -bindir = /usr/ccs/gcc/$(target)/$(version) diff --git a/contrib/gcc/config/i386/x-sco5 b/contrib/gcc/config/i386/x-sco5 new file mode 100644 index 0000000..e13ed74 --- /dev/null +++ b/contrib/gcc/config/i386/x-sco5 @@ -0,0 +1,10 @@ +RANLIB = : +RANLIB_TEST = false +CC = cc +OLDCC = cc +CCLIBFLAGS = +# We avoid the ALLOCA in -lPW becuase it gives us an evil index() +ALLOCA = alloca.o + +# See all the declarations. +FIXPROTO_DEFINES = -D_XOPEN_SOURCE -D_POSIX_C_SOURCE=2 diff --git a/contrib/gcc/config/i386/xm-aix.h b/contrib/gcc/config/i386/xm-aix.h index 5e5d402..4cbd36e 100644 --- a/contrib/gcc/config/i386/xm-aix.h +++ b/contrib/gcc/config/i386/xm-aix.h @@ -1,37 +1,2 @@ -/* Configuration for GNU C-compiler for IBM PS/2 running AIX/386. - Copyright (C) 1988, 1993 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 USG - #undef TRUE #undef FALSE - -#include "i386/xm-i386.h" - -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define bcmp(a,b,c) memcmp (a,b,c) - -/* If not compiled with GNU C, use the portable alloca. */ -#ifndef __GNUC__ -#define USE_C_ALLOCA -#endif - -#define HAVE_PUTENV diff --git a/contrib/gcc/config/i386/xm-bsd386.h b/contrib/gcc/config/i386/xm-bsd386.h index 9deb7ef..6b8eee7 100644 --- a/contrib/gcc/config/i386/xm-bsd386.h +++ b/contrib/gcc/config/i386/xm-bsd386.h @@ -1,6 +1,3 @@ /* Configuration for GCC for Intel i386 running BSDI's BSD/386 as host. */ #include "i386/xm-i386.h" - -#define HAVE_STRERROR - diff --git a/contrib/gcc/config/i386/xm-dgux.h b/contrib/gcc/config/i386/xm-dgux.h new file mode 100644 index 0000000..5bdb9be --- /dev/null +++ b/contrib/gcc/config/i386/xm-dgux.h @@ -0,0 +1,12 @@ + +/* Configuration for GCC for Intel i386 running DG/ux */ + +/* looks just like sysv4 for now */ + +#include "i386/xm-i386.h" +#include "xm-svr4.h" + +/* If not compiled with GNU C, use the portable alloca. */ +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif diff --git a/contrib/gcc/config/i386/xm-dos.h b/contrib/gcc/config/i386/xm-dos.h index 1dd0c01..a734a81 100644 --- a/contrib/gcc/config/i386/xm-dos.h +++ b/contrib/gcc/config/i386/xm-dos.h @@ -1,8 +1,5 @@ #include "i386/xm-i386.h" -/* Inhibit cccp.c's definition of putenv. */ -#define HAVE_PUTENV - /* Use semicolons to separate elements of a path. */ #define PATH_SEPARATOR ';' @@ -15,6 +12,3 @@ #define MKTEMP_EACH_FILE 1 #define NO_PRECOMPILES 1 - -/* sys_errlist proto in cccp.c doesn't match djgpp */ -#define HAVE_STRERROR diff --git a/contrib/gcc/config/i386/xm-isc.h b/contrib/gcc/config/i386/xm-isc.h index 7a0a47c..e686c5e 100644 --- a/contrib/gcc/config/i386/xm-isc.h +++ b/contrib/gcc/config/i386/xm-isc.h @@ -1,5 +1,3 @@ -#include "i386/xm-sysv3.h" - #ifndef REAL_ARITHMETIC #define REAL_VALUE_ATOF(x, mode) strtod ((x), (char **)0) extern double strtod (); diff --git a/contrib/gcc/config/i386/xm-linux.h b/contrib/gcc/config/i386/xm-linux.h index 42f097d..713bf3b2 100644 --- a/contrib/gcc/config/i386/xm-linux.h +++ b/contrib/gcc/config/i386/xm-linux.h @@ -1,5 +1,5 @@ -/* Configuration for GCC for Intel i386 running Linux. - Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. +/* Configuration for GCC for Intel i386 running Linux-based GNU systems. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. diff --git a/contrib/gcc/config/i386/xm-mingw32.h b/contrib/gcc/config/i386/xm-mingw32.h new file mode 100644 index 0000000..d818142 --- /dev/null +++ b/contrib/gcc/config/i386/xm-mingw32.h @@ -0,0 +1,42 @@ +/* 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. + +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_FIELD +#define ONLY_INT_FIELDS 1 +#endif + +#ifndef USE_PROTOTYPES +#define USE_PROTOTYPES 1 +#endif + +#define NO_SYS_SIGLIST 1 +#define environ _environ + +/* Even though we support "/", allow "\" since everybody tests both. */ +#define DIR_SEPARATOR '\\' +#define EXECUTABLE_SUFFIX ".exe" + +#undef PATH_SEPARATOR +#define PATH_SEPARATOR ';' diff --git a/contrib/gcc/config/i386/xm-openbsd.h b/contrib/gcc/config/i386/xm-openbsd.h new file mode 100644 index 0000000..1a79e83 --- /dev/null +++ b/contrib/gcc/config/i386/xm-openbsd.h @@ -0,0 +1,23 @@ +/* Configuration file for i386 hosts running OpenBSD. + 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 +#include + diff --git a/contrib/gcc/config/i386/xm-os2.h b/contrib/gcc/config/i386/xm-os2.h index 5ff2899..aed925e 100644 --- a/contrib/gcc/config/i386/xm-os2.h +++ b/contrib/gcc/config/i386/xm-os2.h @@ -1,7 +1,7 @@ /* Configuration for GNU compiler for an Intel i386 or later processor running OS/2 2.x. - Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. - Contributed by Samuel Figueroa (figueroa@cs.nyu.edu) + Copyright (C) 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc. + Contributed by Samuel Figueroa (figueroa@apple.com) This file is part of GNU CC. @@ -28,20 +28,24 @@ Boston, MA 02111-1307, USA. */ #include /* this defines alloca */ #define USG #define ONLY_INT_FIELDS -#define HAVE_PUTENV #define USE_PROTOTYPES 1 -#define bcmp(a,b,c) memcmp (a,b,c) -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define index strchr -#define rindex strrchr #define strcasecmp stricmp #define kill(a,b) raise(b) #define mktemp tmpnam #else +#ifdef __EMX__ +#define EMX +#define USG +#define BSTRING +#define HAVE_PUTENV +#define HAVE_VPRINTF +#define HAVE_STRERROR +#define strcasecmp stricmp +#else #define ____386BSD____ int spawnv (int modeflag, char *path, char *argv[]); int spawnvp (int modeflag, char *path, char *argv[]); +#endif /* __EMX__ */ #endif /* __IBMC__ */ #ifndef PATH_SEPARATOR @@ -52,6 +56,14 @@ int spawnvp (int modeflag, char *path, char *argv[]); #endif #define EXECUTABLE_SUFFIX ".exe" + +/* The EMX compiler uses regular .o files */ +#ifndef __EMX__ #define OBJECT_SUFFIX ".obj" +#endif + +/* This is required to make temporary file names unique on file + systems which severely restrict the length of file names. */ +#define MKTEMP_EACH_FILE #include "i386/xm-i386.h" diff --git a/contrib/gcc/config/i386/xm-osf.h b/contrib/gcc/config/i386/xm-osf.h index fda50d9..4cbd36e 100644 --- a/contrib/gcc/config/i386/xm-osf.h +++ b/contrib/gcc/config/i386/xm-osf.h @@ -1,32 +1,2 @@ -/* Configuration for GNU C-compiler for 386 running OSF/1 - Copyright (C) 1994 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. */ - #undef TRUE #undef FALSE - -#include "i386/xm-i386.h" - -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define bcmp(a,b,c) memcmp (a,b,c) - -#define HAVE_PUTENV -#define HAVE_VPRINTF - diff --git a/contrib/gcc/config/i386/xm-osf1elf.h b/contrib/gcc/config/i386/xm-osf1elf.h new file mode 100644 index 0000000..69ca9c1 --- /dev/null +++ b/contrib/gcc/config/i386/xm-osf1elf.h @@ -0,0 +1,6 @@ +/* Configuration for GCC for Intel i386 running OSF/1 1.3. */ + +#ifndef HZ +#include +#define HZ DEFAULT_CLK_TCK +#endif diff --git a/contrib/gcc/config/i386/xm-sco.h b/contrib/gcc/config/i386/xm-sco.h index 01a63d90..ad63449 100644 --- a/contrib/gcc/config/i386/xm-sco.h +++ b/contrib/gcc/config/i386/xm-sco.h @@ -1,18 +1,9 @@ /* Configuration for GCC for Intel i386 running SCO. */ -#include "i386/xm-sysv3.h" - -/* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). */ - -#define BROKEN_LDEXP - /* Big buffers improve performance. */ #define IO_BUFFER_SIZE (0x8000 - 1024) -/* SCO has a very small ARG_MAX. */ -#define SMALL_ARG_MAX - #ifndef __GNUC__ /* The SCO compiler gets it wrong, and treats enumerated bitfields as signed quantities, making it impossible to use an 8-bit enum diff --git a/contrib/gcc/config/i386/xm-sco5.h b/contrib/gcc/config/i386/xm-sco5.h new file mode 100644 index 0000000..6b22b1d --- /dev/null +++ b/contrib/gcc/config/i386/xm-sco5.h @@ -0,0 +1,7 @@ +/* Configuration for GCC for Intel i386 running SCO. */ + +/* Big buffers improve performance. */ + +#define IO_BUFFER_SIZE (0x8000 - 1024) + + diff --git a/contrib/gcc/config/i386/xm-sun.h b/contrib/gcc/config/i386/xm-sun.h index d2e714e..de7c201 100644 --- a/contrib/gcc/config/i386/xm-sun.h +++ b/contrib/gcc/config/i386/xm-sun.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for Intel 80386 running SunOS 4.0. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -21,7 +21,3 @@ Boston, MA 02111-1307, USA. */ #define USG #include "i386/xm-i386.h" - -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define bcmp(a,b,c) memcmp (a,b,c) diff --git a/contrib/gcc/config/i386/xm-sysv4.h b/contrib/gcc/config/i386/xm-sysv4.h index 49d52b4..1365064 100644 --- a/contrib/gcc/config/i386/xm-sysv4.h +++ b/contrib/gcc/config/i386/xm-sysv4.h @@ -1,16 +1,5 @@ /* Configuration for GCC for Intel i386 running System V Release 4. */ -#include "i386/xm-i386.h" -#include "xm-svr4.h" - -/* If not compiled with GNU C, use the portable alloca. */ -#ifndef __GNUC__ -#define USE_C_ALLOCA -#endif #ifdef __HIGHC__ #include /* for MetaWare High-C on NCR System 3000 */ #endif - -/* Univel, at least, has a small ARG_MAX. Defining this is harmless - except for causing extra stat calls in the driver program. */ -#define SMALL_ARG_MAX diff --git a/contrib/gcc/config/i386/xm-vsta.h b/contrib/gcc/config/i386/xm-vsta.h index bb333ae..735d1d5 100644 --- a/contrib/gcc/config/i386/xm-vsta.h +++ b/contrib/gcc/config/i386/xm-vsta.h @@ -1,26 +1,2 @@ -/* Configuration for GNU C-compiler for Intel 80386. - Copyright (C) 1994 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 NO_STAB_H - -#include "i386/xm-i386.h" - /* Use semicolons to separate elements of a path. */ #define PATH_SEPARATOR ';' diff --git a/contrib/gcc/config/libgloss.h b/contrib/gcc/config/libgloss.h new file mode 100644 index 0000000..2f2ba56 --- /dev/null +++ b/contrib/gcc/config/libgloss.h @@ -0,0 +1,35 @@ +/* libgloss.h -- operating system specific defines to be used when + targeting GCC for Libgloss supported targets. + Copyright (C) 1996 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. */ + +/* The libgloss standard for crt0.s has the name based on the command line + option. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{pg:pgcrt0%O%s}%{!pg:%{p:pcrt0%O%s}%{!p:crt0%O%s}}}" + +/* This file used to force LINK_SPEC to be the null string, but that is not + correct. LINK_SPEC is used to pass machine specific arguments to the + linker and hence can not be redefined here. LINK_SPEC is never used to + specify startup files or libraries, so it should never conflict with + libgloss. */ + +/* Don't set the target flags, this is done by the linker script */ +#undef LIB_SPEC +#define LIB_SPEC "" diff --git a/contrib/gcc/config/linux-aout.h b/contrib/gcc/config/linux-aout.h index 29fb8e9..ca8a39d 100644 --- a/contrib/gcc/config/linux-aout.h +++ b/contrib/gcc/config/linux-aout.h @@ -1,5 +1,5 @@ -/* Definitions for Linux - Copyright (C) 1995 Free Software Foundation, Inc. +/* Definitions for Linux-based GNU systems. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. @@ -25,7 +25,7 @@ Boston, MA 02111-1307, USA. */ #undef HAVE_ATEXIT #define HAVE_ATEXIT -/* Linux uses ctype from glibc.a. I am not sure how complete it is. +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. For now, we play safe. It may change later. */ #if 0 @@ -36,16 +36,13 @@ Boston, MA 02111-1307, USA. */ #undef STARTFILE_SPEC #define STARTFILE_SPEC "%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}" -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - #undef ASM_APP_ON #define ASM_APP_ON "#APP\n" #undef ASM_APP_OFF #define ASM_APP_OFF "#NO_APP\n" +#define SET_ASM_OP ".set" + /* We need that too. */ #define HANDLE_SYSV_PRAGMA diff --git a/contrib/gcc/config/linux.h b/contrib/gcc/config/linux.h index c82cfe2..b619d01 100644 --- a/contrib/gcc/config/linux.h +++ b/contrib/gcc/config/linux.h @@ -1,7 +1,7 @@ -/* Definitions for Linux with ELF format - Copyright (C) 1995 Free Software Foundation, Inc. +/* Definitions for Linux-based GNU systems with ELF format + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Contributed by Eric Youngdale. - Modified for stabs-in-ELF by H.J. Lu. + Modified for stabs-in-ELF by H.J. Lu (hjl@lucon.org). This file is part of GNU CC. @@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */ #undef HAVE_ATEXIT #define HAVE_ATEXIT -/* Linux uses ctype from glibc.a. I am not sure how complete it is. +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. For now, we play safe. It may change later. */ #if 0 @@ -34,18 +34,16 @@ Boston, MA 02111-1307, USA. */ #define MULTIBYTE_CHARS 1 #endif -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - #undef ASM_APP_ON #define ASM_APP_ON "#APP\n" #undef ASM_APP_OFF #define ASM_APP_OFF "#NO_APP\n" +#define SET_ASM_OP ".set" + /* Use stabs instead of DWARF debug format. */ +#undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG #include "svr4.h" @@ -61,28 +59,57 @@ Boston, MA 02111-1307, USA. */ fprintf (FILE, "\t.version\t\"01.01\"\n"); \ } while (0) -#undef LIBGCC_SPEC -#define LIBGCC_SPEC \ - "%{!shared:-lgcc}" - - -/* Provide a STARTFILE_SPEC appropriate for Linux. Here we add - the Linux magical crtbegin.o file (see crtstuff.c) which +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux 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: \ - %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + %{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 Linux. Here we tack on - the Linux magical crtend.o file (see crtstuff.c) which +/* 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 object constructed before entering `main', followed by a normal - Linux "finalizer" file, `crtn.o'. */ + GNU/Linux "finalizer" file, `crtn.o'. */ #undef ENDFILE_SPEC #define ENDFILE_SPEC \ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* This is for -profile to use -lc_p instead of -lc. */ +#ifndef CC1_SPEC +#define CC1_SPEC "%{profile:-p}" +#endif + +#ifndef USE_GNULIBC_1 +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 1 +#endif + +#undef LIB_SPEC +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -profile or -ggdb to LDFLAGS at the link time, respectively. */ +#if 1 +#ifdef USE_GNULIBC_1 +#define LIB_SPEC \ + "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \ + %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}" +#else +#define LIB_SPEC \ + "%{shared: -lc} \ + %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" +#endif +#else +#define LIB_SPEC \ + "%{!shared: \ + %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif diff --git a/contrib/gcc/config/lynx.h b/contrib/gcc/config/lynx.h index 04919d4..62c790b 100644 --- a/contrib/gcc/config/lynx.h +++ b/contrib/gcc/config/lynx.h @@ -1,5 +1,5 @@ /* Target independent definitions for LynxOS. - Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -133,12 +133,11 @@ do { \ #undef INIT_SECTION_ASM_OP #undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_bss, in_ctors, in_dtors, in_fini, +#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_fini #undef EXTRA_SECTION_FUNCTIONS #define EXTRA_SECTION_FUNCTIONS \ CONST_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION \ CTORS_SECTION_FUNCTION \ DTORS_SECTION_FUNCTION \ FINI_SECTION_FUNCTION diff --git a/contrib/gcc/config/netbsd.h b/contrib/gcc/config/netbsd.h index 8c0974a..0fb4d40 100644 --- a/contrib/gcc/config/netbsd.h +++ b/contrib/gcc/config/netbsd.h @@ -13,11 +13,11 @@ #define GCC_INCLUDE_DIR "/usr/include" #undef INCLUDE_DEFAULTS -#define INCLUDE_DEFAULTS \ - { \ - { GPLUSPLUS_INCLUDE_DIR, 1, 1 }, \ - { GCC_INCLUDE_DIR, 0, 0 }, \ - { 0, 0, 0 } \ +#define INCLUDE_DEFAULTS \ + { \ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \ + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \ + { 0, 0, 0, 0 } \ } /* Under NetBSD, the normal location of the compiler back ends is the @@ -58,8 +58,13 @@ #undef LINK_SPEC #define LINK_SPEC \ - "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" + "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{R*} %{static:-Bstatic} %{assert*}" +/* This defines which switch letters take arguments. */ +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ + || (CHAR) == 'R') /* We have atexit(3). */ @@ -68,28 +73,36 @@ /* Implicit library calls should use memcpy, not bcopy, etc. */ #define TARGET_MEM_FUNCTIONS + +/* Handle #pragma weak and #pragma pack. */ + +#define HANDLE_SYSV_PRAGMA /* * Some imports from svr4.h in support of shared libraries. * Currently, we need the DECLARE_OBJECT_SIZE stuff. */ -/* 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 the strings used for the .type, .size, and .set directives. + These strings generally do not vary from one system running netbsd + to another, but if a given system needs to use different pseudo-op + names for these, they may be overridden in the file which includes + this one. */ #undef TYPE_ASM_OP #undef SIZE_ASM_OP +#undef SET_ASM_OP #define TYPE_ASM_OP ".type" #define SIZE_ASM_OP ".size" +#define SET_ASM_OP ".set" /* This is how we tell the assembler that a symbol is weak. */ #undef ASM_WEAKEN_LABEL #define ASM_WEAKEN_LABEL(FILE,NAME) \ - do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ + do { fputs ("\t.globl\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); \ + 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 diff --git a/contrib/gcc/config/nextstep.c b/contrib/gcc/config/nextstep.c index 823bcee..e909a94 100644 --- a/contrib/gcc/config/nextstep.c +++ b/contrib/gcc/config/nextstep.c @@ -1,5 +1,5 @@ /* Functions for generic NeXT as target machine for GNU C compiler. - Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1989, 90-93, 96, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -18,6 +18,11 @@ 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 +#include "flags.h" +#include "tree.h" + /* Make everything that used to go in the text section really go there. */ int flag_no_mach_text_sections = 0; @@ -35,14 +40,17 @@ static int initial_optimize_flag; extern char *get_directive_line (); /* Called from check_newline via the macro HANDLE_PRAGMA. - FINPUT is the source file input stream. */ + FINPUT is the source file input stream. + CH is the first character after `#pragma'. + The result is 1 if the pragma was handled. */ -void -handle_pragma (finput, get_line_function) +int +handle_pragma (finput, node) FILE *finput; - char *(*get_line_function) (); + tree node; { - register char *p = (*get_line_function) (finput); + int retval = 0; + register char *pname; /* Record initial setting of optimize flag, so we can restore it. */ if (!pragma_initialized) @@ -51,17 +59,24 @@ handle_pragma (finput, get_line_function) initial_optimize_flag = optimize; } - if (OPT_STRCMP ("CC_OPT_ON")) + if (TREE_CODE (node) != IDENTIFIER_NODE) + return 0; + + pname = IDENTIFIER_POINTER (node); + + if (strcmp (pname, "CC_OPT_ON") == 0) { optimize = 1, obey_regdecls = 0; warning ("optimization turned on"); + retval = 1; } - else if (OPT_STRCMP ("CC_OPT_OFF")) + else if (strcmp (pname, "CC_OPT_OFF") == 0) { optimize = 0, obey_regdecls = 1; warning ("optimization turned off"); + retval = 1; } - else if (OPT_STRCMP ("CC_OPT_RESTORE")) + else if (strcmp (pname, "CC_OPT_RESTORE") == 0) { extern int initial_optimize_flag; @@ -74,11 +89,14 @@ handle_pragma (finput, get_line_function) optimize = initial_optimize_flag; } warning ("optimization level restored"); + retval = 1; } - else if (OPT_STRCMP ("CC_WRITABLE_STRINGS")) - flag_writable_strings = 1; - else if (OPT_STRCMP ("CC_NON_WRITABLE_STRINGS")) - flag_writable_strings = 0; - else if (OPT_STRCMP ("CC_NO_MACH_TEXT_SECTIONS")) - flag_no_mach_text_sections = 1; + else if (strcmp (pname, "CC_WRITABLE_STRINGS") == 0) + flag_writable_strings = retval = 1; + else if (strcmp (pname, "CC_NON_WRITABLE_STRINGS") == 0) + flag_writable_strings = 0, retval = 1; + else if (strcmp (pname, "CC_NO_MACH_TEXT_SECTIONS") == 0) + flag_no_mach_text_sections = retval = 1; + + return retval; } diff --git a/contrib/gcc/config/nextstep.h b/contrib/gcc/config/nextstep.h index 6e2e986..96435fc 100644 --- a/contrib/gcc/config/nextstep.h +++ b/contrib/gcc/config/nextstep.h @@ -1,6 +1,6 @@ -/* nextstep.h -- operating system specific defines to be used when - targeting GCC for NeXTSTEP. - Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. +/* Operating system specific defines to be used when targeting GCC + for NeXTSTEP. + Copyright (C) 1989, 90-93, 1996, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -27,26 +27,43 @@ Boston, MA 02111-1307, USA. */ #undef INCLUDE_DEFAULTS #define INCLUDE_DEFAULTS \ { \ - { GPLUSPLUS_INCLUDE_DIR, 1, 1 }, \ - { LOCAL_INCLUDE_DIR, 0, 1 }, \ - { TOOL_INCLUDE_DIR, 0, 1 }, \ - { GCC_INCLUDE_DIR, 0, 0 }, \ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \ + { LOCAL_INCLUDE_DIR, 0, 0, 1 }, \ + { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 }, \ + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \ /* These are for fixincludes-fixed ansi/bsd headers \ which wouldn't be found otherwise. \ (The use of string catenation here is OK since \ NeXT's native compiler is derived from GCC.) */ \ - { GCC_INCLUDE_DIR "/ansi", 0, 0 }, \ - { GCC_INCLUDE_DIR "/bsd", 0, 0 }, \ - { "/NextDeveloper/Headers", 0, 0 }, \ - { "/NextDeveloper/Headers/ansi", 0, 0 }, \ - { "/NextDeveloper/Headers/bsd", 0, 0 }, \ - { "/LocalDeveloper/Headers", 0, 0 }, \ - { "/LocalDeveloper/Headers/ansi", 0, 0 }, \ - { "/LocalDeveloper/Headers/bsd", 0, 0 }, \ - { "/NextDeveloper/2.0CompatibleHeaders", 0, 0 }, \ - { STANDARD_INCLUDE_DIR, 0, 0 }, \ - { "/usr/include/bsd", 0, 0 }, \ - { 0, 0, 0 } \ + { GCC_INCLUDE_DIR "/ansi", 0, 0, 0 }, \ + { GCC_INCLUDE_DIR "/bsd", 0, 0, 0 }, \ + { "/NextDeveloper/Headers", 0, 0, 0 }, \ + { "/NextDeveloper/Headers/ansi", 0, 0, 0 }, \ + { "/NextDeveloper/Headers/bsd", 0, 0, 0 }, \ + { "/LocalDeveloper/Headers", 0, 0, 0 }, \ + { "/LocalDeveloper/Headers/ansi", 0, 0, 0 }, \ + { "/LocalDeveloper/Headers/bsd", 0, 0, 0 }, \ + { "/NextDeveloper/2.0CompatibleHeaders", 0, 0, 0 }, \ + { STANDARD_INCLUDE_DIR, 0, 0, 0 }, \ + { "/usr/include/bsd", 0, 0, 0 }, \ + { 0, 0, 0, 0 } \ + } +#else /* CROSS_COMPILE */ +#undef INCLUDE_DEFAULTS +#define INCLUDE_DEFAULTS \ + { \ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \ + { GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 }, \ + { LOCAL_INCLUDE_DIR, 0, 0, 1 }, \ + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \ + { GCC_INCLUDE_DIR "/ansi", 0, 0, 0 }, \ + { GCC_INCLUDE_DIR "/bsd", 0, 0, 0 }, \ + { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 }, \ + { TOOL_INCLUDE_DIR "/ansi", 0, 0, 0 }, \ + { TOOL_INCLUDE_DIR "/bsd", 0, 0, 0 }, \ + { STANDARD_INCLUDE_DIR, 0, 0, 0 }, \ + { "/usr/include/bsd", 0, 0, 0 }, \ + { 0, 0, 0, 0 } \ } #endif /* CROSS_COMPILE */ @@ -152,11 +169,6 @@ Boston, MA 02111-1307, USA. */ %{p:%e-p profiling is no longer supported. Use -pg instead.} \ %{!p:-lposixcrt0.o}}}" -/* Why not? */ - -#undef DOLLARS_IN_IDENTIFIERS -#define DOLLARS_IN_IDENTIFIERS 2 - /* Allow #sscs (but don't do anything). */ #define SCCS_DIRECTIVE @@ -240,7 +252,7 @@ Boston, MA 02111-1307, USA. */ /* How to parse #pragma's */ #undef HANDLE_PRAGMA -#define HANDLE_PRAGMA(finput) handle_pragma (finput, &get_directive_line) +#define HANDLE_PRAGMA(FINPUT, NODE) handle_pragma (FINPUT, NODE) /* Give methods pretty symbol names on NeXT. */ @@ -254,6 +266,11 @@ Boston, MA 02111-1307, USA. */ (CLASS_NAME), (SEL_NAME)); \ } while (0) +/* The prefix to add to user-visible assembler symbols. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "_" + /* Wrap new method names in quotes so the assembler doesn't gag. Make Objective-C internal symbols local. */ @@ -263,7 +280,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", NAME); } while (0) + else fprintf (FILE, "%s%s", USER_LABEL_PREFIX, NAME); } while (0) #undef ALIGN_ASM_OP #define ALIGN_ASM_OP ".align" @@ -565,3 +582,9 @@ objc_section_init () \ const_section (); \ } \ while (0) + +#ifdef ASM_COMMENT_START +# undef ASM_COMMENT_START +#endif + +#define ASM_COMMENT_START ";#" diff --git a/contrib/gcc/config/openbsd.h b/contrib/gcc/config/openbsd.h new file mode 100644 index 0000000..af8358e --- /dev/null +++ b/contrib/gcc/config/openbsd.h @@ -0,0 +1,302 @@ +/* Base configuration file for all OpenBSD targets. + 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. */ + +/* Common OpenBSD configuration. + All OpenBSD architectures include this file, which is intended as + a repository for common defines. + + Some defines are common to all architectures, a few of them are + triggered by OBSD_* guards, so that we won't override architecture + defaults by mistakes. + + OBSD_HAS_CORRECT_SPECS: + another mechanism provides correct specs already. + OBSD_NO_DYNAMIC_LIBRARIES: + no implementation of dynamic libraries. + OBSD_OLD_GAS: + older flavor of gas which needs help for PIC. + OBSD_HAS_DECLARE_FUNCTION_NAME, OBSD_HAS_DECLARE_FUNCTION_SIZE, + OBSD_HAS_DECLARE_OBJECT: + PIC support, FUNCTION_NAME/FUNCTION_SIZE are independent, whereas + the corresponding logic for OBJECTS is necessarily coupled. + + There are also a few `default' defines such as ASM_WEAKEN_LABEL, + intended as common ground for arch that don't provide + anything suitable. */ + +/* OPENBSD_NATIVE is defined only when gcc is configured as part of + the OpenBSD source tree, specifically through Makefile.bsd-wrapper. + + In such a case the include path can be trimmed as there is no + distinction between system includes and gcc includes. */ + +/* This configuration method, namely Makefile.bsd-wrapper and + OPENBSD_NATIVE is NOT recommended for building cross-compilers. */ + +#ifdef OPENBSD_NATIVE + +#undef GCC_INCLUDE_DIR +#define GCC_INCLUDE_DIR "/usr/include" + +/* The compiler is configured with ONLY the gcc/g++ standard headers. */ +#undef INCLUDE_DEFAULTS +#define INCLUDE_DEFAULTS \ + { \ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \ + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \ + { 0, 0, 0, 0 } \ + } + +/* Under OpenBSD, the normal location of the various *crt*.o files is the + /usr/lib directory. */ +#define STANDARD_STARTFILE_PREFIX "/usr/lib/" + +#endif + + +/* Controlling the compilation driver. */ + +/* CPP_SPEC appropriate for OpenBSD. We deal with -posix and -pthread. + XXX the way threads are handling currently is not very satisfying, + since all code must be compiled with -pthread to work. + This two-stage defines makes it easy to pick that for targets that + have subspecs. */ +#define OBSD_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_POSIX_THREADS}" + +/* LIB_SPEC appropriate for OpenBSD. Select the appropriate libc, + depending on profiling and threads. Basically, + -lc(_r)?(_p)?, select _r for threads, and _p for p or pg. */ +#define OBSD_LIB_SPEC "-lc%{pthread:_r}%{p:_p}%{!p:%{pg:_p}}" + +#ifndef OBSD_HAS_CORRECT_SPECS + +#ifndef OBSD_NO_DYNAMIC_LIBRARIES +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG (CHAR) \ + || (CHAR) == 'R') +#endif + +#undef CPP_SPEC +#define CPP_SPEC OBSD_CPP_SPEC + +#ifdef OBSD_OLD_GAS +/* ASM_SPEC appropriate for OpenBSD. For some architectures, OpenBSD + still uses a special flavor of gas that needs to be told when generating + pic code. */ +#undef ASM_SPEC +#define ASM_SPEC "%{fpic:-k} %{fPIC:-k -K} %|" +#else +/* Since we use gas, stdin -> - is a good idea, but we don't want to + override native specs just for that. */ +#ifndef ASM_SPEC +#define ASM_SPEC "%|" +#endif +#endif + +/* LINK_SPEC appropriate for OpenBSD. Support for GCC options + -static, -assert, and -nostdlib. */ +#undef LINK_SPEC +#ifdef OBSD_NO_DYNAMIC_LIBRARIES +#define LINK_SPEC \ + "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{assert*}" +#else +#define LINK_SPEC \ + "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{R*} %{static:-Bstatic} %{assert*}" +#endif + +#undef LIB_SPEC +#define LIB_SPEC OBSD_LIB_SPEC +#endif + + +/* Runtime target specification. */ + +/* You must redefine CPP_PREDEFINES in any arch specific file. */ +#undef CPP_PREDEFINES + +/* Implicit calls to library routines. */ + +/* Use memcpy and memset instead of bcopy and bzero. */ +#define TARGET_MEM_FUNCTIONS + +/* Miscellaneous parameters. */ + +/* Tell libgcc2.c that OpenBSD targets support atexit. */ +#define HAVE_ATEXIT + +/* Controlling debugging info: dbx options. */ + +/* Don't use the `xsTAG;' construct in DBX output; OpenBSD systems that + use DBX don't support it. */ +#define DBX_NO_XREFS + + +/* Support of shared libraries, mostly imported from svr4.h through netbsd. */ +/* Two differences from svr4.h: + - we use . - _func instead of a local label, + - we put extra spaces in expressions such as + .type _func , @function + This is more readable for a human being and confuses c++filt less. */ + +/* Assembler format: output and generation of labels. */ + +/* Define the strings used for the .type and .size directives. + These strings generally do not vary from one system running OpenBSD + to another, but if a given system needs to use different pseudo-op + names for these, they may be overridden in the arch specific file. */ + +/* OpenBSD assembler is hacked to have .type & .size support even in a.out + format object files. Functions size are supported but not activated + yet (look for GRACE_PERIOD_EXPIRED in gas/config/obj-aout.c). */ + +#undef TYPE_ASM_OP +#undef SIZE_ASM_OP + +#define TYPE_ASM_OP ".type" +#define SIZE_ASM_OP ".size" + +/* The following macro defines the format used to output the second + operand of the .type assembler directive. */ +#undef TYPE_OPERAND_FMT +#define TYPE_OPERAND_FMT "@%s" + +/* Provision if extra assembler code is needed to declare a function's result + (taken from svr4, not needed yet actually). */ +#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 under OpenBSD. These macros also have to output the starting + labels for the relevant functions/objects. */ + +#ifndef OBSD_HAS_DECLARE_FUNCTION_NAME +/* Extra assembler code needed to declare a function properly. + Some assemblers may also need to also have something extra said + about the function's return value. We allow for that here. */ +#undef ASM_DECLARE_FUNCTION_NAME +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ + do { \ + fprintf (FILE, "\t%s\t", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fputs (" , ", FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ + putc ('\n', FILE); \ + ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } while (0) +#endif + +#ifndef OBSD_HAS_DECLARE_FUNCTION_SIZE +/* Declare the size of a function. */ +#undef ASM_DECLARE_FUNCTION_SIZE +#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ + do { \ + if (!flag_inhibit_size_directive) \ + { \ + fprintf (FILE, "\t%s\t", SIZE_ASM_OP); \ + assemble_name (FILE, (FNAME)); \ + fputs (" , . - ", FILE); \ + assemble_name (FILE, (FNAME)); \ + putc ('\n', FILE); \ + } \ + } while (0) +#endif + +#ifndef OBSD_HAS_DECLARE_OBJECT +/* Extra assembler code needed to declare an object properly. */ +#undef ASM_DECLARE_OBJECT_NAME +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fputs (" , ", 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. */ +#undef ASM_FINISH_DECLARE_OBJECT +#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) +#endif + + +/* Those are `generic' ways to weaken/globalize a label. We shouldn't need + to override a processor specific definition. Hence, #ifndef ASM_* + In case overriding turns out to be needed, one can always #undef ASM_* + before including this file. */ + +/* Tell the assembler that a symbol is weak. */ +/* Note: netbsd arm32 assembler needs a .globl here. An override may + be needed when/if we go for arm32 support. */ +#ifndef ASM_WEAKEN_LABEL +#define ASM_WEAKEN_LABEL(FILE,NAME) \ + do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); } while (0) +#endif + +/* Tell the assembler that a symbol is global. */ +#ifndef ASM_GLOBALIZE_LABEL +#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + do { fputs ("\t.globl\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); } while(0) +#endif + + +/* Storage layout. */ + +/* We don't have to worry about binary compatibility with older C++ code, + but there is a big known bug with vtable thunks which has not been + fixed yet, so DON'T activate it by default. */ +/* #define DEFAULT_VTABLE_THUNKS 1 */ + + +/* Otherwise, since we support weak, gthr.h erroneously tries to use + #pragma weak. */ +#define GTHREAD_USE_WEAK 0 + diff --git a/contrib/gcc/config/psos.h b/contrib/gcc/config/psos.h new file mode 100644 index 0000000..d404300 --- /dev/null +++ b/contrib/gcc/config/psos.h @@ -0,0 +1,183 @@ +/* Operating system specific defines to be used when targeting GCC for some + embedded system running pSOS. We assume GNU tools with ELF, but + try to maintain compatibility with the MRI tools. Based on svr4.h. + Copyright (C) 1996 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. + + To use this file, make up a file with a name like: + + ?????-psos.h + + where ????? is replaced by the name of the basic hardware that you + are targeting for. Then, in the file ?????-psos.h, put something + like: + + #include "?????.h" + #include "psos.h" + + followed by any really system-specific defines (or overrides of + defines) which you find that you need. +*/ + + +/* Define a symbol indicating that we are using psos.h. */ + +#define USING_PSOS_H + + +/* All pSOS targets currently use the ELF object file format. */ + +#define OBJECT_FORMAT_ELF + + +/* Provide a NULL STARTFILE_SPEC. The startfile cannot be specified + here because it depends on the architecture (e.g. 68K), the + board-support package (e.g. M162) and the run-time configuration + (e.g. application vs. ram-image vs. rom-image). Specify the + startfile in a linker-script created from the generic + architecture-specific linker-scripts. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + + +/* Predefined macros (independent of processor type). */ + +#define CPP_PREDEFINES "-Dpsos" + + +/* Implicit library calls should use ANSI memcpy rather than BSD + bcopy, etc. */ + +#define TARGET_MEM_FUNCTIONS + + +/* When using stabs, gcc2_compiled must be a stabs entry, not an + ordinary symbol, or gdb won't see it. The stabs entry must be + before the N_SO in order for gdb to find it. */ + +#define ASM_IDENTIFY_GCC(FILE) \ +do \ + { \ + fputs (".stabs \"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \ + } \ +while (0) + +/* 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) + +/* Switch into a generic section. */ + +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") + + +/* Define the pseudo-ops used to switch to the .ctors and .dtors + sections. */ + +#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" +#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" + +/* 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_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 \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +extern void text_section (); + +#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; \ + } \ +} + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ + +#ifndef INT_ASM_OP +#define INT_ASM_OP ".long" +#endif +#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) + + +/* Use DBX debugging info by default. */ + +#ifndef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#endif + +/* For pSOS we use DBX debugging info. */ + +#define DBX_DEBUGGING_INFO + + +/* Prevent generation of an exit function. */ + +#define HAVE_ATEXIT + diff --git a/contrib/gcc/config/ptx4.h b/contrib/gcc/config/ptx4.h new file mode 100644 index 0000000..aa31924 --- /dev/null +++ b/contrib/gcc/config/ptx4.h @@ -0,0 +1,859 @@ +/* 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. + Contributed by Ron Guilmette (rfg@monkeys.com). + Renamed and changed to suit Dynix/ptx v4 and later. + Modified by Tim Wright (timw@sequent.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. + +*/ + +/* Define a symbol indicating that we are using svr4.h. */ +#define USING_SVR4_H + +/* For the sake of libgcc2.c, indicate target supports atexit. */ +#define HAVE_ATEXIT + +/* Cpp, assembler, linker, library, and startfile spec's. */ + +/* This defines which switch letters take arguments. On svr4, most of + the normal cases (defined in gcc.c) apply, and we also have -h* and + -z* options (for the linker). Note however that there is no such + thing as a -T option for svr4. */ + +#define SWITCH_TAKES_ARG(CHAR) \ + ( (CHAR) == 'D' \ + || (CHAR) == 'U' \ + || (CHAR) == 'o' \ + || (CHAR) == 'e' \ + || (CHAR) == 'u' \ + || (CHAR) == 'I' \ + || (CHAR) == 'm' \ + || (CHAR) == 'L' \ + || (CHAR) == 'A' \ + || (CHAR) == 'h' \ + || (CHAR) == 'z') + +/* This defines which multi-letter switches take arguments. On svr4, + there are no such switches except those implemented by GCC itself. */ + +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + && strcmp (STR, "Tdata") && strcmp (STR, "Ttext") \ + && strcmp (STR, "Tbss")) + +/* You should redefine CPP_PREDEFINES in any file which includes this one. + The definition should be appropriate for the type of target system + involved, and it should include any -A (assertion) options which are + appropriate for the given target system. */ +#undef CPP_PREDEFINES + +/* Provide an ASM_SPEC appropriate for svr4. Here we try to support as + many of the specialized svr4 assembler options as seems reasonable, + given that there are certain options which we can't (or shouldn't) + support directly due to the fact that they conflict with other options + for other svr4 tools (e.g. ld) or with other options for GCC itself. + For example, we don't support the -o (output file) or -R (remove + input file) options because GCC already handles these things. We + also don't support the -m (run m4) option for the assembler because + that conflicts with the -m (produce load map) option of the svr4 + linker. We do however allow passing arbitrary options to the svr4 + assembler via the -Wa, option. + + Note that gcc doesn't allow a space to follow -Y in a -Ym,* or -Yd,* + option. +*/ + +#undef ASM_SPEC +#define ASM_SPEC \ + "-no_0f_fix %{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}" + +/* svr4 assemblers need the `-' (indicating input from stdin) to come after + the -o option (and its argument) for some reason. If we try to put it + before the -o option, the assembler will try to read the file named as + the output file in the -o option as an input file (after it has already + written some stuff to it) and the binary stuff contained therein will + cause totally confuse the assembler, resulting in many spurious error + messages. */ + +#undef ASM_FINAL_SPEC +#define ASM_FINAL_SPEC "%{pipe:-}" + +/* Provide a LIB_SPEC appropriate for svr4. Here we tack on the default + standard C library (unless we are building a shared library). */ + +#undef LIB_SPEC +#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}" + +/* Provide a LIBGCC_SPEC appropriate for svr4. We also want to exclude + libgcc when -symbolic. */ + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "%{!shared:%{!symbolic:-lgcc}}" + +/* Provide an ENDFILE_SPEC appropriate for svr4. Here we tack on our own + 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 the normal svr3/svr4 "finalizer" file, + which is either `gcrtn.o' or `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}" + +/* Provide a LINK_SPEC appropriate for svr4. Here we provide support + for the special GCC options -static, -shared, and -symbolic which + allow us to link things in one of these three modes by applying the + appropriate combinations of options at link-time. We also provide + support here for as many of the other svr4 linker options as seems + reasonable, given that some of them conflict with options for other + svr4 tools (e.g. the assembler). In particular, we do support the + -z*, -V, -b, -t, -Qy, -Qn, and -YP* options here, and the -e*, + -l*, -o*, -r, -s, -u*, and -L* options are directly supported + by gcc.c itself. We don't directly support the -m (generate load + map) option because that conflicts with the -m (run m4) option of + the svr4 assembler. We also don't directly support the svr4 linker's + -I* or -M* options because these conflict with existing GCC options. + We do however allow passing arbitrary options to the svr4 linker + via the -Wl, option. We don't support the svr4 linker's -a option + at all because it is totally useless and because it conflicts with + GCC's own -a option. + + Note that gcc doesn't allow a space to follow -Y in a -YP,* option. + + When the -G link option is used (-shared and -symbolic) a final link is + not being done. */ + +#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,/lib/libp:/usr/lib/libp:/lib:/usr/lib} \ + %{!p:-Y P,/lib:/usr/lib}} \ + %{Qy:} %{!Qn:-Qy}" + +/* Gcc automatically adds in one of the files /lib/values-Xc.o, + /lib/values-Xa.o, or /lib/values-Xt.o for each final link + step (depending upon the other gcc options selected, such as + -traditional and -ansi). These files each contain one (initialized) + copy of a special variable called `_lib_version'. Each one of these + files has `_lib_version' initialized to a different (enum) value. + The SVR4 library routines query the value of `_lib_version' at run + to decide how they should behave. Specifically, they decide (based + upon the value of `_lib_version') if they will act in a strictly ANSI + conforming manner or not. +*/ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\ + %{pg:gcrti.o%s}%{!pg:crti.o%s} \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.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 { \ + fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ + } while (0) + +/* Allow #sccs in preprocessor. */ + +#define SCCS_DIRECTIVE + +/* 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 + +/* The numbers used to denote specific machine registers in the System V + Release 4 DWARF debugging information are quite likely to be totally + different from the numbers used in BSD stabs debugging information + for the same kind of target machine. Thus, we undefine the macro + DBX_REGISTER_NUMBER here as an extra inducement to get people to + provide proper machine-specific definitions of DBX_REGISTER_NUMBER + (which is also used to provide DWARF registers numbers in dwarfout.c) + in their tm.h files which include this file. */ + +#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 + +/* 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. The stabs entry must be + before the N_SO in order for gdb to find it. */ + +#define ASM_IDENTIFY_GCC(FILE) \ +do \ + { \ + if (write_symbols != DBX_DEBUG) \ + fputs ("gcc2_compiled.:\n", FILE); \ + else \ + 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) \ + fprintf (FILE, \ + "\t.text\n\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO) + +/* Define the actual types of some ANSI-mandated types. (These + definitions should work for most SVR4 systems). */ + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* This causes trouble, because it requires the host machine + to support ANSI C. */ +/* #define MULTIBYTE_CHARS */ + +#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)) + +/* The prefix to add to user-visible assembler symbols. + + For System V Release 4 the convention is *not* to prepend a leading + underscore onto user-level symbol names. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +/* 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. + + 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, RELOC) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") + + +/* 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/sparc/aout.h b/contrib/gcc/config/sparc/aout.h new file mode 100644 index 0000000..478d710 --- /dev/null +++ b/contrib/gcc/config/sparc/aout.h @@ -0,0 +1,26 @@ +/* Definitions of target machine for GNU compiler, for SPARC using a.out. + Copyright (C) 1994, 1996 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@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. */ + +#include "sparc/sparc.h" /* SPARC definitions */ +#include "aoutos.h" /* A.out definitions */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)" diff --git a/contrib/gcc/config/sparc/bsd.h b/contrib/gcc/config/sparc/bsd.h new file mode 100644 index 0000000..761abe2 --- /dev/null +++ b/contrib/gcc/config/sparc/bsd.h @@ -0,0 +1,7 @@ +#include "sparc/sparc.h" + +#undef LIB_SPEC +#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:gcrt0.o%s}%{!p:crt0.o%s}}" diff --git a/contrib/gcc/config/sparc/elf.h b/contrib/gcc/config/sparc/elf.h new file mode 100644 index 0000000..70cb26a --- /dev/null +++ b/contrib/gcc/config/sparc/elf.h @@ -0,0 +1,42 @@ +/* Definitions of target machine for GNU compiler, + for SPARC running in an embedded environment using the ELF file format. + Copyright (C) 1997 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 "sol2.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -D__elf__ -Acpu(sparc) -Amachine(sparc)" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +/* Use the default. */ +#undef LINK_SPEC + +/* Don't set the target flags, this is done by the linker script */ +#undef LIB_SPEC +#define LIB_SPEC "" + +/* FIXME: until fixed */ +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 64 diff --git a/contrib/gcc/config/sparc/gmon-sol2.c b/contrib/gcc/config/sparc/gmon-sol2.c new file mode 100644 index 0000000..2a5b898 --- /dev/null +++ b/contrib/gcc/config/sparc/gmon-sol2.c @@ -0,0 +1,429 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Mangled into a form that works on Sparc Solaris 2 by Mark Eichin + * for Cygnus Support, July 1992. + */ + +#ifndef lint +static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#if 0 +#include "sparc/gmon.h" +#else +struct phdr { + char *lpc; + char *hpc; + int ncnt; +}; +#define HISTFRACTION 2 +#define HISTCOUNTER unsigned short +#define HASHFRACTION 1 +#define ARCDENSITY 2 +#define MINARCS 50 +struct tostruct { + char *selfpc; + long count; + unsigned short link; +}; +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +#endif + +/* extern mcount() asm ("mcount"); */ +/*extern*/ char *minbrk /* asm ("minbrk") */; + + /* + * froms is actually a bunch of unsigned shorts indexing tos + */ +static int profiling = 3; +static unsigned short *froms; +static struct tostruct *tos = 0; +static long tolimit = 0; +static char *s_lowpc = 0; +static char *s_highpc = 0; +static unsigned long s_textsize = 0; + +static int ssiz; +static char *sbuf; +static int s_scale; + /* see profil(2) where this is describe (incorrectly) */ +#define SCALE_1_TO_1 0x10000L + +#define MSG "No space for profiling buffer(s)\n" + +static void moncontrol(); + +void monstartup(lowpc, highpc) + char *lowpc; + char *highpc; +{ + int monsize; + char *buffer; + register int o; + + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + lowpc = (char *) + ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_lowpc = lowpc; + highpc = (char *) + ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_highpc = highpc; + s_textsize = highpc - lowpc; + monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr); + buffer = sbrk( monsize ); + if ( buffer == (char *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + return; + } + froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION ); + if ( froms == (unsigned short *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + return; + } + tolimit = s_textsize * ARCDENSITY / 100; + if ( tolimit < MINARCS ) { + tolimit = MINARCS; + } else if ( tolimit > 65534 ) { + tolimit = 65534; + } + tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) ); + if ( tos == (struct tostruct *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + tos = 0; + return; + } + minbrk = sbrk(0); + tos[0].link = 0; + sbuf = buffer; + ssiz = monsize; + ( (struct phdr *) buffer ) -> lpc = lowpc; + ( (struct phdr *) buffer ) -> hpc = highpc; + ( (struct phdr *) buffer ) -> ncnt = ssiz; + monsize -= sizeof(struct phdr); + if ( monsize <= 0 ) + return; + o = highpc - lowpc; + if( monsize < o ) +#ifndef hp300 + s_scale = ( (float) monsize / o ) * SCALE_1_TO_1; +#else /* avoid floating point */ + { + int quot = o / monsize; + + if (quot >= 0x10000) + s_scale = 1; + else if (quot >= 0x100) + s_scale = 0x10000 / quot; + else if (o >= 0x800000) + s_scale = 0x1000000 / (o / (monsize >> 8)); + else + s_scale = 0x1000000 / ((o << 8) / monsize); + } +#endif + else + s_scale = SCALE_1_TO_1; + moncontrol(1); +} + +void +_mcleanup() +{ + int fd; + int fromindex; + int endfrom; + char *frompc; + int toindex; + struct rawarc rawarc; + char *profdir; + char *proffile; + char *progname; + char buf[PATH_MAX]; + extern char **___Argv; + + moncontrol(0); + + if ((profdir = getenv("PROFDIR")) != NULL) { + /* If PROFDIR contains a null value, no profiling output is produced */ + if (*profdir == '\0') { + return; + } + + progname=strrchr(___Argv[0], '/'); + if (progname == NULL) + progname=___Argv[0]; + else + progname++; + + sprintf(buf, "%s/%ld.%s", profdir, getpid(), progname); + proffile = buf; + } else { + proffile = "gmon.out"; + } + + fd = creat( proffile, 0666 ); + if ( fd < 0 ) { + perror( proffile ); + return; + } +# ifdef DEBUG + fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); +# endif DEBUG + write( fd , sbuf , ssiz ); + endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); + for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { + if ( froms[fromindex] == 0 ) { + continue; + } + frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); + for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { +# ifdef DEBUG + fprintf( stderr , + "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , + frompc , tos[toindex].selfpc , tos[toindex].count ); +# endif DEBUG + rawarc.raw_frompc = (unsigned long) frompc; + rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; + rawarc.raw_count = tos[toindex].count; + write( fd , &rawarc , sizeof rawarc ); + } + } + close( fd ); +} + +/* + * The Sparc stack frame is only held together by the frame pointers + * in the register windows. According to the SVR4 SPARC ABI + * Supplement, Low Level System Information/Operating System + * Interface/Software Trap Types, a type 3 trap will flush all of the + * register windows to the stack, which will make it possible to walk + * the frames and find the return addresses. + * However, it seems awfully expensive to incur a trap (system + * call) for every function call. It turns out that "call" simply puts + * the return address in %o7 expecting the "save" in the procedure to + * shift it into %i7; this means that before the "save" occurs, %o7 + * contains the address of the call to mcount, and %i7 still contains + * the caller above that. The asm mcount here simply saves those + * registers in argument registers and branches to internal_mcount, + * simulating a call with arguments. + * Kludges: + * 1) the branch to internal_mcount is hard coded; it should be + * possible to tell asm to use the assembler-name of a symbol. + * 2) in theory, the function calling mcount could have saved %i7 + * somewhere and reused the register; in practice, I *think* this will + * break longjmp (and maybe the debugger) but I'm not certain. (I take + * some comfort in the knowledge that it will break the native mcount + * as well.) + * 3) if builtin_return_address worked, this could be portable. + * However, it would really have to be optimized for arguments of 0 + * and 1 and do something like what we have here in order to avoid the + * trap per function call performance hit. + * 4) the atexit and monsetup calls prevent this from simply + * being a leaf routine that doesn't do a "save" (and would thus have + * access to %o7 and %i7 directly) but the call to write() at the end + * would have also prevented this. + * + * -- [eichin:19920702.1107EST] + */ + +/* i7 == last ret, -> frompcindex */ +/* o7 == current ret, -> selfpc */ +/* Solaris 2 libraries use _mcount. */ +asm(".global _mcount; _mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount"); +/* This is for compatibility with old versions of gcc which used mcount. */ +asm(".global mcount; mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount"); + +static void internal_mcount(selfpc, frompcindex) + register char *selfpc; + register unsigned short *frompcindex; +{ + register struct tostruct *top; + register struct tostruct *prevtop; + register long toindex; + static char already_setup; + + /* + * find the return address for mcount, + * and the return address for mcount's caller. + */ + + if(!already_setup) { + extern etext(); + already_setup = 1; + monstartup(0, etext); +#ifdef USE_ONEXIT + on_exit(_mcleanup, 0); +#else + atexit(_mcleanup); +#endif + } + /* + * check that we are profiling + * and that we aren't recursively invoked. + */ + if (profiling) { + goto out; + } + profiling++; + /* + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); + if ((unsigned long)frompcindex > s_textsize) { + goto done; + } + frompcindex = + &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; + toindex = *frompcindex; + if (toindex == 0) { + /* + * first time traversing this arc + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + *frompcindex = toindex; + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &tos[toindex]; + if (top->selfpc == selfpc) { + /* + * arc at front of chain; usual case. + */ + top->count++; + goto done; + } + /* + * have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (; /* goto done */; ) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &tos[top->link]; + if (top->selfpc == selfpc) { + /* + * there it is. + * increment its count + * move it to the head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + + } +done: + profiling--; + /* and fall through */ +out: + return; /* normal return restores saved registers */ + +overflow: + profiling++; /* halt further profiling */ +# define TOLIMIT "mcount: tos overflow\n" + write(2, TOLIMIT, sizeof(TOLIMIT)); + goto out; +} + +/* + * Control profiling + * profiling is what mcount checks to see if + * all the data structures are ready. + */ +static void moncontrol(mode) + int mode; +{ + if (mode) { + /* start */ + profil((unsigned short *)(sbuf + sizeof(struct phdr)), + ssiz - sizeof(struct phdr), + (int)s_lowpc, s_scale); + profiling = 0; + } else { + /* stop */ + profil((unsigned short *)0, 0, 0, 0); + profiling = 3; + } +} diff --git a/contrib/gcc/config/sparc/lb1spc.asm b/contrib/gcc/config/sparc/lb1spc.asm new file mode 100644 index 0000000..831f33a --- /dev/null +++ b/contrib/gcc/config/sparc/lb1spc.asm @@ -0,0 +1,784 @@ +/* This is an assembly language implementation of libgcc1.c for the sparc + processor. + + These routines are derived from the Sparc Architecture Manual, version 8, + slightly edited to match the desired calling convention, and also to + optimize them for our purposes. */ + +#ifdef L_mulsi3 +.text + .align 4 + .global .umul + .proc 4 +.umul: + or %o0, %o1, %o4 ! logical or of multiplier and multiplicand + mov %o0, %y ! multiplier to Y register + andncc %o4, 0xfff, %o5 ! mask out lower 12 bits + be mul_shortway ! can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear NV cc + ! + ! long multiply + ! + mulscc %o4, %o1, %o4 ! first iteration of 33 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 ! 32nd iteration + mulscc %o4, %g0, %o4 ! last iteration only shifts + ! the upper 32 bits of product are wrong, but we do not care + retl + rd %y, %o0 + ! + ! short multiply + ! +mul_shortway: + mulscc %o4, %o1, %o4 ! first iteration of 13 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 ! 12th iteration + mulscc %o4, %g0, %o4 ! last iteration only shifts + rd %y, %o5 + sll %o4, 12, %o4 ! left shift partial product by 12 bits + srl %o5, 20, %o5 ! right shift partial product by 20 bits + retl + or %o5, %o4, %o0 ! merge for true product +#endif + +#ifdef L_divsi3 +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .div name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + .global .udiv + .align 4 + .proc 4 + .text +.udiv: + b ready_to_divide + mov 0, %g3 ! result is always positive + + .global .div + .align 4 + .proc 4 + .text +.div: + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge ready_to_divide ! no, go do the divide + xor %o1, %o0, %g3 ! compute sign in any case + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge ready_to_divide ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative + + +ready_to_divide: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta 0x2 ! ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu got_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu not_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc not_too_big + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b do_single_div + sub %g2, 1, %g2 + + not_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be do_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + do_single_div: + subcc %g2, 1, %g2 + bl end_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b end_single_divloop + nop + single_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + end_single_divloop: + subcc %g2, 1, %g2 + bge single_divloop + tst %o3 + b,a end_regular_divide + +not_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be got_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +divloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +L3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + +L2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + +L3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + +L1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + +L3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + +L2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + +L3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + 9: +end_regular_divide: + subcc %o4, 1, %o4 + bge divloop + tst %o3 + bl,a got_result + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +got_result: + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o2, %o2 +1: + retl + mov %o2, %o0 +#endif + +#ifdef L_modsi3 +/* This implementation was taken from glibc: + * + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ +.text + .align 4 + .global .urem + .proc 4 +.urem: + b divide + mov 0, %g3 ! result always positive + + .align 4 + .global .rem + .proc 4 +.rem: + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + mov %o0, %g3 ! sign of remainder matches %o0 + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. +divide: + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta 0x2 !ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu got_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu not_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc not_too_big + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b do_single_div + sub %g2, 1, %g2 + + not_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be do_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + do_single_div: + subcc %g2, 1, %g2 + bl end_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b end_single_divloop + nop + single_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + end_single_divloop: + subcc %g2, 1, %g2 + bge single_divloop + tst %o3 + b,a end_regular_divide + +not_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be got_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +divloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 +L4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + +L3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + +L2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + +L3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + +L1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + +L3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + +L2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + +L3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + 9: +end_regular_divide: + subcc %o4, 1, %o4 + bge divloop + tst %o3 + bl,a got_result + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + +got_result: + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o3, %o3 +1: + retl + mov %o3, %o0 + +#endif + diff --git a/contrib/gcc/config/sparc/lb1spl.asm b/contrib/gcc/config/sparc/lb1spl.asm new file mode 100644 index 0000000..4c8bc30 --- /dev/null +++ b/contrib/gcc/config/sparc/lb1spl.asm @@ -0,0 +1,246 @@ +/* This is an assembly language implementation of libgcc1.c for the sparclite + processor. + + These routines are all from the Sparclite User's Guide, slightly edited + to match the desired calling convention, and also to optimize them. */ + +#ifdef L_udivsi3 +.text + .align 4 + .global .udiv + .proc 04 +.udiv: + wr %g0,%g0,%y ! Not a delayed write for sparclite + tst %g0 + divscc %o0,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + retl + divscc %g1,%o1,%o0 +#endif + +#ifdef L_umodsi3 +.text + .align 4 + .global .urem + .proc 04 +.urem: + wr %g0,%g0,%y ! Not a delayed write for sparclite + tst %g0 + divscc %o0,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + divscc %g1,%o1,%g1 + bl 1f + rd %y,%o0 + retl + nop +1: retl + add %o0,%o1,%o0 +#endif + +#ifdef L_divsi3 +.text + .align 4 + .global .div + .proc 04 +! ??? This routine could be made faster if was optimized, and if it was +! rewritten to only calculate the quotient. +.div: + wr %g0,%g0,%y ! Not a delayed write for sparclite + mov %o1,%o4 + tst %o1 + bl,a 1f + sub %g0,%o4,%o4 +1: tst %o0 + bl,a 2f + mov -1,%y +2: divscc %o0,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + be 6f + mov %y,%o3 + bg 4f + addcc %o3,%o4,%g0 + be,a 6f + mov %g0,%o3 + tst %o0 + bl 5f + tst %g1 + ba 5f + add %o3,%o4,%o3 +4: subcc %o3,%o4,%g0 + be,a 6f + mov %g0,%o3 + tst %o0 + bge 5f + tst %g1 + sub %o3,%o4,%o3 +5: bl,a 6f + add %g1,1,%g1 +6: tst %o1 + bl,a 7f + sub %g0,%g1,%g1 +7: retl + mov %g1,%o0 ! Quotient is in %g1. +#endif + +#ifdef L_modsi3 +.text + .align 4 + .global .rem + .proc 04 +! ??? This routine could be made faster if was optimized, and if it was +! rewritten to only calculate the remainder. +.rem: + wr %g0,%g0,%y ! Not a delayed write for sparclite + mov %o1,%o4 + tst %o1 + bl,a 1f + sub %g0,%o4,%o4 +1: tst %o0 + bl,a 2f + mov -1,%y +2: divscc %o0,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + divscc %g1,%o4,%g1 + be 6f + mov %y,%o3 + bg 4f + addcc %o3,%o4,%g0 + be,a 6f + mov %g0,%o3 + tst %o0 + bl 5f + tst %g1 + ba 5f + add %o3,%o4,%o3 +4: subcc %o3,%o4,%g0 + be,a 6f + mov %g0,%o3 + tst %o0 + bge 5f + tst %g1 + sub %o3,%o4,%o3 +5: bl,a 6f + add %g1,1,%g1 +6: tst %o1 + bl,a 7f + sub %g0,%g1,%g1 +7: retl + mov %o3,%o0 ! Remainder is in %o3. +#endif diff --git a/contrib/gcc/config/sparc/linux-aout.h b/contrib/gcc/config/sparc/linux-aout.h new file mode 100644 index 0000000..76d7653 --- /dev/null +++ b/contrib/gcc/config/sparc/linux-aout.h @@ -0,0 +1,130 @@ +/* Definitions for SPARC running Linux-based GNU systems with a.out. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Eddie C. Dost (ecd@skynet.be) + +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 +#include + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. + For now, we play safe. It may change later. */ + +#if 0 +#undef MULTIBYTE_CHARS +#define MULTIBYTE_CHARS 1 +#endif + +/* We need that too. */ +#define HANDLE_SYSV_PRAGMA + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* 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); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with a.out)"); + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -Dsparc -Dlinux -Asystem(unix) -Asystem(posix)" + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" + +/* Don't default to pcc-struct-return, because gcc is the only compiler, + and we want to retain compatibility with older gcc versions. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +#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 GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#define LIB_SPEC \ +"%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" +#else +#define LIB_SPEC \ +"%{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg -static}}}" +#endif + +#undef LINK_SPEC +#define LINK_SPEC "-m sparclinux" + +/* 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:%{!V:-V}} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} %{fPIC:-K PIC}" + +#if 0 +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. GNU/Linux does not support + long double yet. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h new file mode 100644 index 0000000..7bbbfa4 --- /dev/null +++ b/contrib/gcc/config/sparc/linux.h @@ -0,0 +1,259 @@ +/* Definitions for SPARC running Linux-based GNU systems with ELF. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Eddie C. Dost (ecd@skynet.be) + +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 LINUX_DEFAULT_ELF + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. + For now, we play safe. It may change later. */ + +#if 0 +#undef MULTIBYTE_CHARS +#define MULTIBYTE_CHARS 1 +#endif + +#ifndef USE_GNULIBC_1 +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 1 +#endif + +/* Use stabs instead of DWARF debug format. */ +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* 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); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux 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: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* 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 + object constructed before entering `main', followed by a normal + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* This is for -profile to use -lc_p instead of -lc. */ +#undef CC1_SPEC +#define CC1_SPEC "%{profile:-p} \ +%{sun4:} %{target:} \ +%{mcypress:-mcpu=cypress} \ +%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \ +%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \ +" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with ELF)"); + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Dunix -Dsparc -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)" + +#undef CPP_SUBTARGET_SPEC +#ifdef USE_GNULIBC_1 +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" +#else +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" +#endif + +#undef LIB_SPEC +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#if 1 +#ifdef USE_GNULIBC_1 +#define LIB_SPEC \ + "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \ + %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}" +#else +#define LIB_SPEC \ + "%{shared: -lc} \ + %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" +#endif +#else +#define LIB_SPEC \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif + +/* Provide a LINK_SPEC appropriate for GNU/Linux. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +/* If ELF is the default format, we should not use /lib/elf. */ + +#undef LINK_SPEC +#ifdef USE_GNULIBC_1 +#ifndef LINUX_DEFAULT_ELF +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/elf/ld-linux.so.1} \ + %{!rpath:-rpath /lib/elf/}} %{static:-static}}}" +#else +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \ + %{static:-static}}}" +#endif +#else +#define LINK_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}}}" +#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:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} %{fPIC:-K PIC}" + +/* Same as sparc.h */ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* We use stabs-in-elf for debugging, because that is what the native + toolchain uses. XXX */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* 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'. */ + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + + +#if 0 +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. GNU/Linux does not support + long double yet. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h new file mode 100644 index 0000000..77bc668 --- /dev/null +++ b/contrib/gcc/config/sparc/linux64.h @@ -0,0 +1,245 @@ +/* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF. + Copyright 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by David S. Miller (davem@caip.rutgers.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. */ + +/* ??? bi-architecture support will require changes to the linker + related specs, among perhaps other things (multilibs). */ +/* #define SPARC_BI_ARCH */ + +#define LINUX_DEFAULT_ELF + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +#include + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* 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); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +#undef ASM_CPU_DEFAULT_SPEC +#define ASM_CPU_DEFAULT_SPEC "-Av9a" + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux 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: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* 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 + object constructed before entering `main', followed by a normal + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc64 GNU/Linux with ELF)"); + +/* A 64 bit v9 compiler with stack-bias, + in a Medium/Anywhere 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) + +/* The default code model. */ +#undef SPARC_DEFAULT_CMODEL +#define SPARC_DEFAULT_CMODEL CM_MEDANY + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#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)" + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "\ +%{fPIC:-D__PIC__ -D__pic__} \ +%{fpic:-D__PIC__ -D__pic__} \ +%{posix:-D_POSIX_SOURCE} \ +%{pthread:-D_REENTRANT} \ +" + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{shared: -lc} \ + %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" + +/* Provide a LINK_SPEC appropriate for GNU/Linux. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +/* If ELF is the default format, we should not use /lib/elf. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf64_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux64.so.2}} \ + %{static:-static}}} \ +%{mlittle-endian:-EL} \ +" + +/* 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:%{!V:-V}} \ +%{!Qn:-Qy} \ +%{n} \ +%{T} \ +%{Ym,*} \ +%{Wa,*:%*} \ +-s %{fpic:-K PIC} %{fPIC:-K PIC} \ +%{mlittle-endian:-EL} \ +%(asm_cpu) %(asm_arch) \ +" + +/* Same as sparc.h */ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* System V Release 4 uses DWARF debugging info. Buf DWARF1 doesn't do + 64-bit anything, so we use DWARF2. */ + +#undef DWARF2_DEBUGGING_INFO +#undef DWARF_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO +#define DWARF2_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* 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'. */ + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + +/* Stabs doesn't use this, and it confuses a simulator. */ +/* ??? Need to see what DWARF needs, if anything. */ +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(FILE) + +/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler. + ??? If ints are 64 bits then UNALIGNED_INT_ASM_OP (defined elsewhere) is + misnamed. These should all refer to explicit sizes (half/word/xword?), + anything other than short/int/long/etc. */ + +#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword" + +/* DWARF bits. */ + +/* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets. + Obviously the Dwarf2 folks havn't tried to actually build systems + with their spec. On a 64-bit system, only 64-bit relocs become + RELATIVE relocations. */ + +/* #define DWARF_OFFSET_SIZE PTR_SIZE */ + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); diff --git a/contrib/gcc/config/sparc/lite.h b/contrib/gcc/config/sparc/lite.h new file mode 100644 index 0000000..55c232a --- /dev/null +++ b/contrib/gcc/config/sparc/lite.h @@ -0,0 +1,38 @@ +/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU. + Copyright (C) 1993, 1996 Free Software Foundation, Inc. + Contributed by Jim Wilson (wilson@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. */ + +#include "sparc/sparc.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu(sparc) -Amachine(sparc)" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparclite)"); + +/* Enable app-regs and epilogue options. Do not enable the fpu. */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE) + +/* US Software GOFAST library support. */ +#include "gofast.h" +#undef INIT_SUBTARGET_OPTABS +#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS diff --git a/contrib/gcc/config/sparc/litecoff.h b/contrib/gcc/config/sparc/litecoff.h new file mode 100644 index 0000000..bd89e1b --- /dev/null +++ b/contrib/gcc/config/sparc/litecoff.h @@ -0,0 +1,113 @@ +/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU, COFF. + Copyright (C) 1994, 1996 Free Software Foundation, Inc. + Written by Ken Raeburn (raeburn@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. */ + +#include "sparc/lite.h" + +#undef ASM_OUTPUT_IDENT + +#undef SELECT_SECTION +#undef SELECT_RTX_SECTION +#define BSS_SECTION_ASM_OP ".section\t\".bss\"" + +#include "svr3.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu(sparc) -Amachine(sparc)" + +/* Default to stabs in COFF. */ + +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "dbxcoff.h" + +/* Support the ctors and dtors sections for g++. */ + +#undef INIT_SECTION_ASM_OP + +/* Support the ctors and dtors sections for g++. */ + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\"" +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\"" + +/* A list of other sections which the compiler might be "in" at any + given time. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_ctors, in_dtors + +/* A list of extra section function definitions. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#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. */ +#undef ASM_OUTPUT_CONSTRUCTOR +#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. */ +#undef ASM_OUTPUT_DESTRUCTOR +#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) + +#undef DO_GLOBAL_CTORS_BODY +#undef DO_GLOBAL_DTORS_BODY diff --git a/contrib/gcc/config/sparc/lynx-ng.h b/contrib/gcc/config/sparc/lynx-ng.h new file mode 100644 index 0000000..9e9f82c --- /dev/null +++ b/contrib/gcc/config/sparc/lynx-ng.h @@ -0,0 +1,41 @@ +/* Definitions for SPARC running LynxOS, using Lynx's old as and ld. + Copyright (C) 1993, 1995 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 +#include + +/* ??? Must redefine to get sparclite and v8 defines. Can this be done + differently? */ + +#undef CPP_SPEC +#define CPP_SPEC "%{mthreads:-D_MULTITHREADED} \ + %{mposix:-D_POSIX_SOURCE} \ + %{msystem-v:-I/usr/include_v} \ + %(cpp_cpu)" + +/* Names to predefine in the preprocessor for this target machine. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -Dsparc -DLynx -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(sparc) -Amachine(sparc)" + +/* Provide required defaults for linker switches. */ + +#undef LINK_SPEC +#define LINK_SPEC "-e __main -T 0 %{msystem-v:-V} %{mcoff:-k}" diff --git a/contrib/gcc/config/sparc/lynx.h b/contrib/gcc/config/sparc/lynx.h new file mode 100644 index 0000000..99b319a --- /dev/null +++ b/contrib/gcc/config/sparc/lynx.h @@ -0,0 +1,53 @@ +/* Definitions for SPARC running LynxOS. + Copyright (C) 1993, 1995, 1996 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 + +#undef ASM_OUTPUT_IDENT +#undef SELECT_SECTION +#undef SELECT_RTX_SECTION + +#define BSS_SECTION_ASM_OP ".section\t\".bss\"" + +#include + +/* ??? Must redefine to get sparclite and v8 defines. Can this be done + differently? */ + +#undef CPP_SPEC +#define CPP_SPEC "%{mthreads:-D_MULTITHREADED} \ + %{mposix:-D_POSIX_SOURCE} \ + %{msystem-v:-I/usr/include_v} \ + %(cpp_cpu)" + +/* Names to predefine in the preprocessor for this target machine. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -Dsparc -DSPARC -DLynx -DLYNX -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(sparc) -Amachine(sparc)" + +#undef LINK_SPEC + +/* Sparc version of libc.a has references to libm.a (printf calls pow for + instance), so we must always link both. */ + +#undef LIB_SPEC +#define LIB_SPEC "%{mthreads:-L/lib/thread/} \ + %{msystem-v:-lc_v -lm_v -lc_v} \ + %{!msystem-v:%{mposix:-lc_p} -lc -lm -lc}" diff --git a/contrib/gcc/config/sparc/netbsd.h b/contrib/gcc/config/sparc/netbsd.h new file mode 100644 index 0000000..a512f41 --- /dev/null +++ b/contrib/gcc/config/sparc/netbsd.h @@ -0,0 +1,46 @@ +#include + +/* Get generic NetBSD definitions. */ + +#include + +/* Names to predefine in the preprocessor for this target machine. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -Dsparc -D__NetBSD__ -Asystem(unix) -Asystem(NetBSD) -Acpu(sparc) -Amachine(sparc)" + +/* Make gcc agree with */ + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_UNSIGNED +#define WCHAR_UNSIGNED 0 + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +/* This is BSD, so it wants DBX format. */ + +#define DBX_DEBUGGING_INFO + +/* This is the char to use for continuation (in case we need to turn + continuation back on). */ + +#define DBX_CONTIN_CHAR '?' + +/* Don't default to pcc-struct-return, because gcc is the only compiler, and + we want to retain compatibility with older gcc versions. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Until they use ELF or something that handles dwarf2 unwinds + and initialization stuff better. */ +#define DWARF2_UNWIND_INFO 0 + diff --git a/contrib/gcc/config/sparc/openbsd.h b/contrib/gcc/config/sparc/openbsd.h new file mode 100644 index 0000000..19ece97 --- /dev/null +++ b/contrib/gcc/config/sparc/openbsd.h @@ -0,0 +1,68 @@ +/* Configuration file for sparc OpenBSD target. + 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 + +/* Get generic OpenBSD definitions. */ +#define OBSD_OLD_GAS +#include + +/* Run-time target specifications. */ +#define CPP_PREDEFINES "-D__unix__ -D__sparc__ -D__OpenBSD__ -Asystem(unix) -Asystem(OpenBSD) -Acpu(sparc) -Amachine(sparc)" + +/* Layout of source language data types */ + +/* This must agree with */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +/* Specific options for DBX Output. */ + +/* This is BSD, so it wants DBX format. */ +#define DBX_DEBUGGING_INFO + +/* This is the char to use for continuation */ +#define DBX_CONTIN_CHAR '?' + +/* Stack & calling: aggregate returns. */ + +/* Don't default to pcc-struct-return, because gcc is the only compiler, and + we want to retain compatibility with older gcc versions. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Assembler format: exception region output. */ + +/* All configurations that don't use elf must be explicit about not using + dwarf unwind information. egcs doesn't try too hard to check internal + configuration files... */ +#define DWARF2_UNWIND_INFO 0 + +/* Default sparc.h does already define ASM_OUTPUT_MI_THUNK */ + diff --git a/contrib/gcc/config/sparc/pbd.h b/contrib/gcc/config/sparc/pbd.h new file mode 100644 index 0000000..459bffd --- /dev/null +++ b/contrib/gcc/config/sparc/pbd.h @@ -0,0 +1,184 @@ +/* Definitions of target machine for GNU compiler, Citicorp/TTI Unicom PBD + version (using GAS and COFF (encapsulated is unacceptable) ) + Copyright (C) 1990, 1996 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/sparc.h" + +/* Names to predefine in the preprocessor for this target machine. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -DUnicomPBD -Dunix -D__GCC_NEW_VARARGS__ -Asystem(unix) -Acpu(sparc) -Amachine(sparc)" + +/* We want DBX format for use with gdb under COFF. */ + +#define DBX_DEBUGGING_INFO + +/* Generate calls to memcpy, memcmp and memset. */ + +#define TARGET_MEM_FUNCTIONS + +/* we use /lib/libp/lib* when profiling */ + +#undef LIB_SPEC +#define LIB_SPEC "%{p:-L/usr/lib/libp} %{pg:-L/usr/lib/libp} -lc" + + +/* Use crt1.o as a startup file and crtn.o as a closing file. */ +/* + * The loader directive file gcc.ifile defines how to merge the constructor + * sections into the data section. Also, since gas only puts out those + * sections in response to N_SETT stabs, and does not (yet) have a + * ".sections" directive, gcc.ifile also defines the list symbols + * __DTOR_LIST__ and __CTOR_LIST__. + * + * Finally, we must explicitly specify the file from libgcc.a that defines + * exit(), otherwise if the user specifies (for example) "-lc_s" on the + * command line, the wrong exit() will be used and global destructors will + * not get called . + */ + +#define STARTFILE_SPEC \ +"%{!r: gcc.ifile%s} %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} \ +%{!r:_exit.o%s}" + +#define ENDFILE_SPEC "crtn.o%s" + +/* cpp has to support a #sccs directive for the /usr/include files */ + +#define SCCS_DIRECTIVE + +/* LINK_SPEC is needed only for SunOS 4. */ + +#undef LINK_SPEC + +/* Although the gas we use can create .ctor and .dtor sections from N_SETT + stabs, it does not support section directives, so we need to have the loader + define the lists. + */ +#define CTOR_LISTS_DEFINED_EXTERNALLY + +/* similar to default, but allows for the table defined by ld with gcc.ifile. + nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0. + The old check is left in so that the same macro can be used if and when + a future version of gas does support section directives. */ + +#define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \ + if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \ + for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); \ + for (i = nptrs; i >= 1; i--) \ + __DTOR_LIST__[i] (); } + +/* + * Here is an example gcc.ifile. I've tested it on PBD sparc + * systems. The NEXT(0x200000) works on just about all 386 and m68k systems, + * but can be reduced to any power of 2 that is >= NBPS (0x40000 on a pbd). + + SECTIONS { + .text BIND(0x41000200) BLOCK (0x200) : + { *(.init) *(.text) vfork = fork; *(.fini) } + + GROUP BIND( NEXT(0x200000) + ADDR(.text) + SIZEOF(.text)): + { .data : { __CTOR_LIST__ = . ; . += 4; *(.ctor) . += 4 ; + __DTOR_LIST__ = . ; . += 4; *(.dtor) . += 4 ; } + .bss : { } + } + } + */ + +/* The prefix to add to user-visible assembler symbols. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +/* fixes: */ +/* + * Internal labels are prefixed with a period. + */ + +/* 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'. */ + +#undef ASM_GENERATE_INTERNAL_LABEL + +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.%s%d", PREFIX, NUM) + + +/* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM) + +/* This is how to output an element of a case-vector that is relative. */ + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL) + +/* This is how to output an element of a case-vector that is absolute. + (The 68000 does not use such vectors, + but we must define this macro anyway.) */ + +#undef ASM_OUTPUT_ADDR_VEC_ELT +#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 + versions either. */ +#undef ASM_OUTPUT_SOURCE_LINE(file, line) +#define ASM_OUTPUT_SOURCE_LINE(file, line) \ + { static int sym_lineno = 1; \ + fprintf (file, ".stabn 68,0,%d,.LM%d\n.LM%d:\n", \ + line, sym_lineno, sym_lineno); \ + sym_lineno += 1; } + +#define ASM_INT_OP ".long " diff --git a/contrib/gcc/config/sparc/rtems.h b/contrib/gcc/config/sparc/rtems.h new file mode 100644 index 0000000..1ab0a42 --- /dev/null +++ b/contrib/gcc/config/sparc/rtems.h @@ -0,0 +1,35 @@ +/* Definitions for rtems targeting a SPARC using a.out. + Copyright (C) 1996, 1997 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 "sparc/aout.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(sparc) -Amachine(sparc)" + +/* Generate calls to memcpy, memcmp and memset. */ +#ifndef TARGET_MEM_FUNCTIONS +#define TARGET_MEM_FUNCTIONS +#endif + +/* end of sparc/rtems.h */ diff --git a/contrib/gcc/config/sparc/sol2-c1.asm b/contrib/gcc/config/sparc/sol2-c1.asm new file mode 100644 index 0000000..618d698 --- /dev/null +++ b/contrib/gcc/config/sparc/sol2-c1.asm @@ -0,0 +1,86 @@ +! crt1.s for solaris 2.0. + +! Copyright (C) 1992 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! 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, 59 Temple Place - Suite 330, +! Boston, MA 02111-1307, USA. +! +! As a special exception, if you link this library with files +! compiled with GCC to produce an executable, this does not 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 file takes control of the process from the kernel, as specified +! in section 3 of the SVr4 ABI. +! This file is the first thing linked into any executable. + + .section ".text" + .proc 022 + .global _start + +_start: + mov 0, %fp ! Mark bottom frame pointer + ld [%sp + 64], %l0 ! argc + add %sp, 68, %l1 ! argv + + ! Leave some room for a call. Sun leaves 32 octets (to sit on + ! a cache line?) so we do too. + sub %sp, 32, %sp + + ! %g1 may contain a function to be registered w/atexit + orcc %g0, %g1, %g0 + be .nope + mov %g1, %o0 + call atexit + nop +.nope: + ! Now make sure constructors and destructors are handled. + set _fini, %o0 + call atexit, 1 + nop + call _init, 0 + nop + + ! We ignore the auxiliary vector; there's 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 + add %l1, %o2, %o2 ! env + set _environ, %o3 + st %o2, [%o3] ! *_environ + call main, 4 + nop + call exit, 0 + nop + call _exit, 0 + nop + ! We should never get here. + + .type _start,#function + .size _start,.-_start diff --git a/contrib/gcc/config/sparc/sol2-ci.asm b/contrib/gcc/config/sparc/sol2-ci.asm new file mode 100644 index 0000000..dd09a34 --- /dev/null +++ b/contrib/gcc/config/sparc/sol2-ci.asm @@ -0,0 +1,60 @@ +! crti.s for solaris 2.0. + +! Copyright (C) 1992 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! 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, 59 Temple Place - Suite 330, +! Boston, MA 02111-1307, USA. +! +! As a special exception, if you link this library with files +! compiled with GCC to produce an executable, this does not 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 file just make a stack frame for the contents of the .fini and +! .init sections. Users may put any desired instructions in those +! sections. + +! This file is linked in before the Values-Xx.o files and also before +! crtbegin, with which perhaps it should be merged. + + .file "crti.s" + + .section ".init" + .proc 022 + .global _init + .type _init,#function + .align 4 +_init: + save %sp, -96, %sp + + + .section ".fini" + .proc 022 + .global _fini + .type _fini,#function + .align 4 +_fini: + save %sp, -96, %sp diff --git a/contrib/gcc/config/sparc/sol2-cn.asm b/contrib/gcc/config/sparc/sol2-cn.asm new file mode 100644 index 0000000..3c5d508 --- /dev/null +++ b/contrib/gcc/config/sparc/sol2-cn.asm @@ -0,0 +1,54 @@ +! crtn.s for solaris 2.0. + +! Copyright (C) 1992 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! 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, 59 Temple Place - Suite 330, +! Boston, MA 02111-1307, USA. +! +! As a special exception, if you link this library with files +! compiled with GCC to produce an executable, this does not 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 file just makes sure that the .fini and .init sections do in +! fact return. Users may put any desired instructions in those sections. +! This file is the last thing linked into any executable. + + .file "crtn.s" + + .section ".init" + .align 4 + + ret + restore + + .section ".fini" + .align 4 + + ret + restore + +! Th-th-th-that's all folks! diff --git a/contrib/gcc/config/sparc/sol2-g1.asm b/contrib/gcc/config/sparc/sol2-g1.asm new file mode 100644 index 0000000..b9d8788 --- /dev/null +++ b/contrib/gcc/config/sparc/sol2-g1.asm @@ -0,0 +1,88 @@ +! gcrt1.s for solaris 2.0. + +! Copyright (C) 1992 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! 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, 59 Temple Place - Suite 330, +! Boston, MA 02111-1307, USA. +! +! As a special exception, if you link this library with files +! compiled with GCC to produce an executable, this does not 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 file takes control of the process from the kernel, as specified +! in section 3 of the SVr4 ABI. +! This file is the first thing linked into any executable. + + .section ".text" + .proc 022 + .global _start + +_start: + mov 0, %fp ! Mark bottom frame pointer + ld [%sp + 64], %l0 ! argc + add %sp, 68, %l1 ! argv + + ! Leave some room for a call. Sun leaves 32 octets (to sit on + ! a cache line?) so we do too. + sub %sp, 32, %sp + + ! %g1 may contain a function to be registered w/atexit + orcc %g0, %g1, %g0 + be .nope + mov %g1, %o0 + call atexit + nop +.nope: + ! Now make sure constructors and destructors are handled. + set _fini, %o0 + call atexit, 1 + nop + call _init, 0 + nop + + ! We ignore the auxiliary vector; there's no defined way to + ! access those data anyway. Instead, go straight to main: + mov %l0, %o0 ! argc + mov %l1, %o1 ! argv + set ___Argv, %o3 + st %o1, [%o3] ! *___Argv + ! Skip argc words past argv, to env: + sll %l0, 2, %o2 + add %o2, 4, %o2 + add %l1, %o2, %o2 ! env + set _environ, %o3 + st %o2, [%o3] ! *_environ + call main, 4 + nop + call exit, 0 + nop + call _exit, 0 + nop + ! We should never get here. + + .type _start,#function + .size _start,.-_start diff --git a/contrib/gcc/config/sparc/sol2-sld.h b/contrib/gcc/config/sparc/sol2-sld.h new file mode 100644 index 0000000..a824987 --- /dev/null +++ b/contrib/gcc/config/sparc/sol2-sld.h @@ -0,0 +1,11 @@ +/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2 + using the system linker. */ + +#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 diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h new file mode 100644 index 0000000..a0fa4a8 --- /dev/null +++ b/contrib/gcc/config/sparc/sol2.h @@ -0,0 +1,232 @@ +/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2 + Copyright 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Ron Guilmette (rfg@netcom.com). + Additional changes by David V. Henkel-Wallace (gumby@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. */ + +/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */ +#include "sparc/sysv4.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ +"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 \ +-Asystem(unix) -Asystem(svr4)" + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "\ +%{pthreads:-D_REENTRANT -D_PTHREADS} \ +%{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \ +%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \ +" + +/* 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) \ +" + +/* This is here rather than in sparc.h because it's not known what + other assemblers will accept. */ +#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 +#undef ASM_CPU_DEFAULT_SPEC +#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plus" +#endif +#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc +#undef ASM_CPU_DEFAULT_SPEC +#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusa" +#endif +#undef ASM_CPU_SPEC +#define ASM_CPU_SPEC "\ +%{mcpu=v8plus:-xarch=v8plus} \ +%{mcpu=ultrasparc:-xarch=v8plusa} \ +%{!mcpu*:%(asm_cpu_default)} \ +" + +/* However it appears that Solaris 2.0 uses the same reg numbering as + the old BSD-style system did. */ + +#undef DBX_REGISTER_NUMBER +/* Same as sparc.h */ +#define DBX_REGISTER_NUMBER(REGNO) \ + (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO) + +/* We use stabs-in-elf for debugging, because that is what the native + toolchain uses. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */ +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.skip %u\n", (SIZE)) + +/* Use .uahalf/.uaword so packed structure members don't generate + assembler errors when using the native assembler. */ +#undef ASM_SHORT +#define ASM_SHORT ".uahalf" +#undef ASM_LONG +#define ASM_LONG ".uaword" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* 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'. */ + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf ((LABEL), "*.L%s%ld", (PREFIX), (long)(NUM)) + + +/* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. + We don't use the standard LIB_SPEC only because we don't yet support c++ */ + +#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 \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}} \ + crtbegin.o%s" + +/* ??? Note: in order for -compat-bsd to work fully, + we must somehow arrange to fixincludes /usr/ucbinclude + and put the result in $(libsubdir)/ucbinclude. */ + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \ + %{!shared:\ + %{!symbolic:\ + %{pthreads:-lpthread} \ + %{!pthreads:%{threads:-lthread}} \ + -lc}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +/* This should be the same as in svr4.h, except with -R added. */ +#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} \ + %{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}}}} \ + %{Qy:} %{!Qn:-Qy}" + +/* This defines which switch letters take arguments. + It is as in svr4.h but with -R added. */ + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ + || (CHAR) == 'R' \ + || (CHAR) == 'h' \ + || (CHAR) == 'x' \ + || (CHAR) == 'z') + +/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h. + Instead, it is enabled here, because it does work under Solaris. */ +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. */ +#define LONG_DOUBLE_TYPE_SIZE 128 + +/* But indicate that it isn't supported by the hardware. */ +#define WIDEST_HARDWARE_FP_SIZE 64 + +#define STDC_0_IN_SYSTEM_HEADERS + +#define MULDI3_LIBCALL "__mul64" +#define DIVDI3_LIBCALL "__div64" +#define UDIVDI3_LIBCALL "__udiv64" +#define MODDI3_LIBCALL "__rem64" +#define UMODDI3_LIBCALL "__urem64" + +#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") + +/* No weird SPARC variants on Solaris */ +#undef TARGET_LIVE_G0 +#define TARGET_LIVE_G0 0 +#undef TARGET_BROKEN_SAVERESTORE +#define TARGET_BROKEN_SAVERESTORE 0 + +/* Solaris allows 64 bit out and global registers in 32 bit mode. + sparc_override_options will disable V8+ if not generating V9 code. */ +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_V8PLUS) + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); + diff --git a/contrib/gcc/config/sparc/sp64-aout.h b/contrib/gcc/config/sparc/sp64-aout.h new file mode 100644 index 0000000..e3056df --- /dev/null +++ b/contrib/gcc/config/sparc/sp64-aout.h @@ -0,0 +1,38 @@ +/* Definitions of target machine for GNU compiler, for SPARC64, a.out. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Doug Evans, dje@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. */ + +#include "sparc/sparc.h" +#include "aoutos.h" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc64-aout)") + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT \ + (MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \ + + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_STACK_BIAS) + +/* The only code model supported is Medium/Low. */ +#undef SPARC_DEFAULT_CMODEL +#define SPARC_DEFAULT_CMODEL CM_MEDLOW + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)" diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h new file mode 100644 index 0000000..2482866 --- /dev/null +++ b/contrib/gcc/config/sparc/sp64-elf.h @@ -0,0 +1,157 @@ +/* Definitions of target machine for GNU compiler, for SPARC64, ELF. + Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Doug Evans, dje@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. */ + +/* ??? We're taking the scheme of including another file and then overriding + the values we don't like a bit too far here. The alternative is to more or + less duplicate all of svr4.h, sparc/sysv4.h, and sparc/sol2.h here + (suitably cleaned up). */ + +#include "sparc/sol2.h" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc64-elf)") + +/* A 64 bit v9 compiler in a Medium/Anywhere code model environment. */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT \ +(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \ + + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_STACK_BIAS) + +#undef SPARC_DEFAULT_CMODEL +#define SPARC_DEFAULT_CMODEL CM_EMBMEDANY + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -D__ELF__ -Acpu(sparc) -Amachine(sparc)" + +/* __svr4__ is used by the C library (FIXME) */ +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "-D__svr4__" + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +#undef ASM_SPEC +#define ASM_SPEC "\ +%{v:-V} -s %{fpic:-K PIC} %{fPIC:-K PIC} \ +%{mlittle-endian:-EL} \ +%(asm_cpu) %(asm_arch) \ +" + +/* This is taken from sol2.h. */ +#undef LINK_SPEC +#define LINK_SPEC "\ +%{v:-V} \ +%{mlittle-endian:-EL} \ +" + +/* We need something a little simpler for the embedded environment. + Profiling doesn't really work yet so we just copy the default. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "\ +%{!shared:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}} \ +crtbegin.o%s \ +" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s" + +/* Use the default (for now). */ +#undef LIB_SPEC + +/* V9 chips can handle either endianness. */ +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ +{"big-endian", -MASK_LITTLE_ENDIAN}, \ +{"little-endian", MASK_LITTLE_ENDIAN}, + +#undef BYTES_BIG_ENDIAN +#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) + +#undef WORDS_BIG_ENDIAN +#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) + +/* ??? This should be 32 bits for v9 but what can we do? */ +#undef WCHAR_TYPE +#define WCHAR_TYPE "short unsigned int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 16 + +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 128 + +/* 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. */ +#undef JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION 1 + +/* System V Release 4 uses DWARF debugging info. + GDB doesn't support 64 bit stabs yet and the desired debug format is DWARF + anyway so it is the default. */ + +#define DWARF_DEBUGGING_INFO +#define DWARF2_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +/* Stabs doesn't use this, and it confuses a simulator. */ +/* ??? Need to see what DWARF needs, if anything. */ +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(FILE) + +/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler. + ??? If ints are 64 bits then UNALIGNED_INT_ASM_OP (defined elsewhere) is + misnamed. These should all refer to explicit sizes (half/word/xword?), + anything other than short/int/long/etc. */ + +#define UNALIGNED_LONGLONG_ASM_OP ".uaxword" + +/* DWARF stuff. */ + +#define ASM_OUTPUT_DWARF_ADDR(FILE, LABEL) \ +do { \ + fprintf ((FILE), "\t%s\t", UNALIGNED_LONGLONG_ASM_OP); \ + assemble_name ((FILE), (LABEL)); \ + fprintf ((FILE), "\n"); \ +} while (0) + +#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE, RTX) \ +do { \ + fprintf ((FILE), "\t%s\t", UNALIGNED_LONGLONG_ASM_OP); \ + output_addr_const ((FILE), (RTX)); \ + fputc ('\n', (FILE)); \ +} while (0) + +#define ASM_OUTPUT_DWARF2_ADDR_CONST(FILE, ADDR) \ + fprintf ((FILE), "\t%s\t%s", UNALIGNED_LONGLONG_ASM_OP, (ADDR)) + +/* ??? Not sure if this should be 4 or 8 bytes. 4 works for now. */ +#define ASM_OUTPUT_DWARF_REF(FILE, LABEL) \ +do { \ + fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \ + assemble_name ((FILE), (LABEL)); \ + fprintf ((FILE), "\n"); \ +} while (0) diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c new file mode 100644 index 0000000..e350729 --- /dev/null +++ b/contrib/gcc/config/sparc/sparc.c @@ -0,0 +1,6461 @@ +/* Subroutines for insn-output.c for Sun SPARC. + Copyright (C) 1987, 88, 89, 92-97, 1998 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. + +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 "tree.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "expr.h" +#include "recog.h" +#include "toplev.h" + +/* 1 if the caller has placed an "unimp" insn immediately after the call. + This is used in v8 code when calling a function that returns a structure. + v9 doesn't have this. Be careful to have this test be the same as that + used on the call. */ + +#define SKIP_CALLERS_UNIMP_P \ +(!TARGET_ARCH64 && current_function_returns_struct \ + && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))) \ + && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) \ + == INTEGER_CST)) + +/* Global variables for machine-dependent things. */ + +/* Size of frame. Need to know this to emit return insns from leaf procedures. + ACTUAL_FSIZE is set by compute_frame_size() which is called during the + reload pass. This is important as the value is later used in insn + scheduling (to see what can go in a delay slot). + APPARENT_FSIZE is the size of the stack less the register save area and less + the outgoing argument area. It is used when saving call preserved regs. */ +static int apparent_fsize; +static int actual_fsize; + +/* Save the operands last given to a compare for use when we + generate a scc or bcc insn. */ + +rtx sparc_compare_op0, sparc_compare_op1; + +/* We may need an epilogue if we spill too many registers. + If this is non-zero, then we branch here for the epilogue. */ +static rtx leaf_label; + +#ifdef LEAF_REGISTERS + +/* Vector to say how input registers are mapped to output + registers. FRAME_POINTER_REGNUM cannot be remapped by + this function to eliminate it. You must use -fomit-frame-pointer + to get that. */ +char leaf_reg_remap[] = +{ 0, 1, 2, 3, 4, 5, 6, 7, + -1, -1, -1, -1, -1, -1, 14, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 8, 9, 10, 11, 12, 13, -1, 15, + + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100}; + +#endif + +/* Name of where we pretend to think the frame pointer points. + Normally, this is "%fp", but if we are in a leaf procedure, + this is "%sp+something". We record "something" separately as it may be + too big for reg+constant addressing. */ + +static 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 *, + 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 function_arg_slotno PROTO((const CUMULATIVE_ARGS *, + enum machine_mode, tree, int, int, + int *, int *)); + +#ifdef DWARF2_DEBUGGING_INFO +extern char *dwarf2out_cfi_label (); +#endif + +/* Option handling. */ + +/* Code model option as passed by user. */ +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; + +/* Parsed values, as a power of two. */ +int sparc_align_loops; +int sparc_align_jumps; +int sparc_align_funcs; + +struct sparc_cpu_select sparc_select[] = +{ + /* switch name, tune arch */ + { (char *)0, "default", 1, 1 }, + { (char *)0, "-mcpu=", 1, 1 }, + { (char *)0, "-mtune=", 1, 0 }, + { 0, 0, 0, 0 } +}; + +/* CPU type. This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx. */ +enum processor_type sparc_cpu; + +/* Validate and override various options, and do some machine dependent + initialization. */ + +void +sparc_override_options () +{ + static struct code_model { + char *name; + int value; + } cmodels[] = { + { "32", CM_32 }, + { "medlow", CM_MEDLOW }, + { "medmid", CM_MEDMID }, + { "medany", CM_MEDANY }, + { "embmedany", CM_EMBMEDANY }, + { 0, 0 } + }; + struct code_model *cmodel; + /* Map TARGET_CPU_DEFAULT to value for -m{arch,tune}=. */ + static struct cpu_default { + int cpu; + 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_supersparc, "supersparc" }, + { TARGET_CPU_v9, "v9" }, + { TARGET_CPU_ultrasparc, "ultrasparc" }, + { 0, 0 } + }; + struct cpu_default *def; + /* Table of values for -m{cpu,tune}=. */ + static struct cpu_table { + char *name; + enum processor_type processor; + int disable; + int enable; + } cpu_table[] = { + { "v7", PROCESSOR_V7, MASK_ISA, 0 }, + { "cypress", PROCESSOR_CYPRESS, MASK_ISA, 0 }, + { "v8", PROCESSOR_V8, MASK_ISA, MASK_V8 }, + /* TI TMS390Z55 supersparc */ + { "supersparc", PROCESSOR_SUPERSPARC, MASK_ISA, MASK_V8 }, + { "sparclite", PROCESSOR_SPARCLITE, MASK_ISA, MASK_SPARCLITE }, + /* The Fujitsu MB86930 is the original sparclite chip, with no fpu. + 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 }, + { "sparclet", PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET }, + /* TEMIC sparclet */ + { "tsc701", PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET }, + { "v9", PROCESSOR_V9, MASK_ISA, MASK_V9 }, + /* TI ultrasparc */ + { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9 }, + { 0, 0, 0, 0 } + }; + 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) + { + error ("%s is not supported by this configuration", + DEFAULT_ARCH32_P ? "-m64" : "-m32"); + } +#endif + + /* Code model selection. */ + sparc_cmodel = SPARC_DEFAULT_CMODEL; + if (sparc_cmodel_string != NULL) + { + if (TARGET_ARCH64) + { + for (cmodel = &cmodels[0]; cmodel->name; cmodel++) + if (strcmp (sparc_cmodel_string, cmodel->name) == 0) + break; + if (cmodel->name == NULL) + error ("bad value (%s) for -mcmodel= switch", sparc_cmodel_string); + else + sparc_cmodel = cmodel->value; + } + else + error ("-mcmodel= is not supported on 32 bit systems"); + } + + fpu = TARGET_FPU; /* save current -mfpu status */ + + /* Set the default CPU. */ + for (def = &cpu_default[0]; def->name; ++def) + if (def->cpu == TARGET_CPU_DEFAULT) + break; + if (! def->name) + abort (); + sparc_select[0].string = def->name; + + for (sel = &sparc_select[0]; sel->name; ++sel) + { + if (sel->string) + { + for (cpu = &cpu_table[0]; cpu->name; ++cpu) + if (! strcmp (sel->string, cpu->name)) + { + if (sel->set_tune_p) + sparc_cpu = cpu->processor; + + if (sel->set_arch_p) + { + target_flags &= ~cpu->disable; + target_flags |= cpu->enable; + } + break; + } + + if (! cpu->name) + error ("bad value (%s) for %s switch", sel->string, sel->name); + } + } + + /* If -mfpu or -mno-fpu was explicitly used, don't override with + the processor default. */ + if (TARGET_FPU_SET) + target_flags = (target_flags & ~MASK_FPU) | fpu; + + /* Use the deprecated v8 insns for sparc64 in 32 bit mode. */ + if (TARGET_V9 && TARGET_ARCH32) + target_flags |= MASK_DEPRECATED_V8_INSNS; + + /* V8PLUS requires V9 */ + if (! TARGET_V9) + target_flags &= ~MASK_V8PLUS; + + /* Don't use stack biasing in 32 bit mode. */ + if (TARGET_ARCH32) + target_flags &= ~MASK_STACK_BIAS; + + /* Validate -malign-loops= value, or provide default. */ + if (sparc_align_loops_string) + { + sparc_align_loops = exact_log2 (atoi (sparc_align_loops_string)); + if (sparc_align_loops < 2 || sparc_align_loops > 7) + fatal ("-malign-loops=%s is not between 4 and 128 or is not a power of two", + sparc_align_loops_string); + } + else + { + /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if + its 0. This sounds a bit kludgey. */ + sparc_align_loops = 0; + } + + /* Validate -malign-jumps= value, or provide default. */ + if (sparc_align_jumps_string) + { + sparc_align_jumps = exact_log2 (atoi (sparc_align_jumps_string)); + if (sparc_align_jumps < 2 || sparc_align_loops > 7) + fatal ("-malign-jumps=%s is not between 4 and 128 or is not a power of two", + sparc_align_jumps_string); + } + else + { + /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if + its 0. This sounds a bit kludgey. */ + sparc_align_jumps = 0; + } + + /* Validate -malign-functions= value, or provide default. */ + if (sparc_align_funcs_string) + { + sparc_align_funcs = exact_log2 (atoi (sparc_align_funcs_string)); + if (sparc_align_funcs < 2 || sparc_align_loops > 7) + fatal ("-malign-functions=%s is not between 4 and 128 or is not a power of two", + sparc_align_funcs_string); + } + else + sparc_align_funcs = DEFAULT_SPARC_ALIGN_FUNCS; + + /* Validate PCC_STRUCT_RETURN. */ + if (flag_pcc_struct_return == DEFAULT_PCC_STRUCT_RETURN) + flag_pcc_struct_return = (TARGET_ARCH64 ? 0 : 1); + + /* Do various machine dependent initializations. */ + sparc_init_modes (); +} + +/* Miscellaneous utilities. */ + +/* Nonzero if CODE, a comparison, is suitable for use in v9 conditional move + or branch on register contents instructions. */ + +int +v9_regcmp_p (code) + enum rtx_code code; +{ + return (code == EQ || code == NE || code == GE || code == LT + || 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. */ + +/* Return non-zero only if OP is a register of mode MODE, + or const0_rtx. Don't allow const0_rtx if TARGET_LIVE_G0 because + %g0 may contain anything. */ + +int +reg_or_0_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (register_operand (op, mode)) + return 1; + if (TARGET_LIVE_G0) + return 0; + if (op == const0_rtx) + return 1; + if (GET_MODE (op) == VOIDmode && GET_CODE (op) == CONST_DOUBLE + && CONST_DOUBLE_HIGH (op) == 0 + && CONST_DOUBLE_LOW (op) == 0) + return 1; + if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT + && GET_CODE (op) == CONST_DOUBLE + && fp_zero_operand (op)) + return 1; + return 0; +} + +/* Nonzero if OP is a floating point value with value 0.0. */ + +int +fp_zero_operand (op) + rtx op; +{ + REAL_VALUE_TYPE r; + + REAL_VALUE_FROM_CONST_DOUBLE (r, op); + return (REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r)); +} + +/* Nonzero if OP is an integer register. */ + +int +intreg_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (register_operand (op, SImode) + || (TARGET_ARCH64 && register_operand (op, DImode))); +} + +/* Nonzero if OP is a floating point condition code register. */ + +int +fcc_reg_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + /* This can happen when recog is called from combine. Op may be a MEM. + Fail instead of calling abort in this case. */ + if (GET_CODE (op) != REG) + return 0; + + if (mode != VOIDmode && mode != GET_MODE (op)) + return 0; + if (mode == VOIDmode + && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode)) + return 0; + +#if 0 /* ??? ==> 1 when %fcc0-3 are pseudos first. See gen_compare_reg(). */ + if (reg_renumber == 0) + return REGNO (op) >= FIRST_PSEUDO_REGISTER; + return REGNO_OK_FOR_CCFP_P (REGNO (op)); +#else + return (unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG < 4; +#endif +} + +/* Nonzero if OP is an integer or floating point condition code register. */ + +int +icc_or_fcc_reg_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == REG && REGNO (op) == SPARC_ICC_REG) + { + if (mode != VOIDmode && mode != GET_MODE (op)) + return 0; + if (mode == VOIDmode + && GET_MODE (op) != CCmode && GET_MODE (op) != CCXmode) + return 0; + return 1; + } + + return fcc_reg_operand (op, mode); +} + +/* Nonzero if OP can appear as the dest of a RESTORE insn. */ +int +restore_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (GET_CODE (op) == REG && GET_MODE (op) == mode + && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32))); +} + +/* Call insn on SPARC can take a PC-relative constant address, or any regular + memory address. */ + +int +call_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM) + abort (); + op = XEXP (op, 0); + return (symbolic_operand (op, mode) || memory_address_p (Pmode, op)); +} + +int +call_operand_address (op, mode) + rtx op; + enum machine_mode mode; +{ + return (symbolic_operand (op, mode) || memory_address_p (Pmode, op)); +} + +/* Returns 1 if OP is either a symbol reference or a sum of a symbol + reference and a constant. */ + +int +symbolic_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + + case CONST: + op = XEXP (op, 0); + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + + /* ??? This clause seems to be irrelevant. */ + case CONST_DOUBLE: + return GET_MODE (op) == mode; + + default: + return 0; + } +} + +/* Return truth value of statement that OP is a symbolic memory + operand of mode MODE. */ + +int +symbolic_memory_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + if (GET_CODE (op) != MEM) + return 0; + op = XEXP (op, 0); + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST + || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); +} + +/* Return truth value of statement that OP is a LABEL_REF of mode MODE. */ + +int +label_ref_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != LABEL_REF) + return 0; + if (GET_MODE (op) != mode) + return 0; + return 1; +} + +/* Return 1 if the operand is an argument used in generating pic references + in either the medium/low or medium/anywhere code models of sparc64. */ + +int +sp64_medium_pic_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + /* Check for (const (minus (symbol_ref:GOT) + (const (minus (label) (pc))))). */ + if (GET_CODE (op) != CONST) + return 0; + op = XEXP (op, 0); + if (GET_CODE (op) != MINUS) + return 0; + if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF) + return 0; + /* ??? Ensure symbol is GOT. */ + if (GET_CODE (XEXP (op, 1)) != CONST) + return 0; + if (GET_CODE (XEXP (XEXP (op, 1), 0)) != MINUS) + return 0; + return 1; +} + +/* Return 1 if the operand is a data segment reference. This includes + the readonly data segment, or in other words anything but the text segment. + This is needed in the medium/anywhere code model on v9. These values + are accessed with EMBMEDANY_BASE_REG. */ + +int +data_segment_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF : + return ! SYMBOL_REF_FLAG (op); + case PLUS : + /* Assume canonical format of symbol + constant. + Fall through. */ + case CONST : + return data_segment_operand (XEXP (op, 0)); + default : + return 0; + } +} + +/* Return 1 if the operand is a text segment reference. + This is needed in the medium/anywhere code model on v9. */ + +int +text_segment_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + switch (GET_CODE (op)) + { + case LABEL_REF : + return 1; + case SYMBOL_REF : + return SYMBOL_REF_FLAG (op); + case PLUS : + /* Assume canonical format of symbol + constant. + Fall through. */ + case CONST : + return text_segment_operand (XEXP (op, 0)); + default : + return 0; + } +} + +/* Return 1 if the operand is either a register or a memory operand that is + not symbolic. */ + +int +reg_or_nonsymb_mem_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + if (register_operand (op, mode)) + return 1; + + if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode)) + return 1; + + return 0; +} + +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; +{ + if (GET_CODE (op) != MEM) + return 0; + if (! symbolic_operand (XEXP (op, 0), Pmode)) + return 0; + return 1; +} + +int +splittable_immediate_memory_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + if (GET_CODE (op) != MEM) + return 0; + if (! immediate_operand (XEXP (op, 0), Pmode)) + return 0; + return 1; +} + +/* Return truth value of whether OP is EQ or NE. */ + +int +eq_or_neq (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (op) == EQ || GET_CODE (op) == NE); +} + +/* Return 1 if this is a comparison operator, but not an EQ, NE, GEU, + or LTU for non-floating-point. We handle those specially. */ + +int +normal_comp_operator (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != '<') + return 0; + + if (GET_MODE (XEXP (op, 0)) == CCFPmode + || GET_MODE (XEXP (op, 0)) == CCFPEmode) + return 1; + + return (code != NE && code != EQ && code != GEU && code != LTU); +} + +/* Return 1 if this is a comparison operator. This allows the use of + MATCH_OPERATOR to recognize all the branch insns. */ + +int +noov_compare_op (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != '<') + return 0; + + if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode) + /* These are the only branches which work with CC_NOOVmode. */ + return (code == EQ || code == NE || code == GE || code == LT); + return 1; +} + +/* Nonzero if OP is a comparison operator suitable for use in v9 + conditional move or branch on register contents instructions. */ + +int +v9_regcmp_op (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != '<') + return 0; + + 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 +extend_op (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND; +} + +/* Return nonzero if OP is an operator of mode MODE which can set + the condition codes explicitly. We do not include PLUS and MINUS + because these require CC_NOOVmode, which we handle explicitly. */ + +int +cc_arithop (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + if (GET_CODE (op) == AND + || GET_CODE (op) == IOR + || GET_CODE (op) == XOR) + return 1; + + return 0; +} + +/* Return nonzero if OP is an operator of mode MODE which can bitwise + complement its second operand and set the condition codes explicitly. */ + +int +cc_arithopn (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + /* XOR is not here because combine canonicalizes (xor (not ...) ...) + and (xor ... (not ...)) to (not (xor ...)). */ + return (GET_CODE (op) == AND + || GET_CODE (op) == IOR); +} + +/* Return true if OP is a register, or is a CONST_INT that can fit in a + signed 13 bit immediate field. This is an acceptable SImode operand for + most 3 address instructions. */ + +int +arith_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + int val; + if (register_operand (op, mode) + || GET_CODE (op) == CONSTANT_P_RTX) + return 1; + if (GET_CODE (op) != CONST_INT) + return 0; + val = INTVAL (op) & 0xffffffff; + return SPARC_SIMM13_P (val); +} + +/* 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. */ + +int +arith11_operand (op, mode) + rtx op; + 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)))); +} + +/* Return true if OP is a register, or is a CONST_INT that can fit in a + signed 10 bit immediate field. This is an acceptable SImode operand for + the movrcc instructions. */ + +int +arith10_operand (op, mode) + rtx op; + 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)))); +} + +/* Return true if OP is a register, is a CONST_INT that fits in a 13 bit + immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit + immediate field. + v9: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that + can fit in a 13 bit immediate field. This is an acceptable DImode operand + for most 3 address instructions. */ + +int +arith_double_operand (op, mode) + rtx op; + 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 + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000) + || (TARGET_ARCH64 + && GET_CODE (op) == CONST_DOUBLE + && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 + && ((CONST_DOUBLE_HIGH (op) == -1 + && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000) + || (CONST_DOUBLE_HIGH (op) == 0 + && (CONST_DOUBLE_LOW (op) & 0x1000) == 0)))); +} + +/* 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. */ +/* ??? Replace with arith11_operand? */ + +int +arith11_double_operand (op, mode) + rtx op; + 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 + && ((CONST_DOUBLE_HIGH (op) == -1 + && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400) + || (CONST_DOUBLE_HIGH (op) == 0 + && (CONST_DOUBLE_LOW (op) & 0x400) == 0))) + || (GET_CODE (op) == CONST_INT + && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) + && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800)); +} + +/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that + can fit in an 10 bit immediate field. This is an acceptable DImode + operand for the movrcc instructions. */ +/* ??? Replace with arith10_operand? */ + +int +arith10_double_operand (op, mode) + rtx op; + 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 + && ((CONST_DOUBLE_HIGH (op) == -1 + && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200) + || (CONST_DOUBLE_HIGH (op) == 0 + && (CONST_DOUBLE_LOW (op) & 0x200) == 0))) + || (GET_CODE (op) == CONST_INT + && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) + && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400)); +} + +/* Return truth value of whether OP is a integer which fits the + range constraining immediate operands in most three-address insns, + which have a 13 bit immediate field. */ + +int +small_int (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); +} + +/* Recognize operand values for the umul instruction. That instruction sign + extends immediate values just like all other sparc instructions, but + interprets the extended result as an unsigned number. */ + +int +uns_small_int (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ +#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); +#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); +#endif +} + +int +uns_arith_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return register_operand (op, mode) || uns_small_int (op, mode); +} + +/* Return truth value of statement that OP is a call-clobbered register. */ +int +clobbered_register (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]); +} + +/* 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. */ + +rtx +gen_compare_reg (code, x, y) + enum rtx_code code; + rtx x, y; +{ + enum machine_mode mode = SELECT_CC_MODE (code, x, y); + rtx cc_reg; + + /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the + fcc regs (cse can't tell they're really call clobbered regs and will + remove a duplicate comparison even if there is an intervening function + call - it will then try to reload the cc reg via an int reg which is why + we need the movcc patterns). It is possible to provide the movcc + patterns by using the ldxfsr/stxfsr v9 insns. I tried it: you need two + registers (say %g1,%g5) and it takes about 6 insns. A better fix would be + to tell cse that CCFPE mode registers (even pseudos) are call + clobbered. */ + + /* ??? This is an experiment. Rather than making changes to cse which may + or may not be easy/clean, we do our own cse. This is possible because + we will generate hard registers. Cse knows they're call clobbered (it + doesn't know the same thing about pseudos). If we guess wrong, no big + deal, but if we win, great! */ + + if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) +#if 1 /* experiment */ + { + int reg; + /* We cycle through the registers to ensure they're all exercised. */ + static int next_fcc_reg = 0; + /* Previous x,y for each fcc reg. */ + static rtx prev_args[4][2]; + + /* Scan prev_args for x,y. */ + for (reg = 0; reg < 4; reg++) + if (prev_args[reg][0] == x && prev_args[reg][1] == y) + break; + if (reg == 4) + { + reg = next_fcc_reg; + prev_args[reg][0] = x; + prev_args[reg][1] = y; + next_fcc_reg = (next_fcc_reg + 1) & 3; + } + cc_reg = gen_rtx_REG (mode, reg + SPARC_FIRST_V9_FCC_REG); + } +#else + cc_reg = gen_reg_rtx (mode); +#endif /* ! experiment */ + else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) + cc_reg = gen_rtx_REG (mode, SPARC_FCC_REG); + 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, + gen_rtx_COMPARE (mode, x, y))); + } + + return cc_reg; +} + +/* This function is used for v9 only. + CODE is the code for an Scc's comparison. + OPERANDS[0] is the target of the Scc insn. + OPERANDS[1] is the value we compare against const0_rtx (which hasn't + been generated yet). + + This function is needed to turn + + (set (reg:SI 110) + (gt (reg:CCX 100 %icc) + (const_int 0))) + into + (set (reg:SI 110) + (gt:DI (reg:CCX 100 %icc) + (const_int 0))) + + IE: The instruction recognizer needs to see the mode of the comparison to + find the right instruction. We could use "gt:DI" right in the + define_expand, but leaving it out allows us to handle DI, SI, etc. + + We refer to the global sparc compare operands sparc_compare_op0 and + sparc_compare_op1. */ + +int +gen_v9_scc (compare_code, operands) + enum rtx_code compare_code; + register rtx *operands; +{ + rtx temp, op0, op1; + + if (! TARGET_ARCH64 + && (GET_MODE (sparc_compare_op0) == DImode + || GET_MODE (operands[0]) == DImode)) + return 0; + + /* Handle the case where operands[0] == sparc_compare_op0. + We "early clobber" the result. */ + if (REGNO (operands[0]) == REGNO (sparc_compare_op0)) + { + op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0)); + emit_move_insn (op0, sparc_compare_op0); + } + else + op0 = sparc_compare_op0; + /* For consistency in the following. */ + op1 = sparc_compare_op1; + + /* Try to use the movrCC insns. */ + if (TARGET_ARCH64 + && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT + && op1 == const0_rtx + && v9_regcmp_p (compare_code)) + { + /* Special case for op0 != 0. This can be done with one instruction if + operands[0] == sparc_compare_op0. We don't assume they are equal + now though. */ + + if (compare_code == NE + && GET_MODE (operands[0]) == DImode + && GET_MODE (op0) == DImode) + { + emit_insn (gen_rtx_SET (VOIDmode, operands[0], op0)); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (DImode, + gen_rtx_fmt_ee (compare_code, DImode, + op0, const0_rtx), + const1_rtx, + operands[0]))); + return 1; + } + + emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx)); + if (GET_MODE (op0) != DImode) + { + temp = gen_reg_rtx (DImode); + convert_move (temp, op0, 0); + } + else + temp = op0; + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + gen_rtx_fmt_ee (compare_code, DImode, + temp, const0_rtx), + const1_rtx, + operands[0]))); + return 1; + } + else + { + operands[1] = gen_compare_reg (compare_code, op0, op1); + + switch (GET_MODE (operands[1])) + { + case CCmode : + case CCXmode : + case CCFPEmode : + case CCFPmode : + break; + default : + abort (); + } + emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx)); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + gen_rtx_fmt_ee (compare_code, + GET_MODE (operands[1]), + operands[1], const0_rtx), + const1_rtx, operands[0]))); + return 1; + } +} + +/* Emit a conditional jump insn for the v9 architecture using comparison code + CODE and jump target LABEL. + This function exists to take advantage of the v9 brxx insns. */ + +void +emit_v9_brxx_insn (code, op0, label) + enum rtx_code code; + rtx op0, label; +{ + emit_jump_insn (gen_rtx_SET (VOIDmode, + pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_fmt_ee (code, GET_MODE (op0), + op0, const0_rtx), + gen_rtx_LABEL_REF (VOIDmode, label), + pc_rtx))); +} + +/* Return nonzero if a return peephole merging return with + setting of output register is ok. */ +int +leaf_return_peephole_ok () +{ + return (actual_fsize == 0); +} + +/* Return nonzero if TRIAL can go into the function epilogue's + delay slot. SLOT is the slot we are trying to fill. */ + +int +eligible_for_epilogue_delay (trial, slot) + rtx trial; + int slot; +{ + rtx pat, src; + + if (slot >= 1) + return 0; + + if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET) + return 0; + + if (get_attr_length (trial) != 1) + return 0; + + /* If %g0 is live, there are lots of things we can't handle. + Rather than trying to find them all now, let's punt and only + optimize things as necessary. */ + if (TARGET_LIVE_G0) + return 0; + + /* 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 (leaf_return_peephole_ok ()) + return ((get_attr_in_uncond_branch_delay (trial) + == IN_BRANCH_DELAY_TRUE)); + return 0; + } + + /* If only trivial `restore' insns work, nothing can go in the + delay slot. */ + else if (TARGET_BROKEN_SAVERESTORE) + return 0; + + pat = PATTERN (trial); + + /* Otherwise, only operations which can be done in tandem with + a `restore' insn can go into the delay slot. */ + if (GET_CODE (SET_DEST (pat)) != REG + || REGNO (SET_DEST (pat)) >= 32 + || REGNO (SET_DEST (pat)) < 24) + return 0; + + /* The set of insns matched here must agree precisely with the set of + patterns paired with a RETURN in sparc.md. */ + + src = SET_SRC (pat); + + /* This matches "*return_[qhs]i". */ + if (arith_operand (src, GET_MODE (src))) + return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode); + + /* This matches "*return_di". */ + else if (arith_double_operand (src, GET_MODE (src))) + return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode); + + /* This matches "*return_sf_no_fpu". */ + else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode) + && register_operand (src, SFmode)) + return 1; + + /* This matches "*return_addsi". */ + else if (GET_CODE (src) == PLUS + && arith_operand (XEXP (src, 0), SImode) + && arith_operand (XEXP (src, 1), SImode) + && (register_operand (XEXP (src, 0), SImode) + || register_operand (XEXP (src, 1), SImode))) + return 1; + + /* This matches "*return_adddi". */ + else if (GET_CODE (src) == PLUS + && arith_double_operand (XEXP (src, 0), DImode) + && arith_double_operand (XEXP (src, 1), DImode) + && (register_operand (XEXP (src, 0), DImode) + || register_operand (XEXP (src, 1), DImode))) + return 1; + + return 0; +} + +static int +check_return_regs (x) + rtx x; +{ + switch (GET_CODE (x)) + { + case REG: + return IN_OR_GLOBAL_P (x); + + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case LABEL_REF: + return 1; + + case SET: + case IOR: + case AND: + case XOR: + case PLUS: + case MINUS: + if (check_return_regs (XEXP (x, 1)) == 0) + return 0; + case NOT: + case NEG: + case MEM: + return check_return_regs (XEXP (x, 0)); + + default: + return 0; + } + +} + +/* Return 1 if TRIAL references only in and global registers. */ +int +eligible_for_return_delay (trial) + rtx trial; +{ + if (GET_CODE (PATTERN (trial)) != SET) + return 0; + + return check_return_regs (PATTERN (trial)); +} + +int +short_branch (uid1, uid2) + int uid1, uid2; +{ + unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2]; + if (delta + 1024 < 2048) + return 1; + /* warning ("long branch, distance %d", delta); */ + return 0; +} + +/* Return non-zero if REG is not used after INSN. + We assume REG is a reload reg, and therefore does + not live past labels or calls or jumps. */ +int +reg_unused_after (reg, insn) + rtx reg; + rtx insn; +{ + enum rtx_code code, prev_code = UNKNOWN; + + while ((insn = NEXT_INSN (insn))) + { + if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)]) + return 1; + + code = GET_CODE (insn); + if (GET_CODE (insn) == CODE_LABEL) + return 1; + + if (GET_RTX_CLASS (code) == 'i') + { + rtx set = single_set (insn); + int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set)); + if (set && in_src) + return 0; + if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) + return 1; + if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn))) + return 0; + } + prev_code = code; + } + return 1; +} + +/* The table we use to reference PIC data. */ +static rtx global_offset_table; + +/* The function we use to get at it. */ +static rtx get_pc_symbol; +static char get_pc_symbol_name[256]; + +/* Ensure that we are not using patterns that are not OK with PIC. */ + +int +check_pic (i) + int i; +{ + switch (flag_pic) + { + case 1: + if (GET_CODE (recog_operand[i]) == SYMBOL_REF + || (GET_CODE (recog_operand[i]) == CONST + && ! (GET_CODE (XEXP (recog_operand[i], 0)) == MINUS + && (XEXP (XEXP (recog_operand[i], 0), 0) + == global_offset_table) + && (GET_CODE (XEXP (XEXP (recog_operand[i], 0), 1)) + == CONST)))) + abort (); + case 2: + default: + return 1; + } +} + +/* Return true if X is an address which needs a temporary register when + reloaded while generating PIC code. */ + +int +pic_address_needs_scratch (x) + rtx x; +{ + /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */ + 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 + && ! SMALL_INT (XEXP (XEXP (x, 0), 1))) + return 1; + + return 0; +} + +/* Legitimize PIC addresses. If the address is already position-independent, + we return ORIG. Newly generated position-independent addresses go into a + reg. This is REG if non zero, otherwise we allocate register(s) as + necessary. */ + +rtx +legitimize_pic_address (orig, mode, reg) + rtx orig; + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx reg; +{ + if (GET_CODE (orig) == SYMBOL_REF + || GET_CODE (orig) == LABEL_REF) + { + rtx pic_ref, address; + rtx insn; + + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + } + + if (flag_pic == 2) + { + /* If not during reload, allocate another temp reg here for loading + in the address, so that these instructions can be optimized + properly. */ + rtx temp_reg = ((reload_in_progress || reload_completed) + ? reg : gen_reg_rtx (Pmode)); + + /* Must put the SYMBOL_REF inside an UNSPEC here so that cse + 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)); + + address = temp_reg; + } + else + address = orig; + + pic_ref = gen_rtx_MEM (Pmode, + gen_rtx_PLUS (Pmode, + pic_offset_table_rtx, address)); + current_function_uses_pic_offset_table = 1; + RTX_UNCHANGING_P (pic_ref) = 1; + insn = emit_move_insn (reg, pic_ref); + /* Put a REG_EQUAL note on this insn, so that it can be optimized + by loop. */ + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, + REG_NOTES (insn)); + return reg; + } + else if (GET_CODE (orig) == CONST) + { + rtx base, offset; + + if (GET_CODE (XEXP (orig, 0)) == PLUS + && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) + return orig; + + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + } + + if (GET_CODE (XEXP (orig, 0)) == PLUS) + { + base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); + offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, + base == reg ? 0 : reg); + } + else + abort (); + + if (GET_CODE (offset) == CONST_INT) + { + if (SMALL_INT (offset)) + return plus_constant_for_output (base, INTVAL (offset)); + else if (! reload_in_progress && ! reload_completed) + offset = force_reg (Pmode, offset); + else + /* If we reach here, then something is seriously wrong. */ + abort (); + } + return gen_rtx_PLUS (Pmode, base, offset); + } + + 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 +pic_setup_code () +{ + rtx seq; + + start_sequence (); + emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table, + get_pc_symbol)); + seq = gen_sequence (); + end_sequence (); + + return seq; +} + +/* Emit special PIC prologues and epilogues. */ + +void +finalize_pic () +{ + /* Labels to get the PC in the prologue of this function. */ + int orig_flag_pic = flag_pic; + rtx insn; + + if (current_function_uses_pic_offset_table == 0) + return; + + if (! flag_pic) + abort (); + + /* 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); + + text_section (); + ASM_OUTPUT_ALIGN (asm_out_file, 3); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0); + fputs ("\tretl\n\tadd %o7,%l7,%l7\n", asm_out_file); + } + + /* Initialize every time through, since we can't easily + know this to be permanent. */ + global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); + get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name); + flag_pic = 0; + + emit_insn_after (pic_setup_code (), get_insns ()); + + /* Insert the code in each nonlocal goto receiver. */ + 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) + emit_insn_after (pic_setup_code (), insn); + + flag_pic = orig_flag_pic; + + /* Need to emit this whether or not we obey regdecls, + since setjmp/longjmp can cause life info to screw up. + ??? In the case where we don't obey regdecls, this is not sufficient + since we may not fall out the bottom. */ + 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. */ + +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; +{ + 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; + + if (GET_CODE (mem) != MEM) + return 0; /* It's gotta be a MEM! */ + + 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; + if (GET_CODE (addr) == PLUS) + { + if (GET_CODE (XEXP (addr, 0)) == REG + && GET_CODE (XEXP (addr, 1)) == CONST_INT) + { + base = XEXP (addr, 0); + offset = XEXP (addr, 1); + } + } + else if (GET_CODE (addr) == REG) + { + base = addr; + 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) + { + 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); + + 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) + { + wordpart[1][1] = adj_offsettable_operand (op1, 4); + wordpart[2][1] = adj_offsettable_operand (op1, 8); + wordpart[3][1] = adj_offsettable_operand (op1, 12); + } + 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); + } + } + } + else /* TARGET_ARCH64 */ + { + 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); + } + } + + 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 (); +} + +/* 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 + are more than 32 modes now. Instead we use two tables: one indexed by + hard register number, and one indexed by mode. */ + +/* The purpose of sparc_mode_class is to shrink the range of modes so that + they all fit (as bit numbers) in a 32 bit word (again). Each real mode is + mapped into one sparc_mode_class mode. */ + +enum sparc_mode_class { + S_MODE, D_MODE, T_MODE, O_MODE, + SF_MODE, DF_MODE, TF_MODE, OF_MODE, + CC_MODE, CCFP_MODE +}; + +/* Modes for single-word and smaller quantities. */ +#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE)) + +/* Modes for double-word and smaller quantities. */ +#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE)) + +/* Modes for quad-word and smaller quantities. */ +#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE)) + +/* Modes for single-float quantities. We must allow any single word or + smaller quantity. This is because the fix/float conversion instructions + take integer inputs/outputs from the float registers. */ +#define SF_MODES (S_MODES) + +/* Modes for double-float and smaller quantities. */ +#define DF_MODES (S_MODES | D_MODES) + +#define DF_MODES64 DF_MODES + +/* Modes for double-float only quantities. */ +#define DF_ONLY_MODES ((1 << (int) DF_MODE) | (1 << (int) D_MODE)) + +/* Modes for double-float and larger quantities. */ +#define DF_UP_MODES (DF_ONLY_MODES | TF_ONLY_MODES) + +/* Modes for quad-float only quantities. */ +#define TF_ONLY_MODES (1 << (int) TF_MODE) + +/* Modes for quad-float and smaller quantities. */ +#define TF_MODES (DF_MODES | TF_ONLY_MODES) + +#define TF_MODES64 (DF_MODES64 | TF_ONLY_MODES) + +/* Modes for condition codes. */ +#define CC_MODES (1 << (int) CC_MODE) +#define CCFP_MODES (1 << (int) CCFP_MODE) + +/* Value is 1 if register/mode pair is acceptable on sparc. + The funny mixture of D and T modes is because integer operations + do not specially operate on tetra quantities, so non-quad-aligned + registers can hold quadword quantities (except %o4 and %i4 because + they cross fixed registers). */ + +/* This points to either the 32 bit or the 64 bit version. */ +int *hard_regno_mode_classes; + +static int hard_32bit_mode_classes[] = { + S_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, + T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES, + T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, + T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES, + + TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, + TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, + TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, + TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, + + /* FP regs f32 to f63. Only the even numbered registers actually exist, + and none can hold SFmode/SImode values. */ + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + + /* %fcc[0123] */ + CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES, + + /* %icc */ + CC_MODES +}; + +static int hard_64bit_mode_classes[] = { + D_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, + T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, + T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, + T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, + + TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, + TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, + TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, + TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, + + /* FP regs f32 to f63. Only the even numbered registers actually exist, + and none can hold SFmode/SImode values. */ + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, + + /* %fcc[0123] */ + CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES, + + /* %icc */ + CC_MODES +}; + +int sparc_mode_class [NUM_MACHINE_MODES]; + +enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER]; + +static void +sparc_init_modes () +{ + int i; + + for (i = 0; i < NUM_MACHINE_MODES; i++) + { + switch (GET_MODE_CLASS (i)) + { + case MODE_INT: + case MODE_PARTIAL_INT: + case MODE_COMPLEX_INT: + if (GET_MODE_SIZE (i) <= 4) + sparc_mode_class[i] = 1 << (int) S_MODE; + else if (GET_MODE_SIZE (i) == 8) + sparc_mode_class[i] = 1 << (int) D_MODE; + else if (GET_MODE_SIZE (i) == 16) + sparc_mode_class[i] = 1 << (int) T_MODE; + else if (GET_MODE_SIZE (i) == 32) + sparc_mode_class[i] = 1 << (int) O_MODE; + else + sparc_mode_class[i] = 0; + break; + case MODE_FLOAT: + case MODE_COMPLEX_FLOAT: + if (GET_MODE_SIZE (i) <= 4) + sparc_mode_class[i] = 1 << (int) SF_MODE; + else if (GET_MODE_SIZE (i) == 8) + sparc_mode_class[i] = 1 << (int) DF_MODE; + else if (GET_MODE_SIZE (i) == 16) + sparc_mode_class[i] = 1 << (int) TF_MODE; + else if (GET_MODE_SIZE (i) == 32) + sparc_mode_class[i] = 1 << (int) OF_MODE; + else + sparc_mode_class[i] = 0; + break; + case MODE_CC: + default: + /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so + we must explicitly check for them here. */ + if (i == (int) CCFPmode || i == (int) CCFPEmode) + sparc_mode_class[i] = 1 << (int) CCFP_MODE; + else if (i == (int) CCmode || i == (int) CC_NOOVmode + || i == (int) CCXmode || i == (int) CCX_NOOVmode) + sparc_mode_class[i] = 1 << (int) CC_MODE; + else + sparc_mode_class[i] = 0; + break; + } + } + + if (TARGET_ARCH64) + hard_regno_mode_classes = hard_64bit_mode_classes; + else + hard_regno_mode_classes = hard_32bit_mode_classes; + + /* Initialize the array used by REGNO_REG_CLASS. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (i < 16 && TARGET_V8PLUS) + sparc_regno_reg_class[i] = I64_REGS; + else if (i < 32) + sparc_regno_reg_class[i] = GENERAL_REGS; + else if (i < 64) + sparc_regno_reg_class[i] = FP_REGS; + else if (i < 96) + sparc_regno_reg_class[i] = EXTRA_FP_REGS; + else if (i < 100) + sparc_regno_reg_class[i] = FPCC_REGS; + else + sparc_regno_reg_class[i] = NO_REGS; + } +} + +/* Save non call used registers from LOW to HIGH at BASE+OFFSET. + N_REGS is the number of 4-byte regs saved thus far. This applies even to + v9 int regs as it simplifies the code. */ + +static int +save_regs (file, low, high, base, offset, n_regs, real_offset) + FILE *file; + int low, high; + char *base; + int offset; + int n_regs; + int real_offset; +{ + int i; + + if (TARGET_ARCH64 && high <= 32) + { + for (i = low; i < high; i++) + { + if (regs_ever_live[i] && ! call_used_regs[i]) + { + fprintf (file, "\tstx %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); + n_regs += 2; + } + } + } + else + { + for (i = low; i < high; i += 2) + { + if (regs_ever_live[i] && ! call_used_regs[i]) + { + if (regs_ever_live[i+1] && ! call_used_regs[i+1]) + { + fprintf (file, "\tstd %s,[%s+%d]\n", + reg_names[i], base, offset + 4 * n_regs); + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + dwarf2out_reg_save (l, i, real_offset + 4 * n_regs); + dwarf2out_reg_save (l, i+1, real_offset + 4 * n_regs + 4); + } + n_regs += 2; + } + else + { + fprintf (file, "\tst %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); + n_regs += 2; + } + } + else + { + if (regs_ever_live[i+1] && ! call_used_regs[i+1]) + { + fprintf (file, "\tst %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); + n_regs += 2; + } + } + } + } + return n_regs; +} + +/* Restore non call used registers from LOW to HIGH at BASE+OFFSET. + + N_REGS is the number of 4-byte regs saved thus far. This applies even to + v9 int regs as it simplifies the code. */ + +static int +restore_regs (file, low, high, base, offset, n_regs) + FILE *file; + int low, high; + char *base; + int offset; + int n_regs; +{ + int i; + + if (TARGET_ARCH64 && high <= 32) + { + for (i = low; i < high; i++) + { + if (regs_ever_live[i] && ! call_used_regs[i]) + fprintf (file, "\tldx [%s+%d], %s\n", + base, offset + 4 * n_regs, reg_names[i]), + n_regs += 2; + } + } + else + { + for (i = low; i < high; i += 2) + { + 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", + base, offset + 4 * n_regs, reg_names[i]), + n_regs += 2; + else + fprintf (file, "\tld [%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", + base, offset + 4 * n_regs + 4, reg_names[i+1]), + n_regs += 2; + } + } + return n_regs; +} + +/* Static variables we want to share between prologue and epilogue. */ + +/* Number of live general or floating point registers needed to be saved + (as 4-byte quantities). This is only done if TARGET_EPILOGUE. */ +static int num_gfregs; + +/* Compute the frame size required by the function. This function is called + during the reload pass and also by output_function_prologue(). */ + +int +compute_frame_size (size, leaf_function) + int size; + int leaf_function; +{ + int n_regs = 0, i; + int outgoing_args_size = (current_function_outgoing_args_size + + REG_PARM_STACK_SPACE (current_function_decl)); + + if (TARGET_EPILOGUE) + { + /* N_REGS is the number of 4-byte regs saved thus far. This applies + even to v9 int regs to be consistent with save_regs/restore_regs. */ + + if (TARGET_ARCH64) + { + for (i = 0; i < 8; i++) + if (regs_ever_live[i] && ! call_used_regs[i]) + n_regs += 2; + } + else + { + for (i = 0; i < 8; i += 2) + if ((regs_ever_live[i] && ! call_used_regs[i]) + || (regs_ever_live[i+1] && ! call_used_regs[i+1])) + n_regs += 2; + } + + for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2) + if ((regs_ever_live[i] && ! call_used_regs[i]) + || (regs_ever_live[i+1] && ! call_used_regs[i+1])) + n_regs += 2; + } + + /* Set up values for use in `function_epilogue'. */ + num_gfregs = n_regs; + + if (leaf_function && n_regs == 0 + && size == 0 && current_function_outgoing_args_size == 0) + { + actual_fsize = apparent_fsize = 0; + } + else + { + /* We subtract STARTING_FRAME_OFFSET, remember it's negative. + The stack bias (if any) is taken out to undo its effects. */ + apparent_fsize = (size - STARTING_FRAME_OFFSET + SPARC_STACK_BIAS + 7) & -8; + apparent_fsize += n_regs * 4; + actual_fsize = apparent_fsize + ((outgoing_args_size + 7) & -8); + } + + /* Make sure nothing can clobber our register windows. + If a SAVE must be done, or there is a stack-local variable, + the register window area must be allocated. + ??? For v8 we apparently need an additional 8 bytes of reserved space. */ + if (leaf_function == 0 || size > 0) + actual_fsize += (16 * UNITS_PER_WORD) + (TARGET_ARCH64 ? 0 : 8); + + return SPARC_STACK_ALIGN (actual_fsize); +} + +/* Build a (32 bit) big number in a register. */ +/* ??? We may be able to use the set macro here too. */ + +static void +build_big_number (file, num, reg) + FILE *file; + int num; + char *reg; +{ + if (num >= 0 || ! TARGET_ARCH64) + { + fprintf (file, "\tsethi %%hi(%d),%s\n", num, reg); + if ((num & 0x3ff) != 0) + fprintf (file, "\tor %s,%%lo(%d),%s\n", reg, num, reg); + } + else /* num < 0 && TARGET_ARCH64 */ + { + /* 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 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. */ + int asize = num; + int inv = ~asize; + int low = -0x400 + (asize & 0x3FF); + + fprintf (file, "\tsethi %%hi(%d),%s\n\txor %s,%d,%s\n", + inv, reg, reg, low, reg); + } +} + +/* Output code for the function prologue. */ + +void +output_function_prologue (file, size, leaf_function) + FILE *file; + int size; + int leaf_function; +{ + /* Need to use actual_fsize, since we are also allocating + space for our callee (and our own register save area). */ + actual_fsize = compute_frame_size (size, leaf_function); + + if (leaf_function) + { + frame_base_name = "%sp"; + frame_base_offset = actual_fsize + SPARC_STACK_BIAS; + } + else + { + frame_base_name = "%fp"; + frame_base_offset = SPARC_STACK_BIAS; + } + + /* This is only for the human reader. */ + fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START); + + if (actual_fsize == 0) + /* do nothing. */ ; + else if (! leaf_function && ! TARGET_BROKEN_SAVERESTORE) + { + if (actual_fsize <= 4096) + fprintf (file, "\tsave %%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); + } + else + { + build_big_number (file, -actual_fsize, "%g1"); + fprintf (file, "\tsave %%sp,%%g1,%%sp\n"); + } + } + else if (! leaf_function && TARGET_BROKEN_SAVERESTORE) + { + /* We assume the environment will properly handle or otherwise avoid + trouble associated with an interrupt occurring after the `save' or + trap occurring during it. */ + fprintf (file, "\tsave\n"); + + if (actual_fsize <= 4096) + fprintf (file, "\tadd %%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); + } + else + { + build_big_number (file, -actual_fsize, "%g1"); + fprintf (file, "\tadd %%fp,%%g1,%%sp\n"); + } + } + else /* leaf function */ + { + if (actual_fsize <= 4096) + fprintf (file, "\tadd %%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); + } + else + { + build_big_number (file, -actual_fsize, "%g1"); + fprintf (file, "\tadd %%sp,%%g1,%%sp\n"); + } + } + + if (dwarf2out_do_frame () && actual_fsize) + { + char *label = dwarf2out_cfi_label (); + + /* The canonical frame address refers to the top of the frame. */ + dwarf2out_def_cfa (label, (leaf_function ? STACK_POINTER_REGNUM + : FRAME_POINTER_REGNUM), + frame_base_offset); + + if (! leaf_function) + { + /* Note the register window save. This tells the unwinder that + it needs to restore the window registers from the previous + frame's window save area at 0(cfa). */ + dwarf2out_window_save (label); + + /* The return address (-8) is now in %i7. */ + dwarf2out_return_reg (label, 31); + } + } + + /* If doing anything with PIC, do it now. */ + if (! flag_pic) + fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START); + + /* Call saved registers are saved just above the outgoing argument area. */ + if (num_gfregs) + { + int offset, real_offset, n_regs; + char *base; + + real_offset = -apparent_fsize; + offset = -apparent_fsize + frame_base_offset; + if (offset < -4096 || offset + num_gfregs * 4 > 4096) + { + /* ??? This might be optimized a little as %g1 might already have a + value close enough that a single add insn will do. */ + /* ??? Although, all of this is probably only a temporary fix + because if %g1 can hold a function result, then + 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); + base = "%g1"; + offset = 0; + } + else + { + base = frame_base_name; + } + + n_regs = 0; + if (TARGET_EPILOGUE && ! leaf_function) + /* ??? Originally saved regs 0-15 here. */ + n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset); + else if (leaf_function) + /* ??? Originally saved regs 0-31 here. */ + n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset); + if (TARGET_EPILOGUE) + save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs, + real_offset); + } + + leaf_label = 0; + if (leaf_function && actual_fsize != 0) + { + /* warning ("leaf procedure with frame size %d", actual_fsize); */ + if (! TARGET_EPILOGUE) + leaf_label = gen_label_rtx (); + } +} + +/* Output code for the function epilogue. */ + +void +output_function_epilogue (file, size, leaf_function) + FILE *file; + int size ATTRIBUTE_UNUSED; + int leaf_function; +{ + char *ret; + + if (leaf_label) + { + emit_label_after (leaf_label, get_last_insn ()); + final_scan_insn (get_last_insn (), file, 0, 0, 1); + } + +#ifdef FUNCTION_BLOCK_PROFILER_EXIT + else if (profile_block_flag == 2) + { + FUNCTION_BLOCK_PROFILER_EXIT(file); + } +#endif + + else if (current_function_epilogue_delay_list == 0) + { + /* If code does not drop into the epilogue, do nothing. */ + rtx insn = get_last_insn (); + if (GET_CODE (insn) == NOTE) + insn = prev_nonnote_insn (insn); + if (insn && GET_CODE (insn) == BARRIER) + return; + } + + /* Restore any call saved registers. */ + if (num_gfregs) + { + int offset, n_regs; + 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); + base = "%g1"; + offset = 0; + } + else + { + base = frame_base_name; + } + + n_regs = 0; + if (TARGET_EPILOGUE && ! leaf_function) + /* ??? Originally saved regs 0-15 here. */ + n_regs = restore_regs (file, 0, 8, base, offset, 0); + else if (leaf_function) + /* ??? Originally saved regs 0-31 here. */ + n_regs = restore_regs (file, 0, 8, base, offset, 0); + if (TARGET_EPILOGUE) + restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs); + } + + /* Work out how to skip the caller's unimp instruction if required. */ + if (leaf_function) + ret = (SKIP_CALLERS_UNIMP_P ? "jmp %o7+12" : "retl"); + else + ret = (SKIP_CALLERS_UNIMP_P ? "jmp %i7+12" : "ret"); + + if (TARGET_EPILOGUE || leaf_label) + { + int old_target_epilogue = TARGET_EPILOGUE; + target_flags &= ~old_target_epilogue; + + if (! leaf_function) + { + /* If we wound up with things in our delay slot, flush them here. */ + if (current_function_epilogue_delay_list) + { + rtx insn = emit_jump_insn_after (gen_rtx_RETURN (VOIDmode), + get_last_insn ()); + PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, + PATTERN (XEXP (current_function_epilogue_delay_list, 0)), + PATTERN (insn))); + final_scan_insn (insn, file, 1, 0, 1); + } + else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P) + fputs ("\treturn %i7+8\n\tnop\n", file); + else + fprintf (file, "\t%s\n\trestore\n", ret); + } + /* All of the following cases are for leaf functions. */ + else if (current_function_epilogue_delay_list) + { + /* eligible_for_epilogue_delay_slot ensures that if this is a + leaf function, then we will only have insn in the delay slot + if the frame size is zero, thus no adjust for the stack is + needed here. */ + if (actual_fsize != 0) + abort (); + fprintf (file, "\t%s\n", ret); + final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), + file, 1, 0, 1); + } + /* Output 'nop' instead of 'sub %sp,-0,%sp' when no frame, so as to + avoid generating confusing assembly language output. */ + 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); + else if (actual_fsize <= 8192) + fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%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", + 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", + actual_fsize, actual_fsize, ret); + target_flags |= old_target_epilogue; + } +} + +/* Functions for handling argument passing. + + For v8 the first six args are normally in registers and the rest are + pushed. Any arg that starts within the first 6 words is at least + partially passed in a register unless its data type forbids. + + For v9, the argument registers are laid out as an array of 16 elements + and arguments are added sequentially. The first 6 int args and up to the + first 16 fp args (depending on size) are passed in regs. + + Slot Stack Integral Float Float in structure Double Long Double + ---- ----- -------- ----- ------------------ ------ ----------- + 15 [SP+248] %f31 %f30,%f31 %d30 + 14 [SP+240] %f29 %f28,%f29 %d28 %q28 + 13 [SP+232] %f27 %f26,%f27 %d26 + 12 [SP+224] %f25 %f24,%f25 %d24 %q24 + 11 [SP+216] %f23 %f22,%f23 %d22 + 10 [SP+208] %f21 %f20,%f21 %d20 %q20 + 9 [SP+200] %f19 %f18,%f19 %d18 + 8 [SP+192] %f17 %f16,%f17 %d16 %q16 + 7 [SP+184] %f15 %f14,%f15 %d14 + 6 [SP+176] %f13 %f12,%f13 %d12 %q12 + 5 [SP+168] %o5 %f11 %f10,%f11 %d10 + 4 [SP+160] %o4 %f9 %f8,%f9 %d8 %q8 + 3 [SP+152] %o3 %f7 %f6,%f7 %d6 + 2 [SP+144] %o2 %f5 %f4,%f5 %d4 %q4 + 1 [SP+136] %o1 %f3 %f2,%f3 %d2 + 0 [SP+128] %o0 %f1 %f0,%f1 %d0 %q0 + + Here SP = %sp if -mno-stack-bias or %sp+stack_bias otherwise. + + Integral arguments are always passed as 64 bit quantities appropriately + extended. + + Passing of floating point values is handled as follows. + If a prototype is in scope: + If the value is in a named argument (i.e. not a stdarg function or a + value not part of the `...') then the value is passed in the appropriate + fp reg. + If the value is part of the `...' and is passed in one of the first 6 + slots then the value is passed in the appropriate int reg. + If the value is part of the `...' and is not passed in one of the first 6 + slots then the value is passed in memory. + If a prototype is not in scope: + If the value is one of the first 6 arguments the value is passed in the + appropriate integer reg and the appropriate fp reg. + If the value is not one of the first 6 arguments the value is passed in + the appropriate fp reg and in memory. + */ + +/* Maximum number of int regs for args. */ +#define SPARC_INT_ARG_MAX 6 +/* Maximum number of fp regs for args. */ +#define SPARC_FP_ARG_MAX 16 + +#define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Handle the INIT_CUMULATIVE_ARGS macro. + Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +void +init_cumulative_args (cum, fntype, libname, indirect) + CUMULATIVE_ARGS *cum; + tree fntype; + tree libname ATTRIBUTE_UNUSED; + int indirect ATTRIBUTE_UNUSED; +{ + cum->words = 0; + cum->prototype_p = fntype && TYPE_ARG_TYPES (fntype); + cum->libcall_p = fntype == 0; +} + +/* Compute the slot number to pass an argument in. + Returns the slot number or -1 if passing on the stack. + + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). + INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG. + *PREGNO records the register number to use if scalar type. + *PPADDING records the amount of padding needed in words. */ + +static int +function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding) + const CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; + int incoming_p; + int *pregno; + int *ppadding; +{ + int regbase = (incoming_p + ? SPARC_INCOMING_INT_ARG_FIRST + : SPARC_OUTGOING_INT_ARG_FIRST); + int slotno = cum->words; + int regno; + + *ppadding = 0; + + if (type != 0 && TREE_ADDRESSABLE (type)) + return -1; + if (TARGET_ARCH32 + && type != 0 && mode == BLKmode + && TYPE_ALIGN (type) % PARM_BOUNDARY != 0) + return -1; + + switch (mode) + { + case VOIDmode : + /* MODE is VOIDmode when generating the actual call. + See emit_call_1. */ + return -1; + + case QImode : case CQImode : + case HImode : case CHImode : + case SImode : case CSImode : + case DImode : case CDImode : + if (slotno >= SPARC_INT_ARG_MAX) + return -1; + regno = regbase + slotno; + break; + + case SFmode : case SCmode : + case DFmode : case DCmode : + case TFmode : case TCmode : + if (TARGET_ARCH32) + { + if (slotno >= SPARC_INT_ARG_MAX) + return -1; + regno = regbase + slotno; + } + else + { + if ((mode == TFmode || mode == TCmode) + && (slotno & 1) != 0) + slotno++, *ppadding = 1; + if (TARGET_FPU && named) + { + if (slotno >= SPARC_FP_ARG_MAX) + return -1; + regno = SPARC_FP_ARG_FIRST + slotno * 2; + if (mode == SFmode) + regno++; + } + else + { + if (slotno >= SPARC_INT_ARG_MAX) + return -1; + regno = regbase + slotno; + } + } + break; + + case BLKmode : + /* For sparc64, objects requiring 16 byte alignment get it. */ + if (TARGET_ARCH64) + { + if (type && TYPE_ALIGN (type) == 128 && (slotno & 1) != 0) + slotno++, *ppadding = 1; + } + + if (TARGET_ARCH32 + || (type && TREE_CODE (type) == UNION_TYPE)) + { + if (slotno >= SPARC_INT_ARG_MAX) + return -1; + regno = regbase + slotno; + } + else + { + tree field; + int intregs_p = 0, fpregs_p = 0; + /* The ABI obviously doesn't specify how packed + structures are passed. These are defined to be passed + in int regs if possible, otherwise memory. */ + int packed_p = 0; + + /* First see what kinds of registers we need. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL) + { + if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE + && TARGET_FPU) + fpregs_p = 1; + else + intregs_p = 1; + if (DECL_PACKED (field)) + packed_p = 1; + } + } + if (packed_p || !named) + fpregs_p = 0, intregs_p = 1; + + /* If all arg slots are filled, then must pass on stack. */ + if (fpregs_p && slotno >= SPARC_FP_ARG_MAX) + return -1; + /* If there are only int args and all int arg slots are filled, + then must pass on stack. */ + if (!fpregs_p && intregs_p && slotno >= SPARC_INT_ARG_MAX) + return -1; + /* Note that even if all int arg slots are filled, fp members may + still be passed in regs if such regs are available. + *PREGNO isn't set because there may be more than one, it's up + to the caller to compute them. */ + return slotno; + } + break; + + default : + abort (); + } + + *pregno = regno; + return slotno; +} + +/* Handle recursive register counting for structure field layout. */ + +struct function_arg_record_value_parms +{ + rtx ret; + int slotno, named, regbase; + int nregs, intoffset; +}; + +static void +function_arg_record_value_1 (type, startbitpos, parms) + tree type; + int startbitpos; + struct function_arg_record_value_parms *parms; +{ + tree field; + + /* The ABI obviously doesn't specify how packed structures are + passed. These are defined to be passed in int regs if possible, + otherwise memory. */ + int packed_p = 0; + + /* We need to compute how many registers are needed so we can + allocate the PARALLEL but before we can do that we need to know + whether there are any packed fields. If there are, int regs are + used regardless of whether there are fp values present. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) + { + packed_p = 1; + break; + } + } + + /* Compute how many registers we need. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL) + { + int bitpos = startbitpos; + if (DECL_FIELD_BITPOS (field)) + bitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); + /* ??? FIXME: else assume zero offset. */ + + if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE) + { + function_arg_record_value_1 (TREE_TYPE (field), bitpos, parms); + } + else if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE + && TARGET_FPU + && ! packed_p + && parms->named) + { + if (parms->intoffset != -1) + { + int intslots, this_slotno; + + intslots = (bitpos - parms->intoffset + BITS_PER_WORD - 1) + / BITS_PER_WORD; + this_slotno = parms->slotno + parms->intoffset + / BITS_PER_WORD; + + intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno); + intslots = MAX (intslots, 0); + parms->nregs += intslots; + parms->intoffset = -1; + } + + /* There's no need to check this_slotno < SPARC_FP_ARG MAX. + If it wasn't true we wouldn't be here. */ + parms->nregs += 1; + } + else + { + if (parms->intoffset == -1) + parms->intoffset = bitpos; + } + } + } +} + +/* Handle recursive structure field register assignment. */ + +static void +function_arg_record_value_3 (bitpos, parms) + int bitpos; + struct function_arg_record_value_parms *parms; +{ + enum machine_mode mode; + int regno, this_slotno, intslots, intoffset; + rtx reg; + + if (parms->intoffset == -1) + return; + intoffset = parms->intoffset; + parms->intoffset = -1; + + intslots = (bitpos - intoffset + BITS_PER_WORD - 1) / BITS_PER_WORD; + this_slotno = parms->slotno + intoffset / BITS_PER_WORD; + + intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno); + if (intslots <= 0) + return; + + /* If this is the trailing part of a word, only load that much into + the register. Otherwise load the whole register. Note that in + the latter case we may pick up unwanted bits. It's not a problem + at the moment but may wish to revisit. */ + + if (intoffset % BITS_PER_WORD != 0) + { + mode = mode_for_size (BITS_PER_WORD - intoffset%BITS_PER_WORD, + MODE_INT, 0); + } + else + mode = word_mode; + + intoffset /= BITS_PER_UNIT; + do + { + regno = parms->regbase + this_slotno; + reg = gen_rtx_REG (mode, regno); + XVECEXP (parms->ret, 0, parms->nregs) + = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset)); + + this_slotno += 1; + intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1; + parms->nregs += 1; + intslots -= 1; + } + while (intslots > 0); +} + +static void +function_arg_record_value_2 (type, startbitpos, parms) + tree type; + int startbitpos; + struct function_arg_record_value_parms *parms; +{ + tree field; + int packed_p = 0; + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) + { + packed_p = 1; + break; + } + } + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL) + { + int bitpos = startbitpos; + if (DECL_FIELD_BITPOS (field)) + bitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); + /* ??? FIXME: else assume zero offset. */ + + if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE) + { + function_arg_record_value_2 (TREE_TYPE (field), bitpos, parms); + } + else if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE + && TARGET_FPU + && ! packed_p + && parms->named) + { + int this_slotno = parms->slotno + bitpos / BITS_PER_WORD; + rtx reg; + + function_arg_record_value_3 (bitpos, parms); + + reg = gen_rtx_REG (DECL_MODE (field), + (SPARC_FP_ARG_FIRST + this_slotno * 2 + + (DECL_MODE (field) == SFmode + && (bitpos & 32) != 0))); + XVECEXP (parms->ret, 0, parms->nregs) + = gen_rtx_EXPR_LIST (VOIDmode, reg, + GEN_INT (bitpos / BITS_PER_UNIT)); + parms->nregs += 1; + } + else + { + if (parms->intoffset == -1) + parms->intoffset = bitpos; + } + } + } +} + +static rtx +function_arg_record_value (type, mode, slotno, named, regbase) + tree type; + enum machine_mode mode; + int slotno, named, regbase; +{ + HOST_WIDE_INT typesize = int_size_in_bytes (type); + struct function_arg_record_value_parms parms; + int nregs; + + parms.ret = NULL_RTX; + parms.slotno = slotno; + parms.named = named; + parms.regbase = regbase; + + /* Compute how many registers we need. */ + parms.nregs = 0; + parms.intoffset = 0; + function_arg_record_value_1 (type, 0, &parms); + + if (parms.intoffset != -1) + { + int intslots, this_slotno; + + intslots = (typesize*BITS_PER_UNIT - parms.intoffset + BITS_PER_WORD - 1) + / BITS_PER_WORD; + this_slotno = slotno + parms.intoffset / BITS_PER_WORD; + + intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno); + intslots = MAX (intslots, 0); + + parms.nregs += intslots; + } + nregs = parms.nregs; + + /* Allocate the vector and handle some annoying special cases. */ + if (nregs == 0) + { + /* ??? Empty structure has no value? Duh? */ + if (typesize <= 0) + { + /* Though there's nothing really to store, return a word register + anyway so the rest of gcc doesn't go nuts. Returning a PARALLEL + leads to breakage due to the fact that there are zero bytes to + load. */ + return gen_rtx_REG (mode, regbase); + } + else + { + /* ??? C++ has structures with no fields, and yet a size. Give up + for now and pass everything back in integer registers. */ + nregs = (typesize + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + } + if (nregs + slotno > SPARC_INT_ARG_MAX) + nregs = SPARC_INT_ARG_MAX - slotno; + } + if (nregs == 0) + abort(); + + parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs)); + + /* Fill in the entries. */ + parms.nregs = 0; + parms.intoffset = 0; + function_arg_record_value_2 (type, 0, &parms); + function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms); + + if (parms.nregs != nregs) + abort (); + + return parms.ret; +} + +/* Handle the FUNCTION_ARG macro. + Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). + INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG. */ + +rtx +function_arg (cum, mode, type, named, incoming_p) + const CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; + int incoming_p; +{ + int regbase = (incoming_p + ? SPARC_INCOMING_INT_ARG_FIRST + : SPARC_OUTGOING_INT_ARG_FIRST); + int slotno, regno, padding; + rtx reg; + + slotno = function_arg_slotno (cum, mode, type, named, incoming_p, + ®no, &padding); + + if (slotno == -1) + return 0; + + if (TARGET_ARCH32) + { + reg = gen_rtx_REG (mode, regno); + return reg; + } + + /* v9 fp args in reg slots beyond the int reg slots get passed in regs + but also have the slot allocated for them. + If no prototype is in scope fp values in register slots get passed + in two places, either fp regs and int regs or fp regs and memory. */ + if ((GET_MODE_CLASS (mode) == MODE_FLOAT + || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) + && SPARC_FP_REG_P (regno)) + { + reg = gen_rtx_REG (mode, regno); + if (cum->prototype_p || cum->libcall_p) + { + /* "* 2" because fp reg numbers are recorded in 4 byte + quantities. */ +#if 0 + /* ??? This will cause the value to be passed in the fp reg and + in the stack. When a prototype exists we want to pass the + value in the reg but reserve space on the stack. That's an + optimization, and is deferred [for a bit]. */ + if ((regno - SPARC_FP_ARG_FIRST) >= SPARC_INT_ARG_MAX * 2) + return gen_rtx_PARALLEL (mode, + gen_rtvec (2, + gen_rtx_EXPR_LIST (VOIDmode, + NULL_RTX, const0_rtx), + gen_rtx_EXPR_LIST (VOIDmode, + reg, const0_rtx))); + else +#else + /* ??? It seems that passing back a register even when past + the area declared by REG_PARM_STACK_SPACE will allocate + space appropriately, and will not copy the data onto the + stack, exactly as we desire. + + This is due to locate_and_pad_parm being called in + expand_call whenever reg_parm_stack_space > 0, which + while benefical to our example here, would seem to be + in error from what had been intended. Ho hum... -- r~ */ +#endif + return reg; + } + else + { + rtx v0, v1; + + if ((regno - SPARC_FP_ARG_FIRST) < SPARC_INT_ARG_MAX * 2) + { + int intreg; + + /* On incoming, we don't need to know that the value + is passed in %f0 and %i0, and it confuses other parts + causing needless spillage even on the simplest cases. */ + if (incoming_p) + return reg; + + intreg = (SPARC_OUTGOING_INT_ARG_FIRST + + (regno - SPARC_FP_ARG_FIRST) / 2); + + v0 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx); + v1 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode, intreg), + const0_rtx); + return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1)); + } + else + { + v0 = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); + v1 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx); + return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1)); + } + } + } + else if (type && TREE_CODE (type) == RECORD_TYPE) + { + /* Structures up to 16 bytes in size are passed in arg slots on the + stack and are promoted to registers where possible. */ + + if (int_size_in_bytes (type) > 16) + abort (); /* shouldn't get here */ + + return function_arg_record_value (type, mode, slotno, named, regbase); + } + else if (type && TREE_CODE (type) == UNION_TYPE) + { + enum machine_mode mode; + int bytes = int_size_in_bytes (type); + + if (bytes > 16) + abort (); + + mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0); + reg = gen_rtx_REG (mode, regno); + } + else + { + /* Scalar or complex int. */ + reg = gen_rtx_REG (mode, regno); + } + + return reg; +} + +/* Handle the FUNCTION_ARG_PARTIAL_NREGS macro. + For an arg passed partly in registers and partly in memory, + this is the number of registers used. + For args passed entirely in registers or entirely in memory, zero. + + Any arg that starts in the first 6 regs but won't entirely fit in them + needs partial registers on v8. On v9, structures with integer + values in arg slots 5,6 will be passed in %o5 and SP+176, and complex fp + values that begin in the last fp reg [where "last fp reg" varies with the + mode] will be split between that reg and memory. */ + +int +function_arg_partial_nregs (cum, mode, type, named) + const CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + int slotno, regno, padding; + + /* We pass 0 for incoming_p here, it doesn't matter. */ + slotno = function_arg_slotno (cum, mode, type, named, 0, ®no, &padding); + + if (slotno == -1) + return 0; + + if (TARGET_ARCH32) + { + if ((slotno + (mode == BLKmode + ? ROUND_ADVANCE (int_size_in_bytes (type)) + : ROUND_ADVANCE (GET_MODE_SIZE (mode)))) + > NPARM_REGS (SImode)) + return NPARM_REGS (SImode) - slotno; + return 0; + } + else + { + if (type && AGGREGATE_TYPE_P (type)) + { + int size = int_size_in_bytes (type); + int align = TYPE_ALIGN (type); + + if (align == 16) + slotno += slotno & 1; + if (size > 8 && size <= 16 + && slotno == SPARC_INT_ARG_MAX - 1) + return 1; + } + else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT + || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT + && ! TARGET_FPU)) + { + if (GET_MODE_ALIGNMENT (mode) == 128) + { + slotno += slotno & 1; + if (slotno == SPARC_INT_ARG_MAX - 2) + return 1; + } + else + { + if (slotno == SPARC_INT_ARG_MAX - 1) + return 1; + } + } + else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) + { + if (GET_MODE_ALIGNMENT (mode) == 128) + slotno += slotno & 1; + if ((slotno + GET_MODE_SIZE (mode) / UNITS_PER_WORD) + > SPARC_FP_ARG_MAX) + return 1; + } + return 0; + } +} + +/* Handle the FUNCTION_ARG_PASS_BY_REFERENCE macro. + !v9: The SPARC ABI stipulates passing struct arguments (of any size) and + quad-precision floats by invisible reference. + v9: Aggregates greater than 16 bytes are passed by reference. + For Pascal, also pass arrays by reference. */ + +int +function_arg_pass_by_reference (cum, mode, type, named) + const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; + enum machine_mode mode; + tree type; + int named ATTRIBUTE_UNUSED; +{ + if (TARGET_ARCH32) + { + return ((type && AGGREGATE_TYPE_P (type)) + || mode == TFmode || mode == TCmode); + } + else + { + return ((type && TREE_CODE (type) == ARRAY_TYPE) + /* Consider complex values as aggregates, so care for TCmode. */ + || GET_MODE_SIZE (mode) > 16 + || (type && AGGREGATE_TYPE_P (type) + && int_size_in_bytes (type) > 16)); + } +} + +/* Handle the FUNCTION_ARG_ADVANCE macro. + Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + TYPE is null for libcalls where that information may not be available. */ + +void +function_arg_advance (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + int slotno, regno, padding; + + /* We pass 0 for incoming_p here, it doesn't matter. */ + slotno = function_arg_slotno (cum, mode, type, named, 0, ®no, &padding); + + /* If register required leading padding, add it. */ + if (slotno != -1) + cum->words += padding; + + if (TARGET_ARCH32) + { + cum->words += (mode != BLKmode + ? ROUND_ADVANCE (GET_MODE_SIZE (mode)) + : ROUND_ADVANCE (int_size_in_bytes (type))); + } + else + { + if (type && AGGREGATE_TYPE_P (type)) + { + int size = int_size_in_bytes (type); + + if (size <= 8) + ++cum->words; + else if (size <= 16) + cum->words += 2; + else /* passed by reference */ + ++cum->words; + } + else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT) + { + cum->words += 2; + } + else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) + { + cum->words += GET_MODE_SIZE (mode) / UNITS_PER_WORD; + } + else + { + cum->words += (mode != BLKmode + ? ROUND_ADVANCE (GET_MODE_SIZE (mode)) + : ROUND_ADVANCE (int_size_in_bytes (type))); + } + } +} + +/* Handle the FUNCTION_ARG_PADDING macro. + For the 64 bit ABI structs are always stored left shifted in their + argument slot. */ + +enum direction +function_arg_padding (mode, type) + enum machine_mode mode; + tree type; +{ + if (TARGET_ARCH64 && type != 0 && AGGREGATE_TYPE_P (type)) + return upward; + + /* This is the default definition. */ + return (! BYTES_BIG_ENDIAN + ? upward + : ((mode == BLKmode + ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST + && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT)) + : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY) + ? downward : upward)); +} + +/* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE macros. + For v9, function return values are subject to the same rules as arguments, + except that up to 32-bytes may be returned in registers. */ + +rtx +function_value (type, mode, incoming_p) + tree type; + enum machine_mode mode; + int incoming_p; +{ + int regno; + int regbase = (incoming_p + ? SPARC_OUTGOING_INT_ARG_FIRST + : SPARC_INCOMING_INT_ARG_FIRST); + + if (TARGET_ARCH64 && type) + { + if (TREE_CODE (type) == RECORD_TYPE) + { + /* Structures up to 32 bytes in size are passed in registers, + promoted to fp registers where possible. */ + + if (int_size_in_bytes (type) > 32) + abort (); /* shouldn't get here */ + + return function_arg_record_value (type, mode, 0, 1, regbase); + } + else if (TREE_CODE (type) == UNION_TYPE) + { + int bytes = int_size_in_bytes (type); + + if (bytes > 32) + abort (); + + mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0); + } + } + + if (incoming_p) + regno = BASE_RETURN_VALUE_REG (mode); + else + regno = BASE_OUTGOING_VALUE_REG (mode); + + return gen_rtx_REG (mode, regno); +} + +/* Do what is necessary for `va_start'. The argument is ignored. + + We look at the current function to determine if stdarg or varargs + is used and return the address of the first unnamed parameter. */ + +rtx +sparc_builtin_saveregs (arglist) + tree arglist ATTRIBUTE_UNUSED; +{ + int first_reg = current_function_args_info.words; + rtx address; + int regno; + + for (regno = first_reg; regno < NPARM_REGS (word_mode); regno++) + emit_move_insn (gen_rtx_MEM (word_mode, + gen_rtx_PLUS (Pmode, + frame_pointer_rtx, + GEN_INT (STACK_POINTER_OFFSET + + UNITS_PER_WORD * regno))), + gen_rtx_REG (word_mode, + BASE_INCOMING_ARG_REG (word_mode) + regno)); + + address = gen_rtx_PLUS (Pmode, + frame_pointer_rtx, + GEN_INT (STACK_POINTER_OFFSET + + UNITS_PER_WORD * first_reg)); + + if (flag_check_memory_usage + && first_reg < NPARM_REGS (word_mode)) + emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, + address, ptr_mode, + GEN_INT (UNITS_PER_WORD + * (NPARM_REGS (word_mode) - first_reg)), + TYPE_MODE (sizetype), GEN_INT (MEMORY_USE_RW), + TYPE_MODE (integer_type_node)); + + return address; +} + +/* Return the string to output a conditional branch to LABEL, which is + the operand number of the label. OP is the conditional expression. + XEXP (OP, 0) is assumed to be a condition code register (integer or + floating point) and its mode specifies what kind of comparison we made. + + REVERSED is non-zero if we should reverse the sense of the comparison. + + ANNUL is non-zero if we should generate an annulling branch. + + NOOP is non-zero if we have to follow this branch by a noop. + + INSN, if set, is the insn. */ + +char * +output_cbranch (op, label, reversed, annul, noop, insn) + rtx op; + int label; + int reversed, annul, noop; + rtx insn; +{ + static char string[20]; + 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"; + char *labelno; + int labeloff; + + /* ??? !v9: FP branches cannot be preceded by another floating point insn. + Because there is currently no concept of pre-delay slots, we can fix + this only by always emitting a nop before a floating point branch. */ + + if ((mode == CCFPmode || mode == CCFPEmode) && ! TARGET_V9) + strcpy (string, "nop\n\t"); + else + string[0] = '\0'; + + /* If not floating-point or if EQ or NE, we can just reverse the code. */ + if (reversed + && ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE)) + code = reverse_condition (code), reversed = 0; + + /* Start by writing the branch condition. */ + switch (code) + { + case NE: + if (mode == CCFPmode || mode == CCFPEmode) + strcat (string, "fbne"); + else + strcpy (string, "bne"); + break; + + case EQ: + if (mode == CCFPmode || mode == CCFPEmode) + strcat (string, "fbe"); + else + strcpy (string, "be"); + break; + + case GE: + if (mode == CCFPmode || mode == CCFPEmode) + { + if (reversed) + strcat (string, "fbul"); + else + strcat (string, "fbge"); + } + else if (mode == CC_NOOVmode) + strcpy (string, "bpos"); + else + strcpy (string, "bge"); + break; + + case GT: + if (mode == CCFPmode || mode == CCFPEmode) + { + if (reversed) + strcat (string, "fbule"); + else + strcat (string, "fbg"); + } + else + strcpy (string, "bg"); + break; + + case LE: + if (mode == CCFPmode || mode == CCFPEmode) + { + if (reversed) + strcat (string, "fbug"); + else + strcat (string, "fble"); + } + else + strcpy (string, "ble"); + break; + + case LT: + if (mode == CCFPmode || mode == CCFPEmode) + { + if (reversed) + strcat (string, "fbuge"); + else + strcat (string, "fbl"); + } + else if (mode == CC_NOOVmode) + strcpy (string, "bneg"); + else + strcpy (string, "bl"); + break; + + case GEU: + strcpy (string, "bgeu"); + break; + + case GTU: + strcpy (string, "bgu"); + break; + + case LEU: + strcpy (string, "bleu"); + break; + + case LTU: + strcpy (string, "blu"); + break; + + default: + break; + } + + /* Now add the annulling, the label, and a possible noop. */ + if (annul) + strcat (string, ",a"); + + if (! TARGET_V9) + { + labeloff = 3; + labelno = v8_labelno; + } + else + { + 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"); + + labeloff = 9; + if (mode == CCFPmode || mode == CCFPEmode) + { + 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'; + } + else if (mode == CCXmode || mode == CCX_NOOVmode) + labelno = v9_xcc_labelno; + else + labelno = v9_icc_labelno; + } + /* Set the char indicating the number of the operand containing the + label_ref. */ + labelno[labeloff] = label + '0'; + strcat (string, labelno); + + if (noop) + strcat (string, "\n\tnop"); + + return string; +} + +/* Return the string to output a conditional branch to LABEL, testing + register REG. LABEL is the operand number of the label; REG is the + operand number of the reg. OP is the conditional expression. The mode + of REG says what kind of comparison we made. + + REVERSED is non-zero if we should reverse the sense of the comparison. + + ANNUL is non-zero if we should generate an annulling branch. + + NOOP is non-zero if we have to follow this branch by a noop. */ + +char * +output_v9branch (op, reg, label, reversed, annul, noop) + rtx op; + int reg, label; + int reversed, annul, noop; +{ + 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"; + + /* If not floating-point or if EQ or NE, we can just reverse the code. */ + if (reversed) + code = reverse_condition (code), reversed = 0; + + /* Only 64 bit versions of these instructions exist. */ + if (mode != DImode) + abort (); + + /* Start by writing the branch condition. */ + + switch (code) + { + case NE: + strcpy (string, "brnz"); + break; + + case EQ: + strcpy (string, "brz"); + break; + + case GE: + strcpy (string, "brgez"); + break; + + case LT: + strcpy (string, "brlz"); + break; + + case LE: + strcpy (string, "brlez"); + break; + + case GT: + strcpy (string, "brgz"); + break; + + default: + abort (); + } + + /* Now add the annulling, reg, label, and nop. */ + if (annul) + strcat (string, ",a"); + + /* ??? Optional prediction bit ",pt" or ",pf" goes here. */ + + labelno[2] = reg + '0'; + labelno[6] = label + '0'; + strcat (string, labelno); + + if (noop) + strcat (string, "\n\tnop"); + + return string; +} + +/* Renumber registers in delay slot. Replace registers instead of + renumbering because they may be shared. + + This does not handle instructions other than move. */ + +static void +epilogue_renumber (where) + rtx *where; +{ + rtx x = *where; + enum rtx_code code = GET_CODE (x); + + switch (code) + { + case MEM: + *where = x = copy_rtx (x); + epilogue_renumber (&XEXP (x, 0)); + return; + + case REG: + { + int regno = REGNO (x); + if (regno > 8 && regno < 24) + abort (); + if (regno >= 24 && regno < 32) + *where = gen_rtx_REG (GET_MODE (x), regno - 16); + return; + } + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case LABEL_REF: + return; + + case IOR: + case AND: + case XOR: + case PLUS: + case MINUS: + epilogue_renumber (&XEXP (x, 1)); + case NEG: + case NOT: + epilogue_renumber (&XEXP (x, 0)); + return; + + default: + debug_rtx (*where); + abort(); + } +} + +/* Output assembler code to return from a function. */ + +char * +output_return (operands) + rtx *operands; +{ + rtx delay = final_sequence ? XVECEXP (final_sequence, 0, 1) : 0; + + if (leaf_label) + { + operands[0] = leaf_label; + return "b%* %l0%("; + } + else if (leaf_function) + { + /* No delay slot in a leaf function. */ + if (delay) + abort (); + + /* If we didn't allocate a frame pointer for the current function, + the stack pointer might have been adjusted. Output code to + restore it now. */ + + operands[0] = GEN_INT (actual_fsize); + + /* Use sub of negated value in first two cases instead of add to + allow actual_fsize == 4096. */ + + if (actual_fsize <= 4096) + { + if (SKIP_CALLERS_UNIMP_P) + return "jmp %%o7+12\n\tsub %%sp,-%0,%%sp"; + else + return "retl\n\tsub %%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"; + else + return "sub %%sp,-4096,%%sp\n\tretl\n\tsub %%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"; + else + return "sethi %%hi(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp"; + } + else + { + if ((actual_fsize & 0x3ff) != 0) + return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp"; + else + return "sethi %%hi(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp"; + } + } + else if (TARGET_V9) + { + if (delay) + { + epilogue_renumber (&SET_DEST (PATTERN (delay))); + epilogue_renumber (&SET_SRC (PATTERN (delay))); + } + if (SKIP_CALLERS_UNIMP_P) + return "return %%i7+12%#"; + else + return "return %%i7+8%#"; + } + else + { + if (delay) + abort (); + if (SKIP_CALLERS_UNIMP_P) + return "jmp %%i7+12\n\trestore"; + else + return "ret\n\trestore"; + } +} + +/* Leaf functions and non-leaf functions have different needs. */ + +static int +reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER; + +static int +reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER; + +static int *reg_alloc_orders[] = { + reg_leaf_alloc_order, + reg_nonleaf_alloc_order}; + +void +order_regs_for_local_alloc () +{ + static int last_order_nonleaf = 1; + + if (regs_ever_live[15] != last_order_nonleaf) + { + last_order_nonleaf = !last_order_nonleaf; + bcopy ((char *) reg_alloc_orders[last_order_nonleaf], + (char *) reg_alloc_order, FIRST_PSEUDO_REGISTER * sizeof (int)); + } +} + +/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1. + This makes them candidates for using ldd and std insns. + + Note reg1 and reg2 *must* be hard registers. */ + +int +registers_ok_for_ldd_peep (reg1, reg2) + rtx reg1, reg2; +{ + /* We might have been passed a SUBREG. */ + if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG) + return 0; + + if (REGNO (reg1) % 2 != 0) + return 0; + + /* Integer ldd is deprecated in SPARC V9 */ + if (TARGET_V9 && REGNO (reg1) < 32) + return 0; + + return (REGNO (reg1) == REGNO (reg2) - 1); +} + +/* Return 1 if addr1 and addr2 are suitable for use in an ldd or + std insn. + + This can only happen when addr1 and addr2 are consecutive memory + locations (addr1 + 4 == addr2). addr1 must also be aligned on a + 64 bit boundary (addr1 % 8 == 0). + + We know %sp and %fp are kept aligned on a 64 bit boundary. Other + registers are assumed to *never* be properly aligned and are + rejected. + + Knowing %sp and %fp are kept aligned on a 64 bit boundary, we + need only check that the offset for addr1 % 8 == 0. */ + +int +addrs_ok_for_ldd_peep (addr1, addr2) + rtx addr1, addr2; +{ + int reg1, offset1; + + /* Extract a register number and offset (if used) from the first addr. */ + if (GET_CODE (addr1) == PLUS) + { + /* If not a REG, return zero. */ + if (GET_CODE (XEXP (addr1, 0)) != REG) + return 0; + else + { + reg1 = REGNO (XEXP (addr1, 0)); + /* The offset must be constant! */ + if (GET_CODE (XEXP (addr1, 1)) != CONST_INT) + return 0; + offset1 = INTVAL (XEXP (addr1, 1)); + } + } + else if (GET_CODE (addr1) != REG) + return 0; + else + { + reg1 = REGNO (addr1); + /* This was a simple (mem (reg)) expression. Offset is 0. */ + offset1 = 0; + } + + /* Make sure the second address is a (mem (plus (reg) (const_int). */ + if (GET_CODE (addr2) != PLUS) + return 0; + + if (GET_CODE (XEXP (addr2, 0)) != REG + || GET_CODE (XEXP (addr2, 1)) != CONST_INT) + return 0; + + /* Only %fp and %sp are allowed. Additionally both addresses must + use the same register. */ + if (reg1 != FRAME_POINTER_REGNUM && reg1 != STACK_POINTER_REGNUM) + return 0; + + if (reg1 != REGNO (XEXP (addr2, 0))) + return 0; + + /* The first offset must be evenly divisible by 8 to ensure the + address is 64 bit aligned. */ + if (offset1 % 8 != 0) + return 0; + + /* The offset for the second addr must be 4 more than the first addr. */ + if (INTVAL (XEXP (addr2, 1)) != offset1 + 4) + return 0; + + /* All the tests passed. addr1 and addr2 are valid for ldd and std + instructions. */ + return 1; +} + +/* Return 1 if reg is a pseudo, or is the first register in + a hard register pair. This makes it a candidate for use in + ldd and std insns. */ + +int +register_ok_for_ldd (reg) + rtx reg; +{ + /* We might have been passed a SUBREG. */ + if (GET_CODE (reg) != REG) + return 0; + + if (REGNO (reg) < FIRST_PSEUDO_REGISTER) + return (REGNO (reg) % 2 == 0); + else + return 1; +} + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ + +void +print_operand (file, x, code) + FILE *file; + rtx x; + int code; +{ + switch (code) + { + case '#': + /* Output a 'nop' if there's nothing for the delay slot. */ + if (dbr_sequence_length () == 0) + fputs ("\n\tnop", file); + return; + case '*': + /* Output an annul flag if there's nothing for the delay slot and we + are optimizing. This is always used with '(' below. */ + /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch; + this is a dbx bug. So, we only do this when optimizing. */ + /* On UltraSPARC, a branch in a delay slot causes a pipeline flush. + Always emit a nop in case the next instruction is a branch. */ + if (dbr_sequence_length () == 0 + && (optimize && (int)sparc_cpu < PROCESSOR_V9)) + fputs (",a", file); + return; + case '(': + /* Output a 'nop' if there's nothing for the delay slot and we are + not optimizing. This is always used with '*' above. */ + if (dbr_sequence_length () == 0 + && ! (optimize && (int)sparc_cpu < PROCESSOR_V9)) + fputs ("\n\tnop", file); + return; + case '_': + /* Output the Embedded Medium/Anywhere code model base register. */ + fputs (EMBMEDANY_BASE_REG, file); + return; + case '@': + /* Print out what we are using as the frame pointer. This might + be %fp, or might be %sp+offset. */ + /* ??? What if offset is too big? Perhaps the caller knows it isn't? */ + fprintf (file, "%s+%d", frame_base_name, frame_base_offset); + return; + case 'Y': + /* Adjust the operand to take into account a RESTORE operation. */ + if (GET_CODE (x) == CONST_INT) + break; + else if (GET_CODE (x) != REG) + output_operand_lossage ("Invalid %%Y operand"); + else if (REGNO (x) < 8) + fputs (reg_names[REGNO (x)], file); + else if (REGNO (x) >= 24 && REGNO (x) < 32) + fputs (reg_names[REGNO (x)-16], file); + else + output_operand_lossage ("Invalid %%Y operand"); + return; + case 'L': + /* Print out the low order register name of a register pair. */ + if (WORDS_BIG_ENDIAN) + fputs (reg_names[REGNO (x)+1], file); + else + fputs (reg_names[REGNO (x)], file); + return; + case 'H': + /* Print out the high order register name of a register pair. */ + if (WORDS_BIG_ENDIAN) + fputs (reg_names[REGNO (x)], file); + else + fputs (reg_names[REGNO (x)+1], file); + return; + case 'R': + /* Print out the second register name of a register pair or quad. + I.e., R (%o0) => %o1. */ + fputs (reg_names[REGNO (x)+1], file); + return; + case 'S': + /* Print out the third register name of a register quad. + I.e., S (%o0) => %o2. */ + fputs (reg_names[REGNO (x)+2], file); + return; + case 'T': + /* Print out the fourth register name of a register quad. + I.e., T (%o0) => %o3. */ + fputs (reg_names[REGNO (x)+3], file); + return; + case 'x': + /* Print a condition code register. */ + if (REGNO (x) == SPARC_ICC_REG) + { + /* We don't handle CC[X]_NOOVmode because they're not supposed + to occur here. */ + if (GET_MODE (x) == CCmode) + fputs ("%icc", file); + else if (GET_MODE (x) == CCXmode) + fputs ("%xcc", file); + else + abort (); + } + else + /* %fccN register */ + fputs (reg_names[REGNO (x)], file); + return; + case 'm': + /* Print the operand's address only. */ + output_address (XEXP (x, 0)); + return; + case 'r': + /* In this case we need a register. Use %g0 if the + operand is const0_rtx. */ + if (x == const0_rtx + || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x)))) + { + fputs ("%g0", file); + return; + } + else + break; + + case 'A': + switch (GET_CODE (x)) + { + case IOR: fputs ("or", file); break; + case AND: fputs ("and", file); break; + case XOR: fputs ("xor", file); break; + default: output_operand_lossage ("Invalid %%A operand"); + } + return; + + case 'B': + switch (GET_CODE (x)) + { + case IOR: fputs ("orn", file); break; + case AND: fputs ("andn", file); break; + case XOR: fputs ("xnor", file); break; + default: output_operand_lossage ("Invalid %%B operand"); + } + return; + + /* These are used by the conditional move instructions. */ + case 'c' : + case 'C': + { + enum rtx_code rc = (code == 'c' + ? reverse_condition (GET_CODE (x)) + : GET_CODE (x)); + switch (rc) + { + case NE: fputs ("ne", file); break; + case EQ: fputs ("e", file); break; + case GE: fputs ("ge", file); break; + case GT: fputs ("g", file); break; + case LE: fputs ("le", file); break; + case LT: fputs ("l", file); break; + case GEU: fputs ("geu", file); break; + case GTU: fputs ("gu", file); break; + case LEU: fputs ("leu", file); break; + case LTU: fputs ("lu", file); break; + default: output_operand_lossage (code == 'c' + ? "Invalid %%c operand" + : "Invalid %%C operand"); + } + return; + } + + /* These are used by the movr instruction pattern. */ + case 'd': + case 'D': + { + enum rtx_code rc = (code == 'd' + ? reverse_condition (GET_CODE (x)) + : GET_CODE (x)); + switch (rc) + { + case NE: fputs ("ne", file); break; + case EQ: fputs ("e", file); break; + case GE: fputs ("gez", file); break; + case LT: fputs ("lz", file); break; + case LE: fputs ("lez", file); break; + case GT: fputs ("gz", file); break; + default: output_operand_lossage (code == 'd' + ? "Invalid %%d operand" + : "Invalid %%D operand"); + } + return; + } + + case 'b': + { + /* Print a sign-extended character. */ + int i = INTVAL (x) & 0xff; + if (i & 0x80) + i |= 0xffffff00; + fprintf (file, "%d", i); + return; + } + + case 'f': + /* Operand must be a MEM; write its address. */ + if (GET_CODE (x) != MEM) + output_operand_lossage ("Invalid %%f operand"); + output_address (XEXP (x, 0)); + return; + + case 0: + /* Do nothing special. */ + break; + + default: + /* Undocumented flag. */ + output_operand_lossage ("invalid operand output code"); + } + + if (GET_CODE (x) == REG) + fputs (reg_names[REGNO (x)], file); + else if (GET_CODE (x) == MEM) + { + fputc ('[', file); + /* Poor Sun assembler doesn't understand absolute addressing. */ + if (CONSTANT_P (XEXP (x, 0)) + && ! TARGET_LIVE_G0) + fputs ("%g0+", file); + output_address (XEXP (x, 0)); + fputc (']', file); + } + else if (GET_CODE (x) == HIGH) + { + fputs ("%hi(", file); + output_addr_const (file, XEXP (x, 0)); + fputc (')', file); + } + else if (GET_CODE (x) == LO_SUM) + { + print_operand (file, XEXP (x, 0), 0); + fputs ("+%lo(", file); + output_addr_const (file, XEXP (x, 1)); + fputc (')', file); + } + else if (GET_CODE (x) == CONST_DOUBLE + && (GET_MODE (x) == VOIDmode + || GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)) + { + if (CONST_DOUBLE_HIGH (x) == 0) + fprintf (file, "%u", CONST_DOUBLE_LOW (x)); + else if (CONST_DOUBLE_HIGH (x) == -1 + && CONST_DOUBLE_LOW (x) < 0) + fprintf (file, "%d", CONST_DOUBLE_LOW (x)); + else + output_operand_lossage ("long long constant not a valid immediate operand"); + } + else if (GET_CODE (x) == CONST_DOUBLE) + output_operand_lossage ("floating point constant not a valid immediate operand"); + else { output_addr_const (file, x); } +} + +/* This function outputs assembler code for VALUE to FILE, where VALUE is + a 64 bit (DImode) value. */ + +/* ??? If there is a 64 bit counterpart to .word that the assembler + understands, then using that would simply this code greatly. */ +/* ??? We only output .xword's for symbols and only then in environments + where the assembler can handle them. */ + +void +output_double_int (file, value) + FILE *file; + rtx value; +{ + if (GET_CODE (value) == CONST_INT) + { + /* ??? This has endianness issues. */ +#if HOST_BITS_PER_WIDE_INT == 64 + HOST_WIDE_INT xword = INTVAL (value); + HOST_WIDE_INT high, low; + + high = (xword >> 32) & 0xffffffff; + low = xword & 0xffffffff; + ASM_OUTPUT_INT (file, GEN_INT (high)); + ASM_OUTPUT_INT (file, GEN_INT (low)); +#else + if (INTVAL (value) < 0) + ASM_OUTPUT_INT (file, constm1_rtx); + else + ASM_OUTPUT_INT (file, const0_rtx); + ASM_OUTPUT_INT (file, value); +#endif + } + else if (GET_CODE (value) == CONST_DOUBLE) + { + ASM_OUTPUT_INT (file, GEN_INT (CONST_DOUBLE_HIGH (value))); + ASM_OUTPUT_INT (file, GEN_INT (CONST_DOUBLE_LOW (value))); + } + else if (GET_CODE (value) == SYMBOL_REF + || GET_CODE (value) == CONST + || GET_CODE (value) == PLUS + || (TARGET_ARCH64 && + (GET_CODE (value) == LABEL_REF + || GET_CODE (value) == CODE_LABEL + || GET_CODE (value) == MINUS))) + { + if (!TARGET_V9 || TARGET_CM_MEDLOW) + { + ASM_OUTPUT_INT (file, const0_rtx); + ASM_OUTPUT_INT (file, value); + } + else + { + fprintf (file, "\t%s\t", ASM_LONGLONG); + output_addr_const (file, value); + fprintf (file, "\n"); + } + } + else + abort (); +} + +/* Return the value of a code used in the .proc pseudo-op that says + what kind of result this function returns. For non-C types, we pick + the closest C type. */ + +#ifndef CHAR_TYPE_SIZE +#define CHAR_TYPE_SIZE BITS_PER_UNIT +#endif + +#ifndef SHORT_TYPE_SIZE +#define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2) +#endif + +#ifndef INT_TYPE_SIZE +#define INT_TYPE_SIZE BITS_PER_WORD +#endif + +#ifndef LONG_TYPE_SIZE +#define LONG_TYPE_SIZE BITS_PER_WORD +#endif + +#ifndef LONG_LONG_TYPE_SIZE +#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2) +#endif + +#ifndef FLOAT_TYPE_SIZE +#define FLOAT_TYPE_SIZE BITS_PER_WORD +#endif + +#ifndef DOUBLE_TYPE_SIZE +#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) +#endif + +#ifndef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) +#endif + +unsigned long +sparc_type_code (type) + register tree type; +{ + register unsigned long qualifiers = 0; + register unsigned shift; + + /* Only the first 30 bits of the qualifier are valid. We must refrain from + setting more, since some assemblers will give an error for this. Also, + we must be careful to avoid shifts of 32 bits or more to avoid getting + unpredictable results. */ + + for (shift = 6; shift < 30; shift += 2, type = TREE_TYPE (type)) + { + switch (TREE_CODE (type)) + { + case ERROR_MARK: + return qualifiers; + + case ARRAY_TYPE: + qualifiers |= (3 << shift); + break; + + case FUNCTION_TYPE: + case METHOD_TYPE: + qualifiers |= (2 << shift); + break; + + case POINTER_TYPE: + case REFERENCE_TYPE: + case OFFSET_TYPE: + qualifiers |= (1 << shift); + break; + + case RECORD_TYPE: + return (qualifiers | 8); + + case UNION_TYPE: + case QUAL_UNION_TYPE: + return (qualifiers | 9); + + case ENUMERAL_TYPE: + return (qualifiers | 10); + + case VOID_TYPE: + return (qualifiers | 16); + + case INTEGER_TYPE: + /* If this is a range type, consider it to be the underlying + type. */ + if (TREE_TYPE (type) != 0) + break; + + /* Carefully distinguish all the standard types of C, + without messing up if the language is not C. We do this by + testing TYPE_PRECISION and TREE_UNSIGNED. The old code used to + look at both the names and the above fields, but that's redundant. + Any type whose size is between two C types will be considered + to be the wider of the two types. Also, we do not have a + special code to use for "long long", so anything wider than + long is treated the same. Note that we can't distinguish + between "int" and "long" in this code if they are the same + size, but that's fine, since neither can the assembler. */ + + if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE) + return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2)); + + else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE) + return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3)); + + else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE) + return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4)); + + else + return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5)); + + case REAL_TYPE: + /* If this is a range type, consider it to be the underlying + type. */ + if (TREE_TYPE (type) != 0) + break; + + /* Carefully distinguish all the standard types of C, + without messing up if the language is not C. */ + + if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE) + return (qualifiers | 6); + + else + return (qualifiers | 7); + + case COMPLEX_TYPE: /* GNU Fortran COMPLEX type. */ + /* ??? We need to distinguish between double and float complex types, + but I don't know how yet because I can't reach this code from + existing front-ends. */ + return (qualifiers | 7); /* Who knows? */ + + case CHAR_TYPE: /* GNU Pascal CHAR type. Not used in C. */ + case BOOLEAN_TYPE: /* GNU Fortran BOOLEAN type. */ + case FILE_TYPE: /* GNU Pascal FILE type. */ + case SET_TYPE: /* GNU Pascal SET type. */ + case LANG_TYPE: /* ? */ + return qualifiers; + + default: + abort (); /* Not a type! */ + } + } + + return qualifiers; +} + +/* Nested function support. */ + +/* 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. + + This takes 16 insns: 2 shifts & 2 ands (to split up addresses), 4 sethi + (to load in opcodes), 4 iors (to merge address and opcodes), and 4 writes + (to store insns). This is a bit excessive. Perhaps a different + mechanism would be better here. + + Emit enough FLUSH insns to synchronize the data and instruction caches. */ + +void +sparc_initialize_trampoline (tramp, fnaddr, cxt) + rtx 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 i,r = 00rr rrr1 00ii iiii iiii iiii iiii iiii + JMPL r+i,d = 10dd ddd1 1100 0rrr rr1i iiii iiii iiii + */ + + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 0)), + expand_binop (SImode, ior_optab, + expand_shift (RSHIFT_EXPR, SImode, fnaddr, + size_int (10), 0, 1), + GEN_INT (0x03000000), + NULL_RTX, 1, OPTAB_DIRECT)); + + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 4)), + expand_binop (SImode, ior_optab, + expand_shift (RSHIFT_EXPR, SImode, cxt, + size_int (10), 0, 1), + GEN_INT (0x05000000), + NULL_RTX, 1, OPTAB_DIRECT)); + + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 8)), + expand_binop (SImode, ior_optab, + expand_and (fnaddr, GEN_INT (0x3ff), NULL_RTX), + GEN_INT (0x81c06000), + NULL_RTX, 1, OPTAB_DIRECT)); + + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 12)), + expand_binop (SImode, ior_optab, + expand_and (cxt, GEN_INT (0x3ff), NULL_RTX), + GEN_INT (0x8410a000), + NULL_RTX, 1, OPTAB_DIRECT)); + + emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp)))); + /* On UltraSPARC a flush flushes an entire cache line. The trampoline is + aligned on a 16 byte boundary so one flush clears it all. */ + if (sparc_cpu != PROCESSOR_ULTRASPARC) + emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, + plus_constant (tramp, 8))))); +} + +/* The 64 bit version is simpler because it makes more sense to load the + values as "immediate" data out of the trampoline. It's also easier since + we can read the PC without clobbering a register. */ + +void +sparc64_initialize_trampoline (tramp, fnaddr, cxt) + rtx tramp, fnaddr, cxt; +{ + /* + rd %pc,%g1 + ldx [%g1+24],%g5 + jmp %g5 + ldx [%g1+16],%g5 + +16 bytes data + */ + + emit_move_insn (gen_rtx_MEM (SImode, tramp), + GEN_INT (0x83414000)); + 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)); + 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_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))))); +} + +/* Subroutines to support a flat (single) register window calling + convention. */ + +/* Single-register window sparc stack frames look like: + + Before call After call + +-----------------------+ +-----------------------+ + high | | | | + mem | caller's temps. | | caller's temps. | + | | | | + +-----------------------+ +-----------------------+ + | | | | + | arguments on stack. | | arguments on stack. | + | | | | + +-----------------------+FP+92->+-----------------------+ + | 6 words to save | | 6 words to save | + | arguments passed | | arguments passed | + | in registers, even | | in registers, even | + | if not passed. | | if not passed. | + SP+68->+-----------------------+FP+68->+-----------------------+ + | 1 word struct addr | | 1 word struct addr | + +-----------------------+FP+64->+-----------------------+ + | | | | + | 16 word reg save area | | 16 word reg save area | + | | | | + SP->+-----------------------+ FP->+-----------------------+ + | 4 word area for | + | fp/alu reg moves | + FP-16->+-----------------------+ + | | + | local variables | + | | + +-----------------------+ + | | + | fp register save | + | | + +-----------------------+ + | | + | gp register save | + | | + +-----------------------+ + | | + | alloca allocations | + | | + +-----------------------+ + | | + | arguments on stack | + | | + SP+92->+-----------------------+ + | 6 words to save | + | arguments passed | + | in registers, even | + low | if not passed. | + memory SP+68->+-----------------------+ + | 1 word struct addr | + SP+64->+-----------------------+ + | | + I 16 word reg save area | + | | + SP->+-----------------------+ */ + +/* Structure to be filled in by sparc_flat_compute_frame_size with register + save masks, and offsets for the current function. */ + +struct sparc_frame_info +{ + unsigned long total_size; /* # bytes that the entire frame takes up. */ + unsigned long var_size; /* # bytes that variables take up. */ + unsigned long args_size; /* # bytes that outgoing arguments take up. */ + unsigned long extra_size; /* # bytes of extra gunk. */ + unsigned int gp_reg_size; /* # bytes needed to store gp regs. */ + unsigned int fp_reg_size; /* # bytes needed to store fp regs. */ + unsigned long gmask; /* Mask of saved gp registers. */ + unsigned long fmask; /* Mask of saved fp registers. */ + unsigned long reg_offset; /* Offset from new sp to store regs. */ + int initialized; /* Nonzero if frame size already calculated. */ +}; + +/* Current frame information calculated by sparc_flat_compute_frame_size. */ +struct sparc_frame_info current_frame_info; + +/* Zero structure to initialize current_frame_info. */ +struct sparc_frame_info zero_frame_info; + +/* Tell prologue and epilogue if register REGNO should be saved / restored. */ + +#define RETURN_ADDR_REGNUM 15 +#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) +#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) + +#define MUST_SAVE_REGISTER(regno) \ + ((regs_ever_live[regno] && !call_used_regs[regno]) \ + || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \ + || (regno == RETURN_ADDR_REGNUM && regs_ever_live[RETURN_ADDR_REGNUM])) + +/* Return the bytes needed to compute the frame pointer from the current + stack pointer. */ + +unsigned long +sparc_flat_compute_frame_size (size) + int size; /* # of var. bytes allocated. */ +{ + int regno; + unsigned long total_size; /* # bytes that the entire frame takes up. */ + unsigned long var_size; /* # bytes that variables take up. */ + unsigned long args_size; /* # bytes that outgoing arguments take up. */ + unsigned long extra_size; /* # extra bytes. */ + unsigned int gp_reg_size; /* # bytes needed to store gp regs. */ + unsigned int fp_reg_size; /* # bytes needed to store fp regs. */ + unsigned long gmask; /* Mask of saved gp registers. */ + unsigned long fmask; /* Mask of saved fp registers. */ + unsigned long reg_offset; /* Offset to register save area. */ + int need_aligned_p; /* 1 if need the save area 8 byte aligned. */ + + /* 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; + need_aligned_p = 0; + + /* Calculate space needed for gp registers. */ + for (regno = 1; regno <= 31; regno++) + { + if (MUST_SAVE_REGISTER (regno)) + { + /* If we need to save two regs in a row, ensure there's room to bump + up the address to align it to a doubleword boundary. */ + if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1)) + { + if (gp_reg_size % 8 != 0) + gp_reg_size += 4; + gp_reg_size += 2 * UNITS_PER_WORD; + gmask |= 3 << regno; + regno++; + need_aligned_p = 1; + } + else + { + gp_reg_size += UNITS_PER_WORD; + gmask |= 1 << regno; + } + } + } + + /* Calculate space needed for fp registers. */ + for (regno = 32; regno <= 63; regno++) + { + if (regs_ever_live[regno] && !call_used_regs[regno]) + { + fp_reg_size += UNITS_PER_WORD; + fmask |= 1 << (regno - 32); + } + } + + if (gmask || fmask) + { + int n; + reg_offset = FIRST_PARM_OFFSET(0) + args_size; + /* Ensure save area is 8 byte aligned if we need it. */ + n = reg_offset % 8; + if (need_aligned_p && n != 0) + { + total_size += 8 - n; + reg_offset += 8 - n; + } + total_size += gp_reg_size + fp_reg_size; + } + + /* ??? This looks a little suspicious. Clarify. */ + if (total_size == extra_size) + total_size = extra_size = 0; + + total_size = SPARC_STACK_ALIGN (total_size); + + /* Save other computed information. */ + current_frame_info.total_size = total_size; + current_frame_info.var_size = var_size; + current_frame_info.args_size = args_size; + current_frame_info.extra_size = extra_size; + current_frame_info.gp_reg_size = gp_reg_size; + current_frame_info.fp_reg_size = fp_reg_size; + current_frame_info.gmask = gmask; + current_frame_info.fmask = fmask; + current_frame_info.reg_offset = reg_offset; + current_frame_info.initialized = reload_completed; + + /* Ok, we're done. */ + return total_size; +} + +/* Save/restore registers in GMASK and FMASK at register BASE_REG plus offset + OFFSET. + + BASE_REG must be 8 byte aligned. This allows us to test OFFSET for + appropriate alignment and use DOUBLEWORD_OP when we can. We assume + [BASE_REG+OFFSET] will always be a valid address. + + WORD_OP is either "st" for save, "ld" for restore. + DOUBLEWORD_OP is either "std" for save, "ldd" for restore. */ + +void +sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, + doubleword_op, base_offset) + FILE *file; + char *base_reg; + unsigned int offset; + unsigned long gmask; + unsigned long fmask; + char *word_op; + char *doubleword_op; + unsigned long base_offset; +{ + int regno; + + if (gmask == 0 && fmask == 0) + return; + + /* Save registers starting from high to low. We've already saved the + previous frame pointer and previous return address for the debugger's + sake. The debugger allows us to not need a nop in the epilog if at least + one register is reloaded in addition to return address. */ + + if (gmask) + { + for (regno = 1; regno <= 31; regno++) + { + if ((gmask & (1L << regno)) != 0) + { + if ((regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0)) + { + /* We can save two registers in a row. If we're not at a + double word boundary, move to one. + sparc_flat_compute_frame_size ensures there's room to do + this. */ + if (offset % 8 != 0) + offset += UNITS_PER_WORD; + + if (word_op[0] == 's') + { + fprintf (file, "\t%s %s,[%s+%d]\n", + doubleword_op, reg_names[regno], + base_reg, offset); + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + dwarf2out_reg_save (l, regno, offset + base_offset); + dwarf2out_reg_save + (l, regno+1, offset+base_offset + UNITS_PER_WORD); + } + } + else + fprintf (file, "\t%s [%s+%d],%s\n", + doubleword_op, base_reg, offset, + reg_names[regno]); + + offset += 2 * UNITS_PER_WORD; + regno++; + } + else + { + if (word_op[0] == 's') + { + fprintf (file, "\t%s %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", + word_op, base_reg, offset, reg_names[regno]); + + offset += UNITS_PER_WORD; + } + } + } + } + + if (fmask) + { + for (regno = 32; regno <= 63; regno++) + { + if ((fmask & (1L << (regno - 32))) != 0) + { + if (word_op[0] == 's') + { + fprintf (file, "\t%s %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", + word_op, base_reg, offset, reg_names[regno]); + + offset += UNITS_PER_WORD; + } + } + } +} + +/* Set up the stack and frame (if desired) for the function. */ + +void +sparc_flat_output_function_prologue (file, size) + FILE *file; + int size; +{ + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + unsigned long gmask = current_frame_info.gmask; + + /* This is only for the human reader. */ + fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START); + fprintf (file, "\t%s# vars= %ld, regs= %d/%d, args= %d, extra= %ld\n", + ASM_COMMENT_START, + current_frame_info.var_size, + current_frame_info.gp_reg_size / 4, + current_frame_info.fp_reg_size / 4, + current_function_outgoing_args_size, + current_frame_info.extra_size); + + size = SPARC_STACK_ALIGN (size); + size = (! current_frame_info.initialized + ? sparc_flat_compute_frame_size (size) + : current_frame_info.total_size); + + /* These cases shouldn't happen. Catch them now. */ + if (size == 0 && (gmask || current_frame_info.fmask)) + abort (); + + /* Allocate our stack frame by decrementing %sp. + At present, the only algorithm gdb can use to determine if this is a + flat frame is if we always set %i7 if we set %sp. This can be optimized + in the future by putting in some sort of debugging information that says + this is a `flat' function. However, there is still the case of debugging + code without such debugging information (including cases where most fns + have such info, but there is one that doesn't). So, always do this now + so we don't get a lot of code out there that gdb can't handle. + If the frame pointer isn't needn't then that's ok - gdb won't be able to + distinguish us from a non-flat function but there won't (and shouldn't) + be any differences anyway. The return pc is saved (if necessary) right + after %i7 so gdb won't have to look too far to find it. */ + if (size > 0) + { + unsigned int reg_offset = current_frame_info.reg_offset; + char *fp_str = reg_names[FRAME_POINTER_REGNUM]; + 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 + happens, the register save area can't be accessed from either end of + the frame. Handle this by decrementing %sp to the start of the gp + register save area, save the regs, update %i7, and then set %sp to its + final value. Given that we only have one scratch register to play + with it is the cheapest solution, and it helps gdb out as it won't + slow down recognition of flat functions. + Don't change the order of insns emitted here without checking with + the gdb folk first. */ + + /* Is the entire register save area offsettable from %sp? */ + if (reg_offset < 4096 - 64 * UNITS_PER_WORD) + { + if (size <= 4096) + { + fprintf (file, "\tadd %s,%d,%s\n", + sp_str, -size, sp_str); + if (gmask & FRAME_POINTER_MASK) + { + fprintf (file, "\tst %s,[%s+%d]\n", + fp_str, sp_str, reg_offset); + fprintf (file, "\tsub %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", + size, t1_str, sp_str, t1_str, sp_str); + if (gmask & FRAME_POINTER_MASK) + { + fprintf (file, "\tst %s,[%s+%d]\n", + fp_str, sp_str, reg_offset); + fprintf (file, "\tadd %s,%s,%s\t%s# set up frame pointer\n", + sp_str, t1_str, fp_str, ASM_COMMENT_START); + reg_offset += 4; + } + } + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + if (gmask & FRAME_POINTER_MASK) + { + dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, + reg_offset - 4 - size); + dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, 0); + } + else + dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size); + } + if (gmask & RETURN_ADDR_MASK) + { + fprintf (file, "\tst %s,[%s+%d]\n", + reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset); + if (dwarf2out_do_frame ()) + dwarf2out_return_save ("", reg_offset - size); + reg_offset += 4; + } + sparc_flat_save_restore (file, sp_str, reg_offset, + gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), + current_frame_info.fmask, + "st", "std", -size); + } + else + { + /* Subtract %sp in two steps, but make sure there is always a + 64 byte register save area, and %sp is properly aligned. */ + /* Amount to decrement %sp by, the first time. */ + unsigned int size1 = ((size - reg_offset + 64) + 15) & -16; + /* Offset to register save area from %sp. */ + unsigned int offset = size1 - (size - reg_offset); + + if (size1 <= 4096) + { + fprintf (file, "\tadd %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", + fp_str, sp_str, offset, sp_str, -size1, fp_str, + ASM_COMMENT_START); + offset += 4; + } + } + else + { + fprintf (file, "\tset %d,%s\n\tsub %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", + fp_str, sp_str, offset, sp_str, t1_str, fp_str, + ASM_COMMENT_START); + offset += 4; + } + } + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + if (gmask & FRAME_POINTER_MASK) + { + dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, + offset - 4 - size1); + dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, 0); + } + else + dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1); + } + if (gmask & RETURN_ADDR_MASK) + { + fprintf (file, "\tst %s,[%s+%d]\n", + reg_names[RETURN_ADDR_REGNUM], sp_str, offset); + if (dwarf2out_do_frame ()) + /* offset - size1 == reg_offset - size + if reg_offset were updated above like offset. */ + dwarf2out_return_save ("", offset - size1); + offset += 4; + } + sparc_flat_save_restore (file, sp_str, offset, + 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", + size - size1, t1_str, sp_str, t1_str, sp_str); + if (dwarf2out_do_frame ()) + if (! (gmask & FRAME_POINTER_MASK)) + dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size); + } + } + + fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START); +} + +/* Do any necessary cleanup after a function to restore stack, frame, + and regs. */ + +void +sparc_flat_output_function_epilogue (file, size) + FILE *file; + int size; +{ + rtx epilogue_delay = current_function_epilogue_delay_list; + int noepilogue = FALSE; + + /* This is only for the human reader. */ + fprintf (file, "\t%s#EPILOGUE#\n", ASM_COMMENT_START); + + /* The epilogue does not depend on any registers, but the stack + registers, so we assume that if we have 1 pending nop, it can be + ignored, and 2 it must be filled (2 nops occur for integer + multiply and divide). */ + + size = SPARC_STACK_ALIGN (size); + size = (!current_frame_info.initialized + ? sparc_flat_compute_frame_size (size) + : current_frame_info.total_size); + + if (size == 0 && epilogue_delay == 0) + { + rtx insn = get_last_insn (); + + /* If the last insn was a BARRIER, we don't have to write any code + because a jump (aka return) was put there. */ + if (GET_CODE (insn) == NOTE) + insn = prev_nonnote_insn (insn); + if (insn && GET_CODE (insn) == BARRIER) + noepilogue = TRUE; + } + + if (!noepilogue) + { + unsigned int reg_offset = current_frame_info.reg_offset; + unsigned int size1; + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + char *fp_str = reg_names[FRAME_POINTER_REGNUM]; + 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); + + if (frame_pointer_needed) + { + if (size > 4095) + fprintf (file,"\tsub %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", + fp_str, size, sp_str, ASM_COMMENT_START); + } + + /* Is the entire register save area offsettable from %sp? */ + if (reg_offset < 4096 - 64 * UNITS_PER_WORD) + { + size1 = 0; + } + else + { + /* Restore %sp in two steps, but make sure there is always a + 64 byte register save area, and %sp is properly aligned. */ + /* Amount to increment %sp by, the first time. */ + size1 = ((reg_offset - 64 - 16) + 15) & -16; + /* Offset to register save area from %sp. */ + reg_offset = size1 - reg_offset; + + fprintf (file, "\tset %d,%s\n\tadd %s,%s,%s\n", + size1, t1_str, sp_str, t1_str, sp_str); + } + + /* We must restore the frame pointer and return address reg first + 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", + sp_str, reg_offset, fp_str); + reg_offset += 4; + } + if (current_frame_info.gmask & RETURN_ADDR_MASK) + { + fprintf (file, "\tld [%s+%d],%s\n", + sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]); + reg_offset += 4; + } + + /* Restore any remaining saved registers. */ + sparc_flat_save_restore (file, sp_str, reg_offset, + current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), + current_frame_info.fmask, + "ld", "ldd", 0); + + /* If we had to increment %sp in two steps, record it so the second + restoration in the epilogue finishes up. */ + if (size1 > 0) + { + size -= size1; + if (size > 4095) + fprintf (file, "\tset %d,%s\n", + size, t1_str); + } + + if (current_function_returns_struct) + fprintf (file, "\tjmp %%o7+12\n"); + else + fprintf (file, "\tretl\n"); + + /* If the only register saved is the return address, we need a + nop, unless we have an instruction to put into it. Otherwise + we don't since reloading multiple registers doesn't reference + the register being loaded. */ + + if (epilogue_delay) + { + if (size) + abort (); + final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); + } + + else if (size > 4095) + fprintf (file, "\tadd %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); + + else + fprintf (file, "\tnop\n"); + } + + /* Reset state info for each function. */ + current_frame_info = zero_frame_info; +} + +/* Define the number of delay slots needed for the function epilogue. + + On the sparc, we need a slot if either no stack has been allocated, + or the only register saved is the return register. */ + +int +sparc_flat_epilogue_delay_slots () +{ + if (!current_frame_info.initialized) + (void) sparc_flat_compute_frame_size (get_frame_size ()); + + if (current_frame_info.total_size == 0) + return 1; + + return 0; +} + +/* Return true is TRIAL is a valid insn for the epilogue delay slot. + Any single length instruction which doesn't reference the stack or frame + pointer is OK. */ + +int +sparc_flat_eligible_for_epilogue_delay (trial, slot) + rtx trial; + int slot ATTRIBUTE_UNUSED; +{ + rtx pat = PATTERN (trial); + + if (get_attr_length (trial) != 1) + return 0; + + /* If %g0 is live, there are lots of things we can't handle. + Rather than trying to find them all now, let's punt and only + optimize things as necessary. */ + if (TARGET_LIVE_G0) + return 0; + + if (! reg_mentioned_p (stack_pointer_rtx, pat) + && ! reg_mentioned_p (frame_pointer_rtx, pat)) + return 1; + + return 0; +} + +/* 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 +supersparc_adjust_cost (insn, link, dep_insn, cost) + rtx insn; + rtx link; + rtx dep_insn; + int cost; +{ + enum attr_type insn_type; + + if (! recog_memoized (insn)) + return 0; + + insn_type = get_attr_type (insn); + + if (REG_NOTE_KIND (link) == 0) + { + /* Data dependency; DEP_INSN writes a register that INSN reads some + 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 + here. */ + if (insn_type == TYPE_LOAD || insn_type == TYPE_FPLOAD) + return cost + 3; + + /* Get the delay only if the address of the store is the dependence. */ + if (insn_type == TYPE_STORE || insn_type == TYPE_FPSTORE) + { + rtx pat = PATTERN(insn); + rtx dep_pat = PATTERN (dep_insn); + + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) + return cost; /* This shouldn't happen! */ + + /* The dependency between the two instructions was on the data that + is being stored. Assume that this implies that the address of the + store is not dependent. */ + if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) + return cost; + + return cost + 3; /* An approximation. */ + } + + /* A shift instruction cannot receive its data from an instruction + in the same cycle; add a one cycle penalty. */ + if (insn_type == TYPE_SHIFT) + return cost + 3; /* Split before cascade into shift. */ + } + else + { + /* Anti- or output- dependency; DEP_INSN reads/writes a register that + INSN writes some cycles later. */ + + /* These are only significant for the fpu unit; writing a fp reg before + the fpu has finished with it stalls the processor. */ + + /* Reusing an integer register causes no problems. */ + if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT) + return 0; + } + + return cost; +} + +int +ultrasparc_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); + +#define SLOW_FP(dep_type) \ +(dep_type == TYPE_FPSQRT || dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD) + + switch (REG_NOTE_KIND (link)) + { + case 0: + /* Data dependency; DEP_INSN writes a register that INSN reads some + cycles later. */ + + switch (insn_type) + { + /* 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; + return cost; + + case TYPE_STORE: + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) + 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 + 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. */ + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET + || GET_CODE (SET_SRC (pat)) != MEM + || GET_CODE (SET_DEST (dep_pat)) != MEM + || ! rtx_equal_p (XEXP (SET_SRC (pat), 0), + XEXP (SET_DEST (dep_pat), 0))) + return cost + 2; + + return cost + 8; + } + return cost; + + 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; + return cost; + + 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. */ + if ((dep_type == TYPE_IALU || dep_type == TYPE_UNARY + || dep_type == TYPE_BINARY) + && cost < 2) + return 2; + /* Otherwise check as for integer conditional moves. */ + + 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; + return cost; + + default: + break; + } + break; + + case REG_DEP_ANTI: + /* Divide and square root lock destination registers for full latency. */ + if (! SLOW_FP (dep_type)) + return 0; + break; + + 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. + - 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. + - 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; +} + +int +sparc_issue_rate () +{ + switch (sparc_cpu) + { + default: + return 1; + case PROCESSOR_V9: + /* Assume V9 processors are capable of at least dual-issue. */ + return 2; + case PROCESSOR_SUPERSPARC: + return 3; + case PROCESSOR_ULTRASPARC: + return 4; + } +} + +static int +set_extends(x, insn) + rtx x, insn; +{ + register rtx pat = PATTERN (insn); + + switch (GET_CODE (SET_SRC (pat))) + { + /* Load and some shift instructions zero extend. */ + case MEM: + case ZERO_EXTEND: + /* sethi clears the high bits */ + case HIGH: + /* 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: + case LE: case LEU: + case GE: case GEU: + case EQ: + case NE: + return 1; + case AND: + { + rtx op1 = XEXP (SET_SRC (pat), 1); + if (GET_CODE (op1) == CONST_INT) + return INTVAL (op1) >= 0; + if (GET_CODE (XEXP (SET_SRC (pat), 0)) == REG + && sparc_check_64 (XEXP (SET_SRC (pat), 0), insn) == 1) + return 1; + if (GET_CODE (op1) == REG + && sparc_check_64 ((op1), insn) == 1) + return 1; + } + case ASHIFT: + case LSHIFTRT: + return GET_MODE (SET_SRC (pat)) == SImode; + /* Positive integers leave the high bits zero. */ + case CONST_DOUBLE: + return ! (CONST_DOUBLE_LOW (x) & 0x80000000); + case CONST_INT: + return ! (INTVAL (x) & 0x80000000); + case ASHIFTRT: + case SIGN_EXTEND: + return - (GET_MODE (SET_SRC (pat)) == SImode); + default: + return 0; + } +} + +/* 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. */ +int +sparc_check_64 (x, insn) + rtx x, insn; +{ + /* If a register is set only once it is safe to ignore insns this + code does not know how to handle. The loop will either recognize + the single set and return the correct value or fail to recognize + it and return 0. */ + int set_once = 0; + + if (GET_CODE (x) == REG + && flag_expensive_optimizations + && REG_N_SETS (REGNO (x)) == 1) + set_once = 1; + + if (insn == 0) + { + if (set_once) + insn = get_last_insn_anywhere (); + else + return 0; + } + + while ((insn = PREV_INSN (insn))) + { + switch (GET_CODE (insn)) + { + case JUMP_INSN: + case NOTE: + break; + case CODE_LABEL: + case CALL_INSN: + default: + if (! set_once) + return 0; + break; + case INSN: + { + rtx pat = PATTERN (insn); + if (GET_CODE (pat) != SET) + return 0; + if (rtx_equal_p (x, SET_DEST (pat))) + return set_extends (x, insn); + if (reg_overlap_mentioned_p (SET_DEST (pat), x)) + return 0; + } + } + } + return 0; +} + +char * +sparc_v8plus_shift (operands, insn, opcode) + rtx *operands; + rtx insn; + char *opcode; +{ + static char asm_code[60]; + + if (GET_CODE (operands[3]) == SCRATCH) + operands[3] = operands[0]; + if (GET_CODE (operands[1]) == CONST_INT) + { + output_asm_insn ("mov %1,%3", operands); + } + else + { + output_asm_insn ("sllx %H1,32,%3", operands); + if (sparc_check_64 (operands[1], insn) <= 0) + output_asm_insn ("srl %L1,0,%L1", operands); + output_asm_insn ("or %L1,%3,%3", operands); + } + + strcpy(asm_code, opcode); + if (which_alternative != 2) + return strcat (asm_code, " %0,%2,%L0\n\tsrlx %L0,32,%H0"); + else + return strcat (asm_code, " %3,%2,%3\n\tsrlx %3,32,%H0\n\tmov %3,%L0"); +} + + +/* Return 1 if DEST and SRC reference only global and in registers. */ + +int +sparc_return_peephole_ok (dest, src) + rtx dest, src; +{ + if (! TARGET_V9) + return 0; + if (leaf_function) + 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); +} diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h new file mode 100644 index 0000000..e66f5e6 --- /dev/null +++ b/contrib/gcc/config/sparc/sparc.h @@ -0,0 +1,3287 @@ +/* Definitions of target machine for GNU compiler, for Sun SPARC. + Copyright (C) 1987, 88, 89, 92, 94-97, 1998 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. + +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. */ + +/* Note that some other tm.h files include this one and then override + whatever definitions are necessary. */ + +/* Specify this in a cover file to provide bi-architecture (32/64) support. */ +/* #define SPARC_BI_ARCH */ + +/* Macro used later in this file to determine default architecture. */ +#define DEFAULT_ARCH32_P ((TARGET_DEFAULT & MASK_64BIT) == 0) + +/* TARGET_ARCH{32,64} are the main macros to decide which of the two + architectures to compile for. We allow targets to choose compile time or + runtime selection. */ +#ifdef SPARC_BI_ARCH +#define TARGET_ARCH32 (! TARGET_64BIT) +#else +#define TARGET_ARCH32 (DEFAULT_ARCH32_P) +#endif +#define TARGET_ARCH64 (! TARGET_ARCH32) + +/* Code model selection. + -mcmodel is used to select the v9 code model. + Different code models aren't supported for v8 code. + + TARGET_CM_32: 32 bit address space, top 32 bits = 0, + pointers are 32 bits. Note that this isn't intended + to imply a v8 abi. + + TARGET_CM_MEDLOW: 32 bit address space, top 32 bits = 0, + avoid generating %uhi and %ulo terms, + pointers are 64 bits. + + 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. + + TARGET_CM_MEDANY: 64 bit address space. + 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. + + TARGET_CM_EMBMEDANY: 64 bit address space. + The text and data segments have a maximum size of 31 bits + and may be located anywhere. Register %g4 contains + the start address of the data segment. +*/ + +enum cmodel { + CM_32, + CM_MEDLOW, + CM_MEDMID, + CM_MEDANY, + CM_EMBMEDANY +}; + +/* Value of -mcmodel specified by user. */ +extern char *sparc_cmodel_string; +/* One of CM_FOO. */ +extern enum cmodel sparc_cmodel; + +/* V9 code model selection. */ +#define TARGET_CM_MEDLOW (sparc_cmodel == CM_MEDLOW) +#define TARGET_CM_MEDMID (sparc_cmodel == CM_MEDMID) +#define TARGET_CM_MEDANY (sparc_cmodel == CM_MEDANY) +#define TARGET_CM_EMBMEDANY (sparc_cmodel == CM_EMBMEDANY) + +#define SPARC_DEFAULT_CMODEL CM_MEDLOW + +/* This is call-clobbered in the normal ABI, but is reserved in the + home grown (aka upward compatible) embedded ABI. */ +#define EMBMEDANY_BASE_REG "%g4" + +/* 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. */ +#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 + +#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__" +/* ??? 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" +#endif +#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc +#define CPP_CPU_DEFAULT_SPEC "-D__sparc_v9__" +#define ASM_CPU_DEFAULT_SPEC "-Av9a" +#endif +#ifndef CPP_CPU_DEFAULT_SPEC +Unrecognized value in TARGET_CPU_DEFAULT. +#endif + +/* 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 + CPP_PREFINES. Also, -D values in CPP_SUBTARGET_SPEC don't get turned into + foo, __foo and __foo__. */ + +#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix -Asystem(unix) -Asystem(bsd)" + +/* Define macros to distinguish architectures. */ + +/* Common CPP definitions used by CPP_SPEC amongst the various targets + for handling -mcpu=xxx switches. */ +#define CPP_CPU_SPEC "\ +%{mcypress:} \ +%{msparclite:-D__sparclite__} \ +%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \ +%{mv8:-D__sparc_v8__} \ +%{msupersparc:-D__supersparc__ -D__sparc_v8__} \ +%{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} \ +%{mcpu=sparclite:-D__sparclite__} \ +%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \ +%{mcpu=v8:-D__sparc_v8__} \ +%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \ +%{mcpu=v9:-D__sparc_v9__} \ +%{mcpu=ultrasparc:-D__sparc_v9__} \ +%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \ +" + +/* ??? The GCC_NEW_VARARGS macro is now obsolete, because gcc always uses + the right varags.h file when bootstrapping. */ +/* ??? It's not clear what value we want to use for -Acpu/machine for + sparc64 in 32 bit environments, so for now we only use `sparc64' in + 64 bit environments. */ + +#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)" +#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu(sparc64) -Amachine(sparc64)" +#define CPP_ARCH_DEFAULT_SPEC \ +(DEFAULT_ARCH32_P ? CPP_ARCH32_SPEC : CPP_ARCH64_SPEC) + +#define CPP_ARCH_SPEC "\ +%{m32:%(cpp_arch32)} \ +%{m64:%(cpp_arch64)} \ +%{!m32:%{!m64:%(cpp_arch_default)}} \ +" + +/* Macros to distinguish endianness. */ +#define CPP_ENDIAN_SPEC "%{mlittle-endian:-D__LITTLE_ENDIAN__}" + +/* Macros to distinguish the particular subtarget. */ +#define CPP_SUBTARGET_SPEC "" + +#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) %(cpp_endian) %(cpp_subtarget)" + +/* Prevent error on `-sun4' and `-target sun4' options. */ +/* This used to translate -dalign to -malign, but that is no good + because it can't turn off the usual meaning of making debugging dumps. */ +/* Translate old style -m into new style -mcpu=. + ??? Delete support for -m for 2.9. */ + +#define CC1_SPEC "\ +%{sun4:} %{target:} \ +%{mcypress:-mcpu=cypress} \ +%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \ +%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \ +" + +/* Override in target specific files. */ +#define ASM_CPU_SPEC "\ +%{mcpu=sparclet:-Asparclet} %{mcpu=tsc701:-Asparclet} \ +%{msparclite:-Asparclite} \ +%{mf930:-Asparclite} %{mf934:-Asparclite} \ +%{mcpu=sparclite:-Asparclite} \ +%{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} \ +%{mv8plus:-Av8plus} \ +%{mcpu=v9:-Av9} \ +%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \ +%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \ +" + +/* Word size selection, among other things. + This is what GAS uses. Add %(asm_arch) to ASM_SPEC to enable. */ + +#define ASM_ARCH32_SPEC "-32" +#define ASM_ARCH64_SPEC "-64" +#define ASM_ARCH_DEFAULT_SPEC \ +(DEFAULT_ARCH32_P ? ASM_ARCH32_SPEC : ASM_ARCH64_SPEC) + +#define ASM_ARCH_SPEC "\ +%{m32:%(asm_arch32)} \ +%{m64:%(asm_arch64)} \ +%{!m32:%{!m64:%(asm_arch_default)}} \ +" + +/* Special flags to the Sun-4 assembler when using pipe for input. */ + +#define ASM_SPEC "\ +%| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L} \ +%(asm_cpu) \ +" + +#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}" + +/* Provide required defaults for linker -e and -d switches. */ + +#define LINK_SPEC \ + "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \ + %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}" + +/* 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. */ + +#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 }, \ + SUBTARGET_EXTRA_SPECS + +#define SUBTARGET_EXTRA_SPECS + +#ifdef SPARC_BI_ARCH +#define NO_BUILTIN_PTRDIFF_TYPE +#define NO_BUILTIN_SIZE_TYPE +#endif +#define PTRDIFF_TYPE (TARGET_ARCH64 ? "long int" : "int") +#define SIZE_TYPE (TARGET_ARCH64 ? "long unsigned int" : "unsigned int") + +/* ??? This should be 32 bits for v9 but what can we do? */ +#define WCHAR_TYPE "short unsigned int" +#define WCHAR_TYPE_SIZE 16 +#define MAX_WCHAR_TYPE_SIZE 16 + +/* Show we can debug even without a frame pointer. */ +#define CAN_DEBUG_WITHOUT_FP + +/* To make profiling work with -f{pic,PIC}, we need to emit the profiling + code into the rtl. Also, if we are profiling, we cannot eliminate + the frame pointer (because the return address will get smashed). */ + +void sparc_override_options (); + +#define OVERRIDE_OPTIONS \ + do { \ + if (profile_flag || profile_block_flag || profile_arc_flag) \ + { \ + if (flag_pic) \ + { \ + char *pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC"; \ + warning ("%s and profiling conflict: disabling %s", \ + pic_string, pic_string); \ + flag_pic = 0; \ + } \ + flag_omit_frame_pointer = 0; \ + } \ + sparc_override_options (); \ + SUBTARGET_OVERRIDE_OPTIONS; \ + } while (0) + +/* This is meant to be redefined in the host dependent files. */ +#define SUBTARGET_OVERRIDE_OPTIONS + +/* These compiler options take an argument. We ignore -target for now. */ + +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + || !strcmp (STR, "target") || !strcmp (STR, "assert")) + +/* Print subsidiary information on the compiler version in use. */ + +#define TARGET_VERSION fprintf (stderr, " (sparc)"); + +/* Generate DBX debugging information. */ + +#define DBX_DEBUGGING_INFO + +/* Run-time compilation parameters selecting different hardware subsets. */ + +extern int target_flags; + +/* Nonzero if we should generate code to use the fpu. */ +#define MASK_FPU 1 +#define TARGET_FPU (target_flags & MASK_FPU) + +/* Nonzero if we should use FUNCTION_EPILOGUE. Otherwise, we + use fast return insns, but lose some generality. */ +#define MASK_EPILOGUE 2 +#define TARGET_EPILOGUE (target_flags & MASK_EPILOGUE) + +/* Nonzero if we should assume that double pointers might be unaligned. + This can happen when linking gcc compiled code with other compilers, + because the ABI only guarantees 4 byte alignment. */ +#define MASK_UNALIGNED_DOUBLES 4 +#define TARGET_UNALIGNED_DOUBLES (target_flags & MASK_UNALIGNED_DOUBLES) + +/* Nonzero means that we should generate code for a v8 sparc. */ +#define MASK_V8 0x8 +#define TARGET_V8 (target_flags & MASK_V8) + +/* Nonzero means that we should generate code for a sparclite. + This enables the sparclite specific instructions, but does not affect + whether FPU instructions are emitted. */ +#define MASK_SPARCLITE 0x10 +#define TARGET_SPARCLITE (target_flags & MASK_SPARCLITE) + +/* Nonzero if we're compiling for the sparclet. */ +#define MASK_SPARCLET 0x20 +#define TARGET_SPARCLET (target_flags & MASK_SPARCLET) + +/* Nonzero if we're compiling for v9 sparc. + Note that v9's can run in 32 bit mode so this doesn't necessarily mean + the word size is 64. */ +#define MASK_V9 0x40 +#define TARGET_V9 (target_flags & MASK_V9) + +/* Non-zero to generate code that uses the instructions deprecated in + the v9 architecture. This option only applies to v9 systems. */ +/* ??? This isn't user selectable yet. It's used to enable such insns + on 32 bit v9 systems and for the moment they're permanently disabled + on 64 bit v9 systems. */ +#define MASK_DEPRECATED_V8_INSNS 0x80 +#define TARGET_DEPRECATED_V8_INSNS (target_flags & MASK_DEPRECATED_V8_INSNS) + +/* Mask of all CPU selection flags. */ +#define MASK_ISA \ +(MASK_V8 + MASK_SPARCLITE + MASK_SPARCLET + MASK_V9 + MASK_DEPRECATED_V8_INSNS) + +/* Non-zero means don't pass `-assert pure-text' to the linker. */ +#define MASK_IMPURE_TEXT 0x100 +#define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT) + +/* Nonzero means that we should generate code using a flat register window + model, i.e. no save/restore instructions are generated, which is + compatible with normal sparc code. + The frame pointer is %i7 instead of %fp. */ +#define MASK_FLAT 0x200 +#define TARGET_FLAT (target_flags & MASK_FLAT) + +/* Nonzero means use the registers that the Sparc ABI reserves for + application software. This must be the default to coincide with the + setting in FIXED_REGISTERS. */ +#define MASK_APP_REGS 0x400 +#define TARGET_APP_REGS (target_flags & MASK_APP_REGS) + +/* Option to select how quad word floating point is implemented. + When TARGET_HARD_QUAD is true, we use the hardware quad instructions. + Otherwise, we use the SPARC ABI quad library functions. */ +#define MASK_HARD_QUAD 0x800 +#define TARGET_HARD_QUAD (target_flags & MASK_HARD_QUAD) + +/* Non-zero on little-endian machines. */ +/* ??? Little endian support currently only exists for sparclet-aout and + sparc64-elf configurations. May eventually want to expand the support + to all targets, but for now it's kept local to only those two. */ +#define MASK_LITTLE_ENDIAN 0x1000 +#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN) + +/* 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. */ +#define MASK_PTR64 0x8000 +#define TARGET_PTR64 (target_flags & MASK_PTR64) + +/* Nonzero if generating code to run in a 64 bit environment. + This is intended to only be used by TARGET_ARCH{32,64} as they are the + mechanism used to control compile time or run time selection. */ +#define MASK_64BIT 0x10000 +#define TARGET_64BIT (target_flags & MASK_64BIT) + +/* 0x20000,0x40000 unused */ + +/* Non-zero means use a stack bias of 2047. Stack offsets are obtained by + adding 2047 to %sp. This option is for v9 only and is the default. */ +#define MASK_STACK_BIAS 0x80000 +#define TARGET_STACK_BIAS (target_flags & MASK_STACK_BIAS) + +/* Non-zero means %g0 is a normal register. + We still clobber it as necessary, but we can't rely on it always having + a zero value. + We don't bother to support this in true 64 bit mode. */ +#define MASK_LIVE_G0 0x100000 +#define TARGET_LIVE_G0 (target_flags & MASK_LIVE_G0) + +/* Non-zero means the cpu has broken `save' and `restore' insns, only + the trivial versions work (save %g0,%g0,%g0; restore %g0,%g0,%g0). + We assume the environment will properly handle or otherwise avoid + trouble associated with an interrupt occurring after the `save' or trap + occurring during it. */ +#define MASK_BROKEN_SAVERESTORE 0x200000 +#define TARGET_BROKEN_SAVERESTORE (target_flags & MASK_BROKEN_SAVERESTORE) + +/* Non-zero means -m{,no-}fpu was passed on the command line. */ +#define MASK_FPU_SET 0x400000 +#define TARGET_FPU_SET (target_flags & MASK_FPU_SET) + +/* Use the UltraSPARC Visual Instruction Set extensions. */ +#define MASK_VIS 0x1000000 +#define TARGET_VIS (target_flags & MASK_VIS) + +/* Compile for Solaris V8+. 32 bit Solaris preserves the high bits of + the current out and global registers. Linux saves the high bits on + context switches but not signals. */ +#define MASK_V8PLUS 0x2000000 +#define TARGET_V8PLUS (target_flags & MASK_V8PLUS) + +/* TARGET_HARD_MUL: Use hardware multiply instructions but not %y. + TARGET_HARD_MUL32: Use hardware multiply instructions with rd %y + to get high 32 bits. False in V8+ or V9 because multiply stores + a 64 bit result in a register. */ + +#define TARGET_HARD_MUL32 \ + ((TARGET_V8 || TARGET_SPARCLITE \ + || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS) \ + && ! TARGET_V8PLUS) + +#define TARGET_HARD_MUL \ + (TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET \ + || TARGET_DEPRECATED_V8_INSNS || TARGET_V8PLUS) + + +/* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +#define TARGET_SWITCHES \ + { {"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}, \ + /* ??? These are deprecated, coerced to -mcpu=. Delete in 2.9. */ \ + {"cypress", 0}, \ + {"sparclite", 0}, \ + {"f930", 0}, \ + {"f934", 0}, \ + {"v8", 0}, \ + {"supersparc", 0}, \ + /* 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}, \ + SUBTARGET_SWITCHES \ + { "", TARGET_DEFAULT}} + +/* MASK_APP_REGS must always be the default because that's what + FIXED_REGISTERS is set to and -ffixed- is processed before + CONDITIONAL_REGISTER_USAGE is called (where we process -mno-app-regs). */ +#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU) + +/* This is meant to be redefined in target specific files. */ +#define SUBTARGET_SWITCHES + +/* Processor type. + These must match the values for the cpu attribute in sparc.md. */ +enum processor_type { + PROCESSOR_V7, + PROCESSOR_CYPRESS, + PROCESSOR_V8, + PROCESSOR_SUPERSPARC, + PROCESSOR_SPARCLITE, + PROCESSOR_F930, + PROCESSOR_F934, + PROCESSOR_SPARCLET, + PROCESSOR_TSC701, + PROCESSOR_V9, + PROCESSOR_ULTRASPARC +}; + +/* This is set from -m{cpu,tune}=xxx. */ +extern enum processor_type sparc_cpu; + +/* Recast the cpu class to be the cpu attribute. + Every file includes us, but not every file includes insn-attr.h. */ +#define sparc_cpu_attr ((enum attr_cpu) sparc_cpu) + +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an + initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + fixed part of the option name, and the address of a variable. + The variable, type `char *', is set to the variable part of the + given option if the fixed part matches. The actual option name + is made by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the + given option is `-mshort-data-512', the variable `m88k_short_data' + will be set to the string `"512"'. + + extern char *m88k_short_data; + #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ + +#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 }, \ + SUBTARGET_OPTIONS \ +} + +/* This is meant to be redefined in target specific files. */ +#define SUBTARGET_OPTIONS + +/* sparc_select[0] is reserved for the default cpu. */ +struct sparc_cpu_select +{ + char *string; + char *name; + int set_tune_p; + int set_arch_p; +}; + +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; +/* Parsed values as a power of two. */ +extern int sparc_align_loops; +extern int sparc_align_jumps; +extern int sparc_align_funcs; + +#define DEFAULT_SPARC_ALIGN_FUNCS \ +(sparc_cpu == PROCESSOR_ULTRASPARC ? 5 : 2) + +/* target machine storage layout */ + +/* Define for cross-compilation to a sparc target with no TFmode from a host + with a different float format (e.g. VAX). */ +#define REAL_ARITHMETIC + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. */ +#define BITS_BIG_ENDIAN 1 + +/* Define this if most significant byte of a word is the lowest numbered. */ +#define BYTES_BIG_ENDIAN 1 + +/* Define this if most significant word of a multiword number is the lowest + numbered. */ +#define WORDS_BIG_ENDIAN 1 + +/* Define this to set the endianness to use in libgcc2.c, which can + not depend on target_flags. */ +#if defined (__LITTLE_ENDIAN__) +#define LIBGCC2_WORDS_BIG_ENDIAN 0 +#else +#define LIBGCC2_WORDS_BIG_ENDIAN 1 +#endif + +/* number of bits in an addressable storage unit */ +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ +#define BITS_PER_WORD (TARGET_ARCH64 ? 64 : 32) +#define MAX_BITS_PER_WORD 64 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD (TARGET_ARCH64 ? 8 : 4) +#define MIN_UNITS_PER_WORD 4 + +/* Now define the sizes of the C data types. */ + +#define SHORT_TYPE_SIZE 16 +#define INT_TYPE_SIZE 32 +#define LONG_TYPE_SIZE (TARGET_ARCH64 ? 64 : 32) +#define LONG_LONG_TYPE_SIZE 64 +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 64 + +#if defined (SPARC_BI_ARCH) +#define MAX_LONG_TYPE_SIZE 64 +#endif + +#if 0 +/* ??? This does not work in SunOS 4.x, so it is not enabled here. + Instead, it is enabled in sol2.h, because it does work under Solaris. */ +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ +#define POINTER_SIZE (TARGET_PTR64 ? 64 : 32) + +/* A macro to update MODE and UNSIGNEDP when an object whose type + is TYPE and which has the specified mode and signedness is to be + stored in a register. This macro is only called when TYPE is a + scalar type. */ +#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ +if (TARGET_ARCH64 \ + && GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ +{ \ + (MODE) = DImode; \ +} + +/* Define this macro if the promotion described by PROMOTE_MODE + should also be done for outgoing function arguments. */ +/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op + for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test + for this value. */ +#define PROMOTE_FUNCTION_ARGS + +/* Define this macro if the promotion described by PROMOTE_MODE + should also be done for the return value of functions. + If this macro is defined, FUNCTION_VALUE must perform the same + promotions done by PROMOTE_MODE. */ +/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op + for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test + for this value. */ +#define PROMOTE_FUNCTION_RETURN + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32) + +/* Boundary (in *bits*) on which stack pointer should be aligned. */ +#define STACK_BOUNDARY (TARGET_ARCH64 ? 128 : 64) + +/* ALIGN FRAMES on double word boundaries */ + +#define SPARC_STACK_ALIGN(LOC) \ + (TARGET_ARCH64 ? (((LOC)+15) & ~15) : (((LOC)+7) & ~7)) + +/* Allocation boundary (in *bits*) for the code of a function. */ +#define FUNCTION_BOUNDARY (1 << (sparc_align_funcs + 3)) + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY (TARGET_ARCH64 ? 64 : 32) + +/* Every structure's size must be a multiple of this. */ +#define STRUCTURE_SIZE_BOUNDARY 8 + +/* A bitfield declared as `int' forces `int' alignment for the struct. */ +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* No data type wants to be aligned rounder than this. */ +#define BIGGEST_ALIGNMENT (TARGET_ARCH64 ? 128 : 64) + +/* The best alignment to use in cases where we have a choice. */ +#define FASTEST_ALIGNMENT 64 + +/* Make strings word-aligned so strcpy from constants will be faster. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST \ + && (ALIGN) < FASTEST_ALIGNMENT) \ + ? FASTEST_ALIGNMENT : (ALIGN)) + +/* Make arrays of chars word-aligned for the same reasons. */ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + (TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN)) + +/* Set this nonzero if move instructions will actually fail to work + when given unaligned data. */ +#define STRICT_ALIGNMENT 1 + +/* Things that must be doubleword aligned cannot go in the text section, + because the linker fails to align the text section enough! + Put them in the data section. This macro is only used in this file. */ +#define MAX_TEXT_ALIGN 32 + +/* This forces all variables and constants to the data section when PIC. + This is because the SunOS 4 shared library scheme thinks everything in + text is a function, and patches the address to point to a loader stub. */ +/* This is defined to zero for every system which doesn't use the a.out object + file format. */ +#ifndef SUNOS4_SHARED_LIBRARIES +#define SUNOS4_SHARED_LIBRARIES 0 +#endif + +/* This is defined differently for v9 in a cover file. */ +#define SELECT_SECTION(T,RELOC) \ +{ \ + if (TREE_CODE (T) == VAR_DECL) \ + { \ + if (TREE_READONLY (T) && ! TREE_SIDE_EFFECTS (T) \ + && DECL_INITIAL (T) \ + && (DECL_INITIAL (T) == error_mark_node \ + || TREE_CONSTANT (DECL_INITIAL (T))) \ + && DECL_ALIGN (T) <= MAX_TEXT_ALIGN \ + && ! (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \ + text_section (); \ + else \ + data_section (); \ + } \ + else if (TREE_CODE (T) == CONSTRUCTOR) \ + { \ + if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)) \ + data_section (); \ + } \ + else if (TREE_CODE_CLASS (TREE_CODE (T)) == 'c') \ + { \ + if ((TREE_CODE (T) == STRING_CST && flag_writable_strings) \ + || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN \ + || (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \ + data_section (); \ + else \ + text_section (); \ + } \ +} + +/* Use text section for a constant + unless we need more alignment than that offers. */ +/* This is defined differently for v9 in a cover file. */ +#define SELECT_RTX_SECTION(MODE, X) \ +{ \ + if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN \ + && ! (flag_pic && (symbolic_operand (X) || SUNOS4_SHARED_LIBRARIES))) \ + text_section (); \ + else \ + data_section (); \ +} + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. + + SPARC has 32 integer registers and 32 floating point registers. + 64 bit SPARC has 32 additional fp regs, but the odd numbered ones are not + accessible. We still account for them to simplify register computations + (eg: in CLASS_MAX_NREGS). There are also 4 fp condition code registers, so + 32+32+32+4 == 100. + Register 100 is used as the integer condition code register. */ + +#define FIRST_PSEUDO_REGISTER 101 + +#define SPARC_FIRST_FP_REG 32 +/* Additional V9 fp regs. */ +#define SPARC_FIRST_V9_FP_REG 64 +#define SPARC_LAST_V9_FP_REG 95 +/* V9 %fcc[0123]. V8 uses (figuratively) %fcc0. */ +#define SPARC_FIRST_V9_FCC_REG 96 +#define SPARC_LAST_V9_FCC_REG 99 +/* V8 fcc reg. */ +#define SPARC_FCC_REG 96 +/* Integer CC reg. We don't distinguish %icc from %xcc. */ +#define SPARC_ICC_REG 100 + +/* Nonzero if REGNO is an fp reg. */ +#define SPARC_FP_REG_P(REGNO) \ +((REGNO) >= SPARC_FIRST_FP_REG && (REGNO) <= SPARC_LAST_V9_FP_REG) + +/* Argument passing regs. */ +#define SPARC_OUTGOING_INT_ARG_FIRST 8 +#define SPARC_INCOMING_INT_ARG_FIRST (TARGET_FLAT ? 8 : 24) +#define SPARC_FP_ARG_FIRST 32 + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + + On non-v9 systems: + g1 is free to use as temporary. + g2-g4 are reserved for applications. Gcc normally uses them as + temporaries, but this can be disabled via the -mno-app-regs option. + g5 through g7 are reserved for the operating system. + + On v9 systems: + g1,g5 are free to use as temporaries, and are free to use between calls + if the call is to an external function via the PLT. + g4 is free to use as a temporary in the non-embedded case. + g4 is reserved in the embedded case. + g2-g3 are reserved for applications. Gcc normally uses them as + temporaries, but this can be disabled via the -mno-app-regs option. + g6-g7 are reserved for the operating system (or application in + embedded case). + ??? Register 1 is used as a temporary by the 64 bit sethi pattern, so must + currently be a fixed register until this pattern is rewritten. + Register 1 is also used when restoring call-preserved registers in large + stack frames. + + Registers fixed in arch32 and not arch64 (or vice-versa) are marked in + CONDITIONAL_REGISTER_USAGE in order to properly handle -ffixed-. +*/ + +#define FIXED_REGISTERS \ + {1, 0, 0, 0, 0, 0, 1, 1, \ + 0, 0, 0, 0, 0, 0, 1, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 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} + +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. */ + +#define CALL_USED_REGISTERS \ + {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, 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} + +/* If !TARGET_FPU, then make the fp registers and fp cc regs fixed so that + they won't be allocated. */ + +#define CONDITIONAL_REGISTER_USAGE \ +do \ + { \ + if (TARGET_ARCH32) \ + { \ + fixed_regs[5] = 1; \ + } \ + else \ + { \ + fixed_regs[1] = 1; \ + } \ + if (! TARGET_V9) \ + { \ + int regno; \ + for (regno = SPARC_FIRST_V9_FP_REG; \ + regno <= SPARC_LAST_V9_FP_REG; \ + regno++) \ + fixed_regs[regno] = 1; \ + /* %fcc0 is used by v8 and v9. */ \ + for (regno = SPARC_FIRST_V9_FCC_REG + 1; \ + regno <= SPARC_LAST_V9_FCC_REG; \ + regno++) \ + fixed_regs[regno] = 1; \ + } \ + if (! TARGET_FPU) \ + { \ + int regno; \ + for (regno = 32; regno < SPARC_LAST_V9_FCC_REG; regno++) \ + fixed_regs[regno] = 1; \ + } \ + /* Don't unfix g2-g4 if they were fixed with -ffixed-. */ \ + fixed_regs[2] |= ! TARGET_APP_REGS; \ + fixed_regs[3] |= ! TARGET_APP_REGS; \ + fixed_regs[4] |= ! TARGET_APP_REGS || TARGET_CM_EMBMEDANY; \ + if (TARGET_FLAT) \ + { \ + /* Let the compiler believe the frame pointer is still \ + %fp, but output it as %i7. */ \ + fixed_regs[31] = 1; \ + reg_names[FRAME_POINTER_REGNUM] = "%i7"; \ + /* ??? This is a hack to disable leaf functions. */ \ + global_regs[7] = 1; \ + } \ + if (profile_block_flag) \ + { \ + /* %g1 and %g2 must be fixed, because BLOCK_PROFILER \ + uses them. */ \ + fixed_regs[1] = 1; \ + fixed_regs[2] = 1; \ + } \ + if (flag_pic != 0) \ + { \ + fixed_regs[23] = 1; \ + call_used_regs[23] = 1; \ + } \ + } \ +while (0) + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. + + On SPARC, ordinary registers hold 32 bits worth; + this means both integer and floating point registers. + On v9, integer regs hold 64 bits worth; floating point regs hold + 32 bits worth (this includes the new fp regs as even the odd ones are + included in the hard register count). */ + +#define HARD_REGNO_NREGS(REGNO, MODE) \ + (TARGET_ARCH64 \ + ? ((REGNO) < 32 \ + ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD \ + : (GET_MODE_SIZE (MODE) + 3) / 4) \ + : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + +/* 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. */ +#define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO) \ + (TARGET_ARCH64 && (REGNO) >= 32 && (REGNO) < 96 && (TMODE) == SImode ? 1 : ((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. */ +extern int *hard_regno_mode_classes; +extern int sparc_mode_class[]; +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((hard_regno_mode_classes[REGNO] & sparc_mode_class[MODE]) != 0) + +/* 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. + + For V9: SFmode can't be combined with other float modes, because they can't + be allocated to the %d registers. Also, DFmode won't fit in odd %f + registers, but SFmode will. */ +#define MODES_TIEABLE_P(MODE1, MODE2) \ + ((MODE1) == (MODE2) \ + || (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \ + && (! TARGET_V9 \ + || (GET_MODE_CLASS (MODE1) != MODE_FLOAT \ + || (MODE1 != SFmode && MODE2 != SFmode))))) + +/* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + +/* SPARC pc isn't overloaded on a register that the compiler knows about. */ +/* #define PC_REGNUM */ + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 14 + +/* Actual top-of-stack address is 92/176 greater than the contents of the + stack pointer register for !v9/v9. That is: + - !v9: 64 bytes for the in and local registers, 4 bytes for structure return + address, and 6*4 bytes for the 6 register parameters. + - v9: 128 bytes for the in and local registers + 6*8 bytes for the integer + parameter regs. */ +#define STACK_POINTER_OFFSET FIRST_PARM_OFFSET(0) + +/* The stack bias (amount by which the hardware register is offset by). */ +#define SPARC_STACK_BIAS ((TARGET_ARCH64 && TARGET_STACK_BIAS) ? 2047 : 0) + +/* Is stack biased? */ +#define STACK_BIAS SPARC_STACK_BIAS + +/* Base register for access to local variables of the function. */ +#define FRAME_POINTER_REGNUM 30 + +#if 0 +/* Register that is used for the return address for the flat model. */ +#define RETURN_ADDR_REGNUM 15 +#endif + +/* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms + may be accessed via the stack pointer) in functions that seem suitable. + This is computed in `reload', in reload1.c. + Used in flow.c, global.c, and reload1.c. + + Being a non-leaf function does not mean a frame pointer is needed in the + flat window model. However, the debugger won't be able to backtrace through + us with out it. */ +#define FRAME_POINTER_REQUIRED \ + (TARGET_FLAT ? (current_function_calls_alloca || current_function_varargs \ + || !leaf_function_p ()) \ + : ! (leaf_function_p () && only_leaf_regs_used ())) + +/* C statement to store the difference between the frame pointer + and the stack pointer values immediately after the function prologue. + + Note, we always pretend that this is a leaf function because if + it's not, there's no point in trying to eliminate the + frame pointer. If it is a leaf function, we guessed right! */ +#define INITIAL_FRAME_POINTER_OFFSET(VAR) \ + ((VAR) = (TARGET_FLAT ? sparc_flat_compute_frame_size (get_frame_size ()) \ + : compute_frame_size (get_frame_size (), 1))) + +/* Base register for access to arguments of the function. */ +#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM + +/* Register in which static-chain is passed to a function. This must + not be a register used by the prologue. */ +#define STATIC_CHAIN_REGNUM (TARGET_ARCH64 ? 5 : 2) + +/* Register which holds offset table for position-independent + data references. */ + +#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: + !v9: Default is on. + v9: Default is off. */ + +#define DEFAULT_PCC_STRUCT_RETURN -1 + +/* Sparc ABI says that quad-precision floats and all structures are returned + in memory. + For v9: unions <= 32 bytes in size are returned in int regs, + structures up to 32 bytes are returned in int and fp regs. */ + +#define RETURN_IN_MEMORY(TYPE) \ +(TARGET_ARCH32 \ + ? (TYPE_MODE (TYPE) == BLKmode \ + || TYPE_MODE (TYPE) == TFmode \ + || TYPE_MODE (TYPE) == TCmode) \ + : (TYPE_MODE (TYPE) == BLKmode \ + && int_size_in_bytes (TYPE) > 32)) + +/* Functions which return large structures get the address + to place the wanted value at offset 64 from the frame. + Must reserve 64 bytes for the in and local registers. + v9: Functions which return large structures get the address to place the + wanted value from an invisible first argument. */ +/* Used only in other #defines in this file. */ +#define STRUCT_VALUE_OFFSET 64 + +#define STRUCT_VALUE \ + (TARGET_ARCH64 \ + ? 0 \ + : gen_rtx_MEM (Pmode, \ + gen_rtx_PLUS (Pmode, stack_pointer_rtx, \ + GEN_INT (STRUCT_VALUE_OFFSET)))) +#define STRUCT_VALUE_INCOMING \ + (TARGET_ARCH64 \ + ? 0 \ + : gen_rtx_MEM (Pmode, \ + gen_rtx_PLUS (Pmode, frame_pointer_rtx, \ + GEN_INT (STRUCT_VALUE_OFFSET)))) + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + +/* The SPARC has various kinds of registers: general, floating point, + and condition codes [well, it has others as well, but none that we + care directly about]. + + For v9 we must distinguish between the upper and lower floating point + registers because the upper ones can't hold SFmode values. + HARD_REGNO_MODE_OK won't help here because reload assumes that register(s) + satisfying a group need for a class will also satisfy a single need for + that class. EXTRA_FP_REGS is a bit of a misnomer as it covers all 64 fp + regs. + + It is important that one class contains all the general and all the standard + fp regs. Otherwise find_reg() won't properly allocate int regs for moves, + because reg_class_record() will bias the selection in favor of fp regs, + because reg_class_subunion[GENERAL_REGS][FP_REGS] will yield FP_REGS, + because FP_REGS > GENERAL_REGS. + + It is also important that one class contain all the general and all the + fp regs. Otherwise when spilling a DFmode reg, it may be from EXTRA_FP_REGS + but find_reloads() may use class GENERAL_OR_FP_REGS. This will cause + allocate_reload_reg() to bypass it causing an abort because the compiler + thinks it doesn't have a spill reg when in fact it does. + + v9 also has 4 floating point condition code registers. Since we don't + have a class that is the union of FPCC_REGS with either of the others, + it is important that it appear first. Otherwise the compiler will die + trying to compile _fixunsdfsi because fix_truncdfsi2 won't match its + constraints. + + It is important that SPARC_ICC_REG have class NO_REGS. Otherwise combine + may try to use it to hold an SImode value. See register_operand. + ??? Should %fcc[0123] be handled similarly? +*/ + +enum reg_class { NO_REGS, FPCC_REGS, I64_REGS, GENERAL_REGS, FP_REGS, + EXTRA_FP_REGS, GENERAL_OR_FP_REGS, GENERAL_OR_EXTRA_FP_REGS, + ALL_REGS, LIM_REG_CLASSES }; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ + +#define REG_CLASS_NAMES \ + { "NO_REGS", "FPCC_REGS", "I64_REGS", "GENERAL_REGS", "FP_REGS", \ + "EXTRA_FP_REGS", "GENERAL_OR_FP_REGS", "GENERAL_OR_EXTRA_FP_REGS", \ + "ALL_REGS" } + +/* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS \ + {{0, 0, 0, 0}, {0, 0, 0, 0xf}, {0xffff, 0, 0, 0}, \ + {-1, 0, 0, 0}, {0, -1, 0, 0}, {0, -1, -1, 0}, \ + {-1, -1, 0, 0}, {-1, -1, -1, 0}, {-1, -1, -1, 0x1f}} + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + +extern enum reg_class sparc_regno_reg_class[]; + +#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)] + +/* This is the order in which to allocate registers normally. + + We put %f0/%f1 last among the float registers, so as to make it more + likely that a pseudo-register which dies in the float return register + will get allocated to the float return register, thus saving a move + instruction at the end of the function. */ + +#define REG_ALLOC_ORDER \ +{ 8, 9, 10, 11, 12, 13, 2, 3, \ + 15, 16, 17, 18, 19, 20, 21, 22, \ + 23, 24, 25, 26, 27, 28, 29, 31, \ + 34, 35, 36, 37, 38, 39, /* %f2-%f7 */ \ + 40, 41, 42, 43, 44, 45, 46, 47, /* %f8-%f15 */ \ + 48, 49, 50, 51, 52, 53, 54, 55, /* %f16-%f23 */ \ + 56, 57, 58, 59, 60, 61, 62, 63, /* %f24-%f31 */ \ + 64, 65, 66, 67, 68, 69, 70, 71, /* %f32-%f39 */ \ + 72, 73, 74, 75, 76, 77, 78, 79, /* %f40-%f47 */ \ + 80, 81, 82, 83, 84, 85, 86, 87, /* %f48-%f55 */ \ + 88, 89, 90, 91, 92, 93, 94, 95, /* %f56-%f63 */ \ + 32, 33, /* %f0,%f1 */ \ + 96, 97, 98, 99, 100, /* %fcc0-3, %icc */ \ + 1, 4, 5, 6, 7, 0, 14, 30} + +/* This is the order in which to allocate registers for + leaf functions. If all registers can fit in the "i" registers, + then we have the possibility of having a leaf function. */ + +#define REG_LEAF_ALLOC_ORDER \ +{ 2, 3, 24, 25, 26, 27, 28, 29, \ + 15, 8, 9, 10, 11, 12, 13, \ + 16, 17, 18, 19, 20, 21, 22, 23, \ + 34, 35, 36, 37, 38, 39, \ + 40, 41, 42, 43, 44, 45, 46, 47, \ + 48, 49, 50, 51, 52, 53, 54, 55, \ + 56, 57, 58, 59, 60, 61, 62, 63, \ + 64, 65, 66, 67, 68, 69, 70, 71, \ + 72, 73, 74, 75, 76, 77, 78, 79, \ + 80, 81, 82, 83, 84, 85, 86, 87, \ + 88, 89, 90, 91, 92, 93, 94, 95, \ + 32, 33, \ + 96, 97, 98, 99, 100, \ + 1, 4, 5, 6, 7, 0, 14, 30, 31} + +#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc () + +/* ??? %g7 is not a leaf register to effectively #undef LEAF_REGISTERS when + -mflat is used. Function only_leaf_regs_used will return 0 if a global + register is used and is not permitted in a leaf function. We make %g7 + a global reg if -mflat and voila. Since %g7 is a system register and is + fixed it won't be used by gcc anyway. */ + +#define LEAF_REGISTERS \ +{ 1, 1, 1, 1, 1, 1, 1, 0, \ + 0, 0, 0, 0, 0, 0, 1, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 1, 1, 1, 1, 1, 1, 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} + +extern char leaf_reg_remap[]; +#define LEAF_REG_REMAP(REGNO) (leaf_reg_remap[REGNO]) + +/* The class value for index registers, and the one for base regs. */ +#define INDEX_REG_CLASS GENERAL_REGS +#define BASE_REG_CLASS GENERAL_REGS + +/* Local macro to handle the two v9 classes of FP regs. */ +#define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS || (CLASS) == EXTRA_FP_REGS) + +/* Get reg_class from a letter such as appears in the machine description. + In the not-v9 case, coerce v9's 'e' class to 'f', so we can use 'e' in the + .md file for v8 and v9. + 'd' and 'b' are used for single and double precision VIS operations, + if TARGET_VIS. + 'h' is used for V8+ 64 bit global and out registers. */ + +#define REG_CLASS_FROM_LETTER(C) \ +(TARGET_V9 \ + ? ((C) == 'f' ? FP_REGS \ + : (C) == 'e' ? EXTRA_FP_REGS \ + : (C) == 'c' ? FPCC_REGS \ + : ((C) == 'd' && TARGET_VIS) ? FP_REGS\ + : ((C) == 'b' && TARGET_VIS) ? EXTRA_FP_REGS\ + : ((C) == 'h' && TARGET_V8PLUS) ? I64_REGS\ + : NO_REGS) \ + : ((C) == 'f' ? FP_REGS \ + : (C) == 'e' ? FP_REGS \ + : (C) == 'c' ? FPCC_REGS \ + : NO_REGS)) + +/* The letters I, J, K, L and M in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. + + `I' is used for the range of constants an insn can actually contain. + `J' is used for the range which is just zero (since that is R0). + `K' is used for constants which can be loaded with a single sethi insn. + `L' is used for the range of constants supported by the movcc insns. + `M' is used for the range of constants supported by the movrcc insns. */ + +#define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400) +#define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x400 < 0x800) +#define SPARC_SIMM13_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x1000 < 0x2000) +/* 10 and 11 bit immediates are only used for a few specific insns. + SMALL_INT is used throughout the port so we continue to use it. */ +#define SMALL_INT(X) (SPARC_SIMM13_P (INTVAL (X))) +/* 13 bit immediate, considering only the low 32 bits */ +#define SMALL_INT32(X) (SPARC_SIMM13_P ((int)INTVAL (X) & 0xffffffff)) +#define SPARC_SETHI_P(X) \ +(((unsigned HOST_WIDE_INT) (X) & ~(unsigned HOST_WIDE_INT) 0xfffffc00) == 0) + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? SPARC_SIMM13_P (VALUE) \ + : (C) == 'J' ? (VALUE) == 0 \ + : (C) == 'K' ? SPARC_SETHI_P (VALUE) \ + : (C) == 'L' ? SPARC_SIMM11_P (VALUE) \ + : (C) == 'M' ? SPARC_SIMM10_P (VALUE) \ + : 0) + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. */ + +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'G' ? fp_zero_operand (VALUE) \ + : (C) == 'H' ? arith_double_operand (VALUE, DImode) \ + : 0) + +/* Given an rtx X being reloaded into a reg required to be + 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. */ +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ + (CONSTANT_P (X) \ + && (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)) + +/* 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 + 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) \ + && (GET_CODE (IN) == MEM \ + || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \ + && true_regnum (IN) == -1))) ? 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) + +/* On SPARC it is not possible to directly move data between + GENERAL_REGS and FP_REGS. */ +#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ + (FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) + +/* Return the stack location to use for secondary memory needed reloads. + We want to use the reserved location just below the frame pointer. + However, we must ensure that there is a frame, so use assign_stack_local + if the frame size is zero. */ +#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \ + (get_frame_size () == 0 \ + ? assign_stack_local (MODE, GET_MODE_SIZE (MODE), 0) \ + : gen_rtx_MEM (MODE, gen_rtx_PLUS (Pmode, frame_pointer_rtx, \ + GEN_INT (STARTING_FRAME_OFFSET)))) + +/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9 + because the movsi and movsf patterns don't handle r/f moves. + For v8 we copy the default definition. */ +#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \ + (TARGET_ARCH64 \ + ? (GET_MODE_BITSIZE (MODE) < 32 \ + ? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \ + : MODE) \ + : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD \ + ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0) \ + : MODE)) + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ +/* On SPARC, this is the size of MODE in words. */ +#define CLASS_MAX_NREGS(CLASS, MODE) \ + (FP_REG_CLASS_P (CLASS) ? (GET_MODE_SIZE (MODE) + 3) / 4 \ + : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Stack layout; function entry, exit and calling. */ + +/* Define the number of register that can hold parameters. + This macro is only used in other macro definitions below and in sparc.c. + MODE is the mode of the argument. + !v9: All args are passed in %o0-%o5. + v9: %o0-%o5 and %f0-%f31 are cumulatively used to pass values. + See the description in sparc.c. */ +#define NPARM_REGS(MODE) \ +(TARGET_ARCH64 \ + ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 6) \ + : 6) + +/* Define this if pushing a word on the stack + makes the stack pointer a smaller address. */ +#define STACK_GROWS_DOWNWARD + +/* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ +#define FRAME_GROWS_DOWNWARD + +/* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ +/* This allows space for one TFmode floating point value. */ +#define STARTING_FRAME_OFFSET \ + (TARGET_ARCH64 ? (SPARC_STACK_BIAS - 16) \ + : (-SPARC_STACK_ALIGN (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT))) + +/* If we generate an insn to push BYTES bytes, + this says how many the stack pointer really advances by. + On SPARC, don't define this because there are no push insns. */ +/* #define PUSH_ROUNDING(BYTES) */ + +/* Offset of first parameter from the argument pointer register value. + !v9: This is 64 for the ins and locals, plus 4 for the struct-return reg + even if this function isn't going to use it. + v9: This is 128 for the ins and locals. */ +#define FIRST_PARM_OFFSET(FNDECL) \ + (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \ + : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD)) + +/* 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. + v9: Only space for the arguments passed is allocated. */ +/* ??? Ideally, we'd use zero here (as the minimum), but zero has special + meaning to the backend. Further, we need to be able to detect if a + varargs/unprototyped function is called, as they may want to spill more + registers than we've provided space. Ugly, ugly. So for now we retain + all 6 slots even for v9. */ +#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD) + +/* Keep the stack pointer constant throughout the function. + This is both an optimization and a necessity: longjmp + doesn't behave itself when the stack pointer moves within + the function! */ +#define ACCUMULATE_OUTGOING_ARGS + +/* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + SIZE is the number of bytes of arguments passed on the stack. */ + +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 + +/* Some subroutine macros specific to this machine. + When !TARGET_FPU, put float return values in the general registers, + since we don't have any fp registers. */ +#define BASE_RETURN_VALUE_REG(MODE) \ + (TARGET_ARCH64 \ + ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \ + : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32 : 8)) + +#define BASE_OUTGOING_VALUE_REG(MODE) \ + (TARGET_ARCH64 \ + ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \ + : TARGET_FLAT ? 8 : 24) \ + : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32 \ + : (TARGET_FLAT ? 8 : 24))) + +#define BASE_PASSING_ARG_REG(MODE) \ + (TARGET_ARCH64 \ + ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \ + : 8) + +/* ??? FIXME -- seems wrong for v9 structure passing... */ +#define BASE_INCOMING_ARG_REG(MODE) \ + (TARGET_ARCH64 \ + ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \ + : TARGET_FLAT ? 8 : 24) \ + : (TARGET_FLAT ? 8 : 24)) + +/* Define this macro if the target machine has "register windows". This + C expression returns the register number as seen by the called function + corresponding to register number OUT as seen by the calling function. + Return OUT if register number OUT is not an outbound register. */ + +#define INCOMING_REGNO(OUT) \ + ((TARGET_FLAT || (OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16) + +/* Define this macro if the target machine has "register windows". This + C expression returns the register number as seen by the calling function + corresponding to register number IN as seen by the called function. + Return IN if register number IN is not an inbound register. */ + +#define OUTGOING_REGNO(IN) \ + ((TARGET_FLAT || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16) + +/* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + +/* On SPARC the value is found in the first "output" register. */ + +extern struct rtx_def *function_value (); +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + function_value ((VALTYPE), TYPE_MODE (VALTYPE), 1) + +/* But the called function leaves it in the first "input" register. */ + +#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \ + function_value ((VALTYPE), TYPE_MODE (VALTYPE), 0) + +/* Define how to find the value returned by a library function + assuming the value has mode MODE. */ + +#define LIBCALL_VALUE(MODE) \ + function_value (NULL_TREE, (MODE), 1) + +/* 1 if N is a possible register number for a function value + as seen by the caller. + On SPARC, the first "output" reg is used for integer values, + and the first floating point register is used for floating point values. */ + +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 8 || (N) == 32) + +/* Define the size of space to allocate for the return value of an + untyped_call. */ + +#define APPLY_RESULT_SIZE 16 + +/* 1 if N is a possible register number for function argument passing. + On SPARC, these are the "output" registers. v9 also uses %f0-%f31. */ + +#define FUNCTION_ARG_REGNO_P(N) \ +(TARGET_ARCH64 \ + ? (((N) >= 8 && (N) <= 13) || ((N) >= 32 && (N) <= 63)) \ + : ((N) >= 8 && (N) <= 13)) + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. + + On SPARC (!v9), this is a single integer, which is a number of words + of arguments scanned so far (including the invisible argument, + if any, which holds the structure-value-address). + Thus 7 or more means all following args should go on the stack. + + For v9, we also need to know whether a prototype is present. */ + +struct sparc_args { + int words; /* number of words passed so far */ + int prototype_p; /* non-zero if a prototype is present */ + int libcall_p; /* non-zero if a library call */ +}; +#define CUMULATIVE_ARGS struct sparc_args + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +extern void init_cumulative_args (); +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ +init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (INDIRECT)); + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + TYPE is null for libcalls where that information may not be available. */ + +extern void function_arg_advance (); +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ +function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED)) + +/* Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + +extern struct rtx_def *function_arg (); +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +function_arg (& (CUM), (MODE), (TYPE), (NAMED), 0) + +/* Define where a function finds its arguments. + This is different from FUNCTION_ARG because of register windows. */ + +#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ +function_arg (& (CUM), (MODE), (TYPE), (NAMED), 1) + +/* For an arg passed partly in registers and partly in memory, + this is the number of registers used. + For args passed entirely in registers or entirely in memory, zero. */ + +extern int function_arg_partial_nregs (); +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ +function_arg_partial_nregs (& (CUM), (MODE), (TYPE), (NAMED)) + +/* A C expression that indicates when an argument must be passed by reference. + If nonzero for an argument, a copy of that argument is made in memory and a + pointer to the argument is passed instead of the argument itself. + The pointer is passed in whatever way is appropriate for passing a pointer + to that type. */ + +extern int function_arg_pass_by_reference (); +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ +function_arg_pass_by_reference (& (CUM), (MODE), (TYPE), (NAMED)) + +/* If defined, a C expression which determines whether, and in which direction, + to pad out an argument with extra space. The value should be of type + `enum direction': either `upward' to pad above the argument, + `downward' to pad below, or `none' to inhibit padding. */ + +#define FUNCTION_ARG_PADDING(MODE, TYPE) \ +function_arg_padding ((MODE), (TYPE)) + +/* If defined, a C expression that gives the alignment boundary, in bits, + of an argument with the specified mode and type. If it is not defined, + PARM_BOUNDARY is used for all arguments. + For sparc64, objects requiring 16 byte alignment are passed that way. */ + +#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ +((TARGET_ARCH64 \ + && (GET_MODE_ALIGNMENT (MODE) == 128 \ + || ((TYPE) && TYPE_ALIGN (TYPE) == 128))) \ + ? 128 : PARM_BOUNDARY) + +/* Define the information needed to generate branch and scc insns. This is + stored from the compare operation. Note that we can't use "rtx" here + since it hasn't been defined! */ + +extern struct rtx_def *sparc_compare_op0, *sparc_compare_op1; + +/* Define the function that build the compare insn for scc and bcc. */ + +extern struct rtx_def *gen_compare_reg (); + +/* This function handles all v9 scc insns */ + +extern int gen_v9_scc (); + +/* Generate the special assembly code needed to tell the assembler whatever + it might need to know about the return value of a function. + + For Sparc assemblers, we need to output a .proc pseudo-op which conveys + information to the assembler relating to peephole optimization (done in + the assembler). */ + +#define ASM_DECLARE_RESULT(FILE, RESULT) \ + fprintf ((FILE), "\t.proc\t0%lo\n", sparc_type_code (TREE_TYPE (RESULT))) + +/* Output the label for a function definition. */ + +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ +do { \ + ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ + ASM_OUTPUT_LABEL (FILE, NAME); \ +} while (0) + +/* This macro generates the assembly code for function entry. + FILE is a stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. */ + +/* On SPARC, move-double insns between fpu and cpu need an 8-byte block + of memory. If any fpu reg is used in the function, we allocate + such a block here, at the bottom of the frame, just in case it's needed. + + If this function is a leaf procedure, then we may choose not + 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 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. + + profile_block_flag == 0, no option used: + + No profiling done. + + 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'. + +*/ + +/* 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: + +*/ + +#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) + +/* 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) + +*/ + +#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) + +/* 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. +*/ + +#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \ + fprintf (FILE, "\tcall ___bb_trace_ret\n\tnop\n" ); + +/* The function `__bb_trace_func' is called in every basic block + and is not allowed to change the machine state. Saving (restoring) + the state can either be done in the BLOCK_PROFILER macro, + before calling function (rsp. after returning from function) + `__bb_trace_func', or it can be done inside the function by + defining the macros: + + MACHINE_STATE_SAVE(ID) + MACHINE_STATE_RESTORE(ID) + + In the latter case care must be taken, that the prologue code + of function `__bb_trace_func' does not already change the + state prior to saving it with MACHINE_STATE_SAVE. + + The parameter `ID' is a string identifying a unique macro use. + + On sparc it is sufficient to save the psw register to memory. + Unfortunately the psw register can be read in supervisor mode only, + so we read only the condition codes by using branch instructions + and hope that this is enough. */ + +#define MACHINE_STATE_SAVE(ID) \ + int ms_flags, ms_saveret; \ + asm volatile( \ + "mov %%g0,%0\n\ + be,a LFLGNZ"ID"\n\ + or %0,4,%0\n\ +LFLGNZ"ID":\n\ + bcs,a LFLGNC"ID"\n\ + or %0,1,%0\n\ +LFLGNC"ID":\n\ + bvs,a LFLGNV"ID"\n\ + or %0,2,%0\n\ +LFLGNV"ID":\n\ + bneg,a LFLGNN"ID"\n\ + or %0,8,%0\n\ +LFLGNN"ID":\n\ + mov %%g2,%1" \ + : "=r"(ms_flags), "=r"(ms_saveret)); + +/* On sparc MACHINE_STATE_RESTORE restores the psw register from memory. + The psw register can be written in supervisor mode only, + which is true even for simple condition codes. + We use some combination of instructions to produce the + proper condition codes, but some flag combinations can not + be generated in this way. If this happens an unimplemented + instruction will be executed to abort the program. */ + +#define MACHINE_STATE_RESTORE(ID) \ +{ extern char flgtab[] __asm__("LFLGTAB"ID); \ + int scratch; \ + asm volatile ( \ + "jmpl %2+%1,%%g0\n\ + ! Do part of VC in the delay slot here, as it needs 3 insns.\n\ + addcc 2,%3,%%g0\n\ +LFLGTAB" ID ":\n\ + ! 0\n\ + ba LFLGRET"ID"\n\ + orcc 1,%%g0,%%g0\n\ + ! C\n\ + ba LFLGRET"ID"\n\ + addcc 2,%3,%%g0\n\ + ! V\n\ + unimp\n\ + nop\n\ + ! VC\n\ + ba LFLGRET"ID"\n\ + addxcc %4,%4,%0\n\ + ! Z\n\ + ba LFLGRET"ID"\n\ + subcc %%g0,%%g0,%%g0\n\ + ! ZC\n\ + ba LFLGRET"ID"\n\ + addcc 1,%3,%0\n\ + ! ZVC\n\ + ba LFLGRET"ID"\n\ + addcc %4,%4,%0\n\ + ! N\n\ + ba LFLGRET"ID"\n\ + orcc %%g0,-1,%%g0\n\ + ! NC\n\ + ba LFLGRET"ID"\n\ + addcc %%g0,%3,%%g0\n\ + ! NV\n\ + unimp\n\ + nop\n\ + ! NVC\n\ + unimp\n\ + nop\n\ + ! NZ\n\ + unimp\n\ + nop\n\ + ! NZC\n\ + unimp\n\ + nop\n\ + ! NZV\n\ + unimp\n\ + nop\n\ + ! NZVC\n\ + unimp\n\ + nop\n\ +LFLGRET"ID":\n\ + mov %5,%%g2" \ + : "=r"(scratch) \ + : "r"(ms_flags*8), "r"(flgtab), "r"(-1), \ + "r"(0x80000000), "r"(ms_saveret) \ + : "cc", "%g2"); } + +/* 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. */ + +extern int current_function_calls_alloca; +extern int current_function_outgoing_args_size; + +#define EXIT_IGNORE_STACK \ + (get_frame_size () != 0 \ + || current_function_calls_alloca || current_function_outgoing_args_size) + +/* This macro generates the assembly code for function exit, + on machines that need it. If FUNCTION_EPILOGUE is not defined + then individual return instructions are generated for each + return statement. Args are same as for FUNCTION_PROLOGUE. + + The function epilogue should not depend on the current stack pointer! + It should use the frame pointer only. This is mandatory because + of alloca; we also take advantage of it to omit stack adjustments + before returning. */ + +/* This declaration is needed due to traditional/ANSI + incompatibilities which cannot be #ifdefed away + because they occur inside of macros. Sigh. */ +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)) + +#define DELAY_SLOTS_FOR_EPILOGUE \ + (TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1) +#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \ + (TARGET_FLAT ? sparc_flat_eligible_for_epilogue_delay (trial, slots_filled) \ + : eligible_for_epilogue_delay (trial, slots_filled)) + +/* Define registers used by the epilogue and return instruction. */ +#define EPILOGUE_USES(REGNO) \ + (!TARGET_FLAT && REGNO == 31) + +/* Length in units of the trampoline for entering a nested function. */ + +#define TRAMPOLINE_SIZE (TARGET_ARCH64 ? 32 : 16) + +#define TRAMPOLINE_ALIGNMENT 128 /* 16 bytes */ + +/* 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. */ + +void sparc_initialize_trampoline (); +void sparc64_initialize_trampoline (); +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ + if (TARGET_ARCH64) \ + sparc64_initialize_trampoline (TRAMP, FNADDR, CXT); \ + else \ + sparc_initialize_trampoline (TRAMP, FNADDR, CXT) + +/* Generate necessary RTL for __builtin_saveregs(). + ARGLIST is the argument list; see expr.c. */ + +extern struct rtx_def *sparc_builtin_saveregs (); +#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) sparc_builtin_saveregs (ARGLIST) + +/* Define this macro if the location where a function argument is passed + depends on whether or not it is a named argument. + + This macro controls how the NAMED argument to FUNCTION_ARG + is set for varargs and stdarg functions. With this macro defined, + the NAMED argument is always true for named arguments, and false for + unnamed arguments. If this is not defined, but SETUP_INCOMING_VARARGS + is defined, then all arguments are treated as named. Otherwise, all named + arguments except the last are treated as named. + For the v9 we want NAMED to mean what it says it means. */ + +#define STRICT_ARGUMENT_NAMING TARGET_V9 + +/* Generate RTL to flush the register windows so as to make arbitrary frames + available. */ +#define SETUP_FRAME_ADDRESSES() \ + emit_insn (gen_flush_register_windows ()) + +/* Given an rtx for the address of a frame, + return an rtx for the address of the word in the frame + that holds the dynamic chain--the previous frame's address. + ??? -mflat support? */ +#define DYNAMIC_CHAIN_ADDRESS(frame) \ + gen_rtx_PLUS (Pmode, frame, GEN_INT (14 * UNITS_PER_WORD)) + +/* The return address isn't on the stack, it is in a register, so we can't + access it from the current frame pointer. We can access it from the + previous frame pointer though by reading a value from the register window + save area. */ +#define RETURN_ADDR_IN_PREVIOUS_FRAME + +/* This is the offset of the return address to the true next instruction to be + executed for the current function. */ +#define RETURN_ADDR_OFFSET \ + (8 + 4 * (! TARGET_ARCH64 && current_function_returns_struct)) + +/* The current return address is in %i7. The return address of anything + farther back is in the register window save area at [%fp+60]. */ +/* ??? This ignores the fact that the actual return address is +8 for normal + returns, and +12 for structure returns. */ +#define RETURN_ADDR_RTX(count, frame) \ + ((count == -1) \ + ? gen_rtx_REG (Pmode, 31) \ + : gen_rtx_MEM (Pmode, \ + memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD)))) + +/* Before the prologue, the return address is %o7 + 8. OK, sometimes it's + +12, but always using +8 is close enough for frame unwind purposes. + Actually, just using %o7 is close enough for unwinding, but %o7+8 + is something you can return to. */ +#define INCOMING_RETURN_ADDR_RTX \ + gen_rtx_PLUS (word_mode, gen_rtx_REG (word_mode, 15), GEN_INT (8)) + +/* The offset from the incoming value of %sp to the top of the stack frame + for the current function. On sparc64, we have to account for the stack + bias if present. */ +#define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS + +#define DOESNT_NEED_UNWINDER (! TARGET_FLAT) + +/* Addressing modes, and classification of registers for them. */ + +/* #define HAVE_POST_INCREMENT */ +/* #define HAVE_POST_DECREMENT */ + +/* #define HAVE_PRE_DECREMENT */ +/* #define HAVE_PRE_INCREMENT */ + +/* Macros to check register numbers against specific register classes. */ + +/* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ + +#define REGNO_OK_FOR_INDEX_P(REGNO) \ +((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32) +#define REGNO_OK_FOR_BASE_P(REGNO) \ +((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32) +#define REGNO_OK_FOR_FP_P(REGNO) \ + (((unsigned) (REGNO) - 32 < (TARGET_V9 ? (unsigned)64 : (unsigned)32)) \ + || ((unsigned) reg_renumber[REGNO] - 32 < (TARGET_V9 ? (unsigned)64 : (unsigned)32))) +#define REGNO_OK_FOR_CCFP_P(REGNO) \ + (TARGET_V9 \ + && (((unsigned) (REGNO) - 96 < (unsigned)4) \ + || ((unsigned) reg_renumber[REGNO] - 96 < (unsigned)4))) + +/* Now macros that check whether X is a register and also, + strictly, whether it is in a specified class. + + These macros are specific to the SPARC, and may be used only + in code for printing assembler insns and in conditions for + define_optimization. */ + +/* 1 if X is an fp register. */ + +#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X))) + +/* Is X, a REG, an in or global register? i.e. is regno 0..7 or 24..31 */ +#define IN_OR_GLOBAL_P(X) (REGNO (X) < 8 || (REGNO (X) >= 24 && REGNO (X) <= 31)) + +/* Maximum number of registers that can appear in a valid memory address. */ + +#define MAX_REGS_PER_ADDRESS 2 + +/* Recognize any constant value that is a valid address. + When PIC, we do not accept an address that would require a scratch reg + to load into a register. */ + +#define CONSTANT_ADDRESS_P(X) \ + (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ + || (GET_CODE (X) == CONST \ + && ! (flag_pic && pic_address_needs_scratch (X)))) + +/* Define this, so that when PIC, reload won't try to reload invalid + addresses which require two reload registers. */ + +#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. */ + +#define LEGITIMATE_CONSTANT_P(X) \ + (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode) + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + +/* Optional extra constraints for this machine. Borrowed from romp.h. + + 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. + + `S' handles constraints for calls. ??? So where is it? */ + +#ifndef REG_OK_STRICT + +/* 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) \ + (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32)) +/* 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) \ + (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32)) + +/* '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) + +#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 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) +#endif + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + On SPARC, the actual legitimate addresses must be REG+REG or REG+SMALLINT + ordinarily. This changes a bit when generating PIC. + + If you change this, execute "rm explow.o recog.o reload.o". */ + +#define RTX_OK_FOR_BASE_P(X) \ + ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ + || (GET_CODE (X) == SUBREG \ + && GET_CODE (SUBREG_REG (X)) == REG \ + && REG_OK_FOR_BASE_P (SUBREG_REG (X)))) + +#define RTX_OK_FOR_INDEX_P(X) \ + ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ + || (GET_CODE (X) == SUBREG \ + && GET_CODE (SUBREG_REG (X)) == REG \ + && REG_OK_FOR_INDEX_P (SUBREG_REG (X)))) + +#define RTX_OK_FOR_OFFSET_P(X) \ + (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ if (RTX_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + else if (GET_CODE (X) == PLUS) \ + { \ + register rtx op0 = XEXP (X, 0); \ + register rtx op1 = XEXP (X, 1); \ + if (flag_pic && op0 == pic_offset_table_rtx) \ + { \ + if (RTX_OK_FOR_BASE_P (op1)) \ + goto ADDR; \ + else if (flag_pic == 1 \ + && GET_CODE (op1) != REG \ + && GET_CODE (op1) != LO_SUM \ + && GET_CODE (op1) != MEM \ + && (GET_CODE (op1) != CONST_INT \ + || SMALL_INT (op1))) \ + goto ADDR; \ + } \ + else if (RTX_OK_FOR_BASE_P (op0)) \ + { \ + if (RTX_OK_FOR_INDEX_P (op1) \ + || RTX_OK_FOR_OFFSET_P (op1)) \ + goto ADDR; \ + } \ + else if (RTX_OK_FOR_BASE_P (op1)) \ + { \ + if (RTX_OK_FOR_INDEX_P (op0) \ + || RTX_OK_FOR_OFFSET_P (op0)) \ + goto ADDR; \ + } \ + } \ + else if (GET_CODE (X) == LO_SUM) \ + { \ + register rtx op0 = XEXP (X, 0); \ + register rtx op1 = XEXP (X, 1); \ + if (RTX_OK_FOR_BASE_P (op0) \ + && 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) \ + goto ADDR; \ + } \ + else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \ + goto ADDR; \ +} + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. */ + +/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */ +extern struct rtx_def *legitimize_pic_address (); +#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ +{ rtx sparc_x = (X); \ + if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \ + (X) = gen_rtx_PLUS (Pmode, XEXP (X, 1), \ + force_operand (XEXP (X, 0), NULL_RTX)); \ + if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \ + (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \ + force_operand (XEXP (X, 1), NULL_RTX)); \ + if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS) \ + (X) = gen_rtx_PLUS (Pmode, force_operand (XEXP (X, 0), NULL_RTX),\ + XEXP (X, 1)); \ + if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS) \ + (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \ + force_operand (XEXP (X, 1), NULL_RTX)); \ + if (sparc_x != (X) && memory_address_p (MODE, X)) \ + goto WIN; \ + if (flag_pic) (X) = legitimize_pic_address (X, MODE, 0); \ + else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ + (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \ + copy_to_mode_reg (Pmode, XEXP (X, 1))); \ + else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ + (X) = gen_rtx_PLUS (Pmode, XEXP (X, 1), \ + 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); \ + if (memory_address_p (MODE, X)) \ + goto WIN; } + +/* 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. */ + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) + +/* If we are referencing a function make the SYMBOL_REF special. + In the Embedded Medium/Anywhere code model, %g4 points to the data segment + so we must not add it to function addresses. */ + +#define ENCODE_SECTION_INFO(DECL) \ + do { \ + if (TARGET_CM_EMBMEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \ + SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ + } while (0) + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE Pmode + +/* Define as C expression which evaluates to nonzero if the tablejump + instruction expects the table to contain offsets from the address of the + table. + Do not define this if the table should contain absolute addresses. */ +/* #define CASE_VECTOR_PC_RELATIVE 1 */ + +/* Specify the tree operation to be used to convert reals to integers. */ +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* This is the kind of divide that is easiest to do in the general case. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Define this as 1 if `char' should by default be signed; else as 0. */ +#define DEFAULT_SIGNED_CHAR 1 + +/* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ +#define MOVE_MAX 8 + +#if 0 /* Sun 4 has matherr, so this is no good. */ +/* This is the value of the error code EDOM for this machine, + used by the sqrt instruction. */ +#define TARGET_EDOM 33 + +/* This is how to refer to the variable errno. */ +#define GEN_ERRNO_RTX \ + gen_rtx_MEM (SImode, gen_rtx_SYMBOL_REF (Pmode, "errno")) +#endif /* 0 */ + +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD + will either zero-extend or sign-extend. The value of this macro should + be the code that says which one of the two operations is implicitly + done, NIL if none. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Nonzero if access to memory by bytes is slow and undesirable. + For RISC chips, it means that access to memory by bytes is no + better than access by words when possible, so grab a whole word + and maybe make use of that. */ +#define SLOW_BYTE_ACCESS 1 + +/* We assume that the store-condition-codes instructions store 0 for false + and some other value for true. This is the value stored for true. */ + +#define STORE_FLAG_VALUE 1 + +/* When a prototype says `char' or `short', really pass an `int'. */ +#define PROMOTE_PROTOTYPES + +/* Define this to be nonzero if shift instructions ignore all but the low-order + few bits. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +#define Pmode (TARGET_PTR64 ? DImode : SImode) + +/* Generate calls to memcpy, memcmp and memset. */ +#define TARGET_MEM_FUNCTIONS + +/* Add any extra modes needed to represent the condition code. + + On the Sparc, we have a "no-overflow" mode which is used when an add or + subtract insn is used to set the condition code. Different branches are + used in this case for some operations. + + We also have two modes to indicate that the relevant condition code is + in the floating-point condition code register. One for comparisons which + will generate an exception if the result is unordered (CCFPEmode) and + one for comparisons which will never trap (CCFPmode). + + CCXmode and CCX_NOOVmode are only used by v9. */ + +#define EXTRA_CC_MODES CCXmode, CC_NOOVmode, CCX_NOOVmode, CCFPmode, CCFPEmode + +/* Define the names for the modes specified above. */ + +#define EXTRA_CC_NAMES "CCX", "CC_NOOV", "CCX_NOOV", "CCFP", "CCFPE" + +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, + return the mode to be used for the comparison. For floating-point, + CCFP[E]mode is used. CC_NOOVmode should be used when the first operand is a + PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special + processing is needed. */ +#define SELECT_CC_MODE(OP,X,Y) \ + (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ + ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ + : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ + || GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT) \ + ? (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \ + : ((TARGET_ARCH64 || TARGET_V8PLUS) && GET_MODE (X) == DImode ? CCXmode : CCmode))) + +/* Return non-zero if SELECT_CC_MODE will never return MODE for a + floating point inequality comparison. */ + +#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) + +/* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ +#define FUNCTION_MODE SImode + +/* Define this if addresses of constant functions + shouldn't be put through pseudo regs where they can be cse'd. + Desirable on machines where ordinary constants are expensive + but a CALL with constant address is cheap. */ +#define NO_FUNCTION_CSE + +/* alloca should avoid clobbering the old register save area. */ +#define SETJMP_VIA_SAVE_AREA + +/* Define subroutines to call to handle multiply and divide. + Use the subroutines that Sun's library provides. + The `*' prevents an underscore from being prepended by the compiler. */ + +#define DIVSI3_LIBCALL "*.div" +#define UDIVSI3_LIBCALL "*.udiv" +#define MODSI3_LIBCALL "*.rem" +#define UMODSI3_LIBCALL "*.urem" +/* .umul is a little faster than .mul. */ +#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" + +/* 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, + and the compiler will notice and try to use the TFmode sqrt instruction + for calls to the builtin function sqrt, but this fails. */ +#define INIT_TARGET_OPTABS \ + do { \ + add_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, ADDTF3_LIBCALL); \ + sub_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, SUBTF3_LIBCALL); \ + neg_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, NEGTF2_LIBCALL); \ + smul_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, MULTF3_LIBCALL); \ + flodiv_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, DIVTF3_LIBCALL); \ + eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL); \ + netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, NETF2_LIBCALL); \ + gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GTTF2_LIBCALL); \ + getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GETF2_LIBCALL); \ + lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LTTF2_LIBCALL); \ + letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LETF2_LIBCALL); \ + trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, TRUNCTFSF2_LIBCALL); \ + trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, TRUNCTFDF2_LIBCALL); \ + extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EXTENDSFTF2_LIBCALL); \ + extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EXTENDDFTF2_LIBCALL); \ + floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATSITF2_LIBCALL); \ + fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL); \ + fixunstfsi_libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFSI2_LIBCALL); \ + if (TARGET_FPU) \ + sqrt_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx_SYMBOL_REF (Pmode, "_Q_sqrt"); \ + INIT_SUBTARGET_OPTABS; \ + } while (0) + +/* This is meant to be redefined in the host dependent files */ +#define INIT_SUBTARGET_OPTABS + +/* 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, + return it with a return statement. Otherwise, break from the switch. */ + +#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ + case CONST_INT: \ + if (INTVAL (RTX) < 0x1000 && INTVAL (RTX) >= -0x1000) \ + return 0; \ + case HIGH: \ + return 2; \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 4; \ + case CONST_DOUBLE: \ + if (GET_MODE (RTX) == DImode) \ + if ((XINT (RTX, 3) == 0 \ + && (unsigned) XINT (RTX, 2) < 0x1000) \ + || (XINT (RTX, 3) == -1 \ + && XINT (RTX, 2) < 0 \ + && XINT (RTX, 2) >= -0x1000)) \ + 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 + and another. */ +#define GENERAL_OR_I64(C) ((C) == GENERAL_REGS || (C) == I64_REGS) +#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ + (((FP_REG_CLASS_P (CLASS1) && GENERAL_OR_I64 (CLASS2)) \ + || (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \ + || (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \ + ? (sparc_cpu == PROCESSOR_ULTRASPARC ? 12 : 6) : 2) + +/* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. The purpose for the cost of MULT is to encourage + `synth_mult' to find a synthetic multiply when reasonable. + + If we need more than 12 insns to do a multiply, then go out-of-line, + since the call overhead will be < 10% of the cost of the multiply. */ + +#define RTX_COSTS(X,CODE,OUTER_CODE) \ + case MULT: \ + return TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \ + case DIV: \ + case UDIV: \ + case MOD: \ + case UMOD: \ + return COSTS_N_INSNS (25); \ + /* Make FLOAT and FIX more expensive than CONST_DOUBLE,\ + so that cse will favor the latter. */ \ + case FLOAT: \ + case FIX: \ + return 19; + +#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 + +/* Conditional branches with empty delay slots have a length of two. */ +#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ + if (GET_CODE (INSN) == CALL_INSN \ + || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn))) \ + LENGTH += 1; else + +/* Control the assembler format that we output. */ + +/* Output at beginning of assembler file. */ + +#define ASM_FILE_START(file) + +/* A C string constant describing how to begin a comment in the target + assembler language. The compiler assumes that the comment will end at + the end of the line. */ + +#define ASM_COMMENT_START "!" + +/* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ + +#define ASM_APP_ON "" + +/* Output to assembler file text saying following lines + no longer contain unusual constructs. */ + +#define ASM_APP_OFF "" + +/* ??? Try to make the style consistent here (_OP?). */ + +#define ASM_LONGLONG ".xword" +#define ASM_LONG ".word" +#define ASM_SHORT ".half" +#define ASM_BYTE_OP ".byte" +#define ASM_FLOAT ".single" +#define ASM_DOUBLE ".double" +#define ASM_LONGDOUBLE ".xxx" /* ??? Not known (or used yet). */ + +/* Output before read-only data. */ + +#define TEXT_SECTION_ASM_OP ".text" + +/* Output before writable data. */ + +#define DATA_SECTION_ASM_OP ".data" + +/* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ + +#define REGISTER_NAMES \ +{"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7", \ + "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7", \ + "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \ + "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7", \ + "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", \ + "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", \ + "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", \ + "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31", \ + "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39", \ + "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47", \ + "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55", \ + "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63", \ + "%fcc0", "%fcc1", "%fcc2", "%fcc3", "%icc"} + +/* Define additional names for use in asm clobbers and asm declarations. */ + +#define ADDITIONAL_REGISTER_NAMES \ +{{"ccr", SPARC_ICC_REG}, {"cc", SPARC_ICC_REG}} + +/* How to renumber registers for dbx and gdb. In the flat model, the frame + pointer is really %i7. */ + +#define DBX_REGISTER_NUMBER(REGNO) \ + (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO) + +/* On Sun 4, this limit is 2048. We use 1000 to be safe, since the length + can run past this up to a continuation point. Once we used 1500, but + a single entry in C++ can run more than 500 bytes, due to the length of + mangled symbol names. dbxout.c should really be fixed to do + continuations when they are actually needed instead of trying to + guess... */ +#define DBX_CONTIN_LENGTH 1000 + +/* This is how to output a note to DBX telling it the line number + to which the following sequence of instructions corresponds. + + This is needed for SunOS 4.0, and should not hurt for 3.2 + versions either. */ +#define ASM_OUTPUT_SOURCE_LINE(file, line) \ + { static int sym_lineno = 1; \ + fprintf (file, ".stabn 68,0,%d,LM%d\nLM%d:\n", \ + line, sym_lineno, sym_lineno); \ + sym_lineno += 1; } + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ + +#define ASM_OUTPUT_LABEL(FILE,NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + +/* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ + +#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + +/* The prefix to add to user-visible assembler symbols. */ + +#define USER_LABEL_PREFIX "_" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, "%s%d:\n", PREFIX, NUM) + +/* 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'. */ + +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf ((LABEL), "*%s%ld", (PREFIX), (long)(NUM)) + +/* This is how to output an assembler line defining a `float' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ + +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + { \ + long t; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t, \ + ASM_COMMENT_START, str); \ + } \ + +/* This is how to output an assembler line defining a `double' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ + +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + { \ + long t[2]; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0], \ + ASM_COMMENT_START, str); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]); \ + } + +/* This is how to output an assembler line defining a `long double' + constant. */ + +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ + { \ + long t[4]; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0], \ + ASM_COMMENT_START, str); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[2]); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[3]); \ + } + +/* This is how to output an assembler line defining an `int' constant. */ + +#define ASM_OUTPUT_INT(FILE,VALUE) \ +( fprintf (FILE, "\t%s\t", ASM_LONG), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line defining a DImode constant. */ +#define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \ + output_double_int (FILE, VALUE) + +/* Likewise for `char' and `short' constants. */ + +#define ASM_OUTPUT_SHORT(FILE,VALUE) \ +( fprintf (FILE, "\t%s\t", ASM_SHORT), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +#define ASM_OUTPUT_CHAR(FILE,VALUE) \ +( fprintf (FILE, "\t%s\t", ASM_BYTE_OP), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line for a numeric constant byte. */ + +#define ASM_OUTPUT_BYTE(FILE,VALUE) \ + fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) + +/* 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) \ + fprintf (FILE, "\t.word\t"); \ + else \ + fprintf (FILE, "\t.xword\t"); \ + assemble_name (FILE, label); \ + fputc ('\n', FILE); \ +} while (0) + +/* This is how to output an element of a case-vector that is relative. + (SPARC uses such vectors only when generating PIC.) */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ +do { \ + char label[30]; \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ + if (Pmode == SImode) \ + fprintf (FILE, "\t.word\t"); \ + else \ + fprintf (FILE, "\t.xword\t"); \ + assemble_name (FILE, label); \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", (REL)); \ + fputc ('-', FILE); \ + assemble_name (FILE, label); \ + fputc ('\n', FILE); \ +} while (0) + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG) != 0) \ + fprintf (FILE, "\t.align %d\n", (1<<(LOG))) + +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (sparc_align_jumps) + +#define LOOP_ALIGN(LABEL) (sparc_align_loops) + +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.skip %u\n", (SIZE)) + +/* This says how to output an assembler line + to define a global common symbol. */ + +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +( fputs ("\t.common ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u,\"bss\"\n", (SIZE))) + +/* This says how to output an assembler line to define a local common + symbol. */ + +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGNED) \ +( fputs ("\t.reserve ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u,\"bss\",%u\n", \ + (SIZE), ((ALIGNED) / BITS_PER_UNIT))) + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + do { \ + fputs (".globl ", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + fputs ("\n", (FILE)); \ + ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \ + } while (0) + +/* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) + +#define IDENT_ASM_OP ".ident" + +/* Output #ident as a .ident. */ + +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +/* Output code to add DELTA to the first argument, and then jump to FUNCTION. + Used for C++ multiple inheritance. */ +#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ +do { \ + int big_delta = (DELTA) >= 4096 || (DELTA) < -4096; \ + if (big_delta) \ + fprintf (FILE, "\tset %d,%%g1\n\tadd %%o0,%%g1,%%o0\n", (DELTA)); \ + /* Don't use the jmp solution unless we know the target is local to \ + the application or shared object. \ + XXX: Wimp out and don't actually check anything except if this is \ + an embedded target where we assume there are no shared libs. */ \ + if (!TARGET_CM_EMBMEDANY || flag_pic) \ + { \ + if (! big_delta) \ + fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA); \ + fprintf (FILE, "\tmov %%o7,%%g1\n"); \ + fprintf (FILE, "\tcall "); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, ",0\n"); \ + } \ + else if (TARGET_CM_EMBMEDANY) \ + { \ + fprintf (FILE, "\tsetx "); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, ",%%g5,%%g1\n\tjmp %%g1\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tsethi %%hi("); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, "),%%g1\n\tjmp %%g1+%%lo("); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, ")\n"); \ + } \ + if (!TARGET_CM_EMBMEDANY || flag_pic) \ + fprintf (FILE, "\tmov %%g1,%%o7\n"); \ + else if (big_delta) \ + fprintf (FILE, "\tnop\n"); \ + else \ + fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA); \ +} while (0) + +/* Define the parentheses used to group arithmetic operations + in assembler code. */ + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ + ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_') + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ + +#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) + +/* Print a memory address as an operand to reference that memory location. */ + +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ +{ register rtx base, index = 0; \ + int offset = 0; \ + register rtx addr = ADDR; \ + if (GET_CODE (addr) == REG) \ + fputs (reg_names[REGNO (addr)], FILE); \ + else if (GET_CODE (addr) == PLUS) \ + { \ + if (GET_CODE (XEXP (addr, 0)) == CONST_INT) \ + offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);\ + else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) \ + offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);\ + else \ + base = XEXP (addr, 0), index = XEXP (addr, 1); \ + fputs (reg_names[REGNO (base)], FILE); \ + if (index == 0) \ + fprintf (FILE, "%+d", offset); \ + 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 (); \ + } \ + else if (GET_CODE (addr) == MINUS \ + && GET_CODE (XEXP (addr, 1)) == LABEL_REF) \ + { \ + output_addr_const (FILE, XEXP (addr, 0)); \ + fputs ("-(", FILE); \ + output_addr_const (FILE, XEXP (addr, 1)); \ + fputs ("-.)", FILE); \ + } \ + else if (GET_CODE (addr) == LO_SUM) \ + { \ + output_operand (XEXP (addr, 0), 0); \ + fputs ("+%lo(", FILE); \ + output_address (XEXP (addr, 1)); \ + fputc (')', FILE); \ + } \ + else if (flag_pic && GET_CODE (addr) == CONST \ + && GET_CODE (XEXP (addr, 0)) == MINUS \ + && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST \ + && GET_CODE (XEXP (XEXP (XEXP (addr, 0), 1), 0)) == MINUS \ + && XEXP (XEXP (XEXP (XEXP (addr, 0), 1), 0), 1) == pc_rtx) \ + { \ + addr = XEXP (addr, 0); \ + output_addr_const (FILE, XEXP (addr, 0)); \ + /* Group the args of the second CONST in parenthesis. */ \ + fputs ("-(", FILE); \ + /* Skip past the second CONST--it does nothing for us. */\ + output_addr_const (FILE, XEXP (XEXP (addr, 1), 0)); \ + /* Close the parenthesis. */ \ + fputc (')', FILE); \ + } \ + else \ + { \ + output_addr_const (FILE, addr); \ + } \ +} + +/* 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}}, + + +/* The number of Pmode words for the setjmp buffer. */ +#define JMP_BUF_SIZE 12 + +#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (flag_pic) + +/* Declare functions defined in sparc.c and used in templates. */ + +extern char *doublemove_string (); +extern char *output_block_move (); +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 char *output_v9branch (); +extern char *singlemove_string (); + +extern void emit_v9_brxx_insn (); +extern void finalize_pic (); +extern void order_regs_for_local_alloc (); +extern void output_double_int (); +extern void output_function_epilogue (); +extern void output_function_prologue (); +extern void print_operand (); +extern void sparc_flat_output_function_epilogue (); +extern void sparc_flat_output_function_prologue (); + +extern int addrs_ok_for_ldd_peep (); +extern int arith10_double_operand (); +extern int arith10_operand (); +extern int arith11_double_operand (); +extern int arith11_operand (); +extern int arith_double_operand (); +extern int arith_operand (); +extern int call_operand_address (); +extern int cc_arithop (); +extern int cc_arithopn (); +extern int check_pic (); +extern int compute_frame_size (); +extern int data_segment_operand (); +extern int eligible_for_epilogue_delay (); +extern int eligible_for_return_delay (); +extern int emit_move_sequence (); +extern int extend_op (); +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 noov_compare_op (); +extern int pic_address_needs_scratch (); +extern int reg_or_0_operand (); +extern int reg_or_nonsymb_mem_operand (); +extern int reg_unused_after (); +extern int register_ok_for_ldd (); +extern int registers_ok_for_ldd_peep (); +extern int restore_operand (); +extern int short_branch (); +extern int small_int (); +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 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 char *sparc_v8plus_shift (); + +#ifdef __STDC__ +/* Function used for V8+ code generation. Returns 1 if the high + 32 bits of REG are 0 before INSN. */ +extern int sparc_check_64 (struct rtx_def *, struct rtx_def *); +extern int sparc_return_peephole_ok (struct rtx_def *, struct rtx_def *); +extern int compute_frame_size (int, int); +#endif + +/* Defined in flags.h, but insn-emit.c does not include flags.h. */ + +extern int flag_pic; diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md new file mode 100644 index 0000000..ccfde05 --- /dev/null +++ b/contrib/gcc/config/sparc/sparc.md @@ -0,0 +1,6684 @@ +;;- Machine description for SPARC chip for GNU C compiler +;; Copyright (C) 1987, 88, 89, 92-96, 1997 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. + +;; 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. + +;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; 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 +;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of +;; 'f' for all DF/TFmode values, including those that are specific to the v8. +;; +;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to +;; test TARGET_LIVE_G0 if we have TARGET_ARCH64. + +;; 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" + (const (symbol_ref "sparc_cpu_attr"))) + +;; Attribute for the instruction set. +;; At present we only need to distinguish v9/!v9, but for clarity we +;; test TARGET_V8 too. +(define_attr "isa" "v6,v8,v9,sparclet" + (const + (cond [(symbol_ref "TARGET_V9") (const_string "v9") + (symbol_ref "TARGET_V8") (const_string "v8") + (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")] + (const_string "v6")))) + +;; Architecture size. +(define_attr "arch" "arch32bit,arch64bit" + (const + (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")] + (const_string "arch32bit")))) + +;; Whether -mlive-g0 is in effect. +(define_attr "live_g0" "no,yes" + (const + (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")] + (const_string "no")))) + +;; Insn type. Used to default other attribute values. + +;; type "unary" insns have one input operand (1) and one output operand (0) +;; type "binary" insns have two input operands (1,2) and one output (0) +;; type "compare" insns have one or two input operands (0,1) and no output +;; type "call_no_delay_slot" is a call followed by an unimp instruction. + +(define_attr "type" + "move,unary,binary,compare,load,sload,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,return,address,imul,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc" + (const_string "binary")) + +;; Set true if insn uses call-clobbered intermediate register. +(define_attr "use_clobbered" "false,true" + (if_then_else (and (eq_attr "type" "address") + (match_operand 0 "clobbered_register" "")) + (const_string "true") + (const_string "false"))) + +;; Length (in # of insns). +(define_attr "length" "" + (cond [(eq_attr "type" "load,sload,fpload") + (if_then_else (match_operand 1 "symbolic_memory_operand" "") + (const_int 2) (const_int 1)) + + (eq_attr "type" "store,fpstore") + (if_then_else (match_operand 0 "symbolic_memory_operand" "") + (const_int 2) (const_int 1)) + + (eq_attr "type" "address") (const_int 2) + + (eq_attr "type" "binary") + (if_then_else (ior (match_operand 2 "arith_operand" "") + (match_operand 2 "arith_double_operand" "")) + (const_int 1) (const_int 3)) + + (eq_attr "type" "multi") (const_int 2) + + (eq_attr "type" "move,unary") + (if_then_else (ior (match_operand 1 "arith_operand" "") + (match_operand 1 "arith_double_operand" "")) + (const_int 1) (const_int 2))] + + (const_int 1))) + +(define_asm_attributes + [(set_attr "length" "1") + (set_attr "type" "multi")]) + +;; Attributes for instruction and branch scheduling + +(define_attr "in_call_delay" "false,true" + (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,return,multi") + (const_string "false") + (eq_attr "type" "load,fpload,store,fpstore") + (if_then_else (eq_attr "length" "1") + (const_string "true") + (const_string "false")) + (eq_attr "type" "address") + (if_then_else (eq_attr "use_clobbered" "false") + (const_string "true") + (const_string "false"))] + (if_then_else (eq_attr "length" "1") + (const_string "true") + (const_string "false")))) + +(define_delay (eq_attr "type" "call") + [(eq_attr "in_call_delay" "true") (nil) (nil)]) + +(define_attr "leaf_function" "false,true" + (const (symbol_ref "leaf_function"))) + + +(define_attr "in_return_delay" "false,true" + (if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu") + (eq_attr "length" "1")) + (eq_attr "leaf_function" "false")) + (match_insn "eligible_for_return_delay")) + (const_string "true") + (const_string "false"))) + +(define_delay (and (eq_attr "type" "return") + (eq_attr "isa" "v9")) + [(eq_attr "in_return_delay" "true") (nil) (nil)]) + +;; ??? Should implement the notion of predelay slots for floating point +;; branches. This would allow us to remove the nop always inserted before +;; a floating point branch. + +;; ??? It is OK for fill_simple_delay_slots to put load/store instructions +;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so. +;; This is because doing so will add several pipeline stalls to the path +;; that the load/store did not come from. Unfortunately, there is no way +;; to prevent fill_eager_delay_slots from using load/store without completely +;; disabling them. For the SPEC benchmark set, this is a serious lose, +;; because it prevents us from moving back the final store of inner loops. + +(define_attr "in_branch_delay" "false,true" + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") + (eq_attr "length" "1")) + (const_string "true") + (const_string "false"))) + +(define_attr "in_uncond_branch_delay" "false,true" + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") + (eq_attr "length" "1")) + (const_string "true") + (const_string "false"))) + +(define_attr "in_annul_branch_delay" "false,true" + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") + (eq_attr "length" "1")) + (const_string "true") + (const_string "false"))) + +(define_delay (eq_attr "type" "branch") + [(eq_attr "in_branch_delay" "true") + (nil) (eq_attr "in_annul_branch_delay" "true")]) + +(define_delay (eq_attr "type" "uncond_branch") + [(eq_attr "in_uncond_branch_delay" "true") + (nil) (nil)]) + +;; Function units of the SPARC + +;; (define_function_unit {name} {num-units} {n-users} {test} +;; {ready-delay} {issue-delay} [{conflict-list}]) + +;; The integer ALU. +;; (Noted only for documentation; units that take one cycle do not need to +;; be specified.) + +;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on +;; the inputs. + +;; (define_function_unit "alu" 1 0 +;; (eq_attr "type" "unary,binary,move,address") 1 0) + +;; ---- cypress CY7C602 scheduling: +;; Memory with load-delay of 1 (i.e., 2 cycle load). + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "cypress") + (eq_attr "type" "load,sload,fpload")) + 2 2) + +;; SPARC has two floating-point units: the FP ALU, +;; and the FP MUL/DIV/SQRT unit. +;; Instruction timings on the CY7C602 are as follows +;; FABSs 4 +;; FADDs/d 5/5 +;; FCMPs/d 4/4 +;; FDIVs/d 23/37 +;; FMOVs 4 +;; FMULs/d 5/7 +;; FNEGs 4 +;; FSQRTs/d 34/63 +;; FSUBs/d 5/5 +;; FdTOi/s 5/5 +;; FsTOi/d 5/5 +;; FiTOs/d 9/5 + +;; The CY7C602 can only support 2 fp isnsn simultaneously. +;; More insns cause the chip to stall. + +(define_function_unit "fp_alu" 1 0 + (and (eq_attr "cpu" "cypress") + (eq_attr "type" "fp,fpmove")) + 5 5) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "cypress") + (eq_attr "type" "fpmul")) + 7 7) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "cypress") + (eq_attr "type" "fpdivs,fpdivd")) + 37 37) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "cypress") + (eq_attr "type" "fpsqrt")) + 63 63) + +;; ----- The TMS390Z55 scheduling +;; The Supersparc can issue 1 - 3 insns per cycle: up to two integer, +;; one ld/st, one fp. +;; Memory delivers its result in one cycle to IU, zero cycles to FP + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "load,sload")) + 1 1) + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "fpload")) + 0 1) + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "store,fpstore")) + 1 1) + +(define_function_unit "shift" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "shift")) + 1 1) + +;; There are only two write ports to the integer register file +;; A store also uses a write port + +(define_function_unit "iwport" 2 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "load,sload,store,shift,ialu")) + 1 1) + +;; Timings; throughput/latency +;; FADD 1/3 add/sub, format conv, compar, abs, neg +;; FMUL 1/3 +;; FDIVs 4/6 +;; FDIVd 7/9 +;; FSQRTs 6/8 +;; FSQRTd 10/12 +;; IMUL 4/4 + +(define_function_unit "fp_alu" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "fp,fpmove,fpcmp")) + 3 1) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "fpmul")) + 3 1) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "fpdivs")) + 6 4) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "fpdivd")) + 9 7) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "fpsqrt")) + 12 10) + +(define_function_unit "fp_mds" 1 0 + (and (eq_attr "cpu" "supersparc") + (eq_attr "type" "imul")) + 4 4) + +;; ----- sparclet tsc701 scheduling +;; The tsc701 issues 1 insn per cycle. +;; Results may be written back out of order. + +;; Loads take 2 extra cycles to complete and 4 can be buffered at a time. + +(define_function_unit "tsc701_load" 4 1 + (and (eq_attr "cpu" "tsc701") + (eq_attr "type" "load,sload")) + 3 1) + +;; Stores take 2(?) extra cycles to complete. +;; It is desirable to not have any memory operation in the following 2 cycles. +;; (??? or 2 memory ops in the case of std). + +(define_function_unit "tsc701_store" 1 0 + (and (eq_attr "cpu" "tsc701") + (eq_attr "type" "store")) + 3 3 + [(eq_attr "type" "load,sload,store")]) + +;; The multiply unit has a latency of 5. +(define_function_unit "tsc701_mul" 1 0 + (and (eq_attr "cpu" "tsc701") + (eq_attr "type" "imul")) + 5 5) + +;; ----- The UltraSPARC-1 scheduling +;; UltraSPARC has two integer units. Shift instructions can only execute +;; on IE0. Condition code setting instructions, call, and jmpl (including +;; the ret and retl pseudo-instructions) can only execute on IE1. +;; Branch on register uses IE1, but branch on condition code does not. +;; Conditional moves take 2 cycles. No other instruction can issue in the +;; same cycle as a conditional move. +;; Multiply and divide take many cycles during which no other instructions +;; can issue. +;; Memory delivers its result in two cycles (except for signed loads, +;; which take one cycle more). One memory instruction can be issued per +;; cycle. + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "load,fpload")) + 2 1) + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "sload")) + 3 1) + +(define_function_unit "memory" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "store,fpstore")) + 1 1) + +(define_function_unit "ieu" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "ialu,binary,shift,compare,cmove,call")) + 1 1) + +(define_function_unit "ieu_shift" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "shift")) + 1 1) + +(define_function_unit "ieu_shift" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "cmove")) + 2 1) + +;; Timings; throughput/latency +;; FMOV 1/1 fmov, fabs, fneg +;; FMOVcc 1/2 +;; FADD 1/4 add/sub, format conv, compar +;; FMUL 1/4 +;; FDIVs 12/12 +;; FDIVd 22/22 +;; FSQRTs 12/12 +;; FSQRTd 22/22 +;; FCMP takes 1 cycle to branch, 2 cycles to conditional move. + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpmove")) + 1 1) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpcmove")) + 2 1) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fp")) + 4 1) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpcmp")) + 2 1) + +(define_function_unit "fmul" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpmul")) + 4 1) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpcmove")) + 2 1) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpdivs")) + 12 12) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpdivd")) + 22 22) + +(define_function_unit "fadd" 1 0 + (and (eq_attr "cpu" "ultrasparc") + (eq_attr "type" "fpsqrt")) + 12 12) + +;; Compare instructions. +;; This controls RTL generation and register allocation. + +;; We generate RTL for comparisons and branches by having the cmpxx +;; patterns store away the operands. Then, the scc and bcc patterns +;; emit RTL for both the compare and the branch. +;; +;; We do this because we want to generate different code for an sne and +;; seq insn. In those cases, if the second operand of the compare is not +;; const0_rtx, we want to compute the xor of the two operands and test +;; it against zero. +;; +;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match +;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc +;; insns that actually require more than one machine instruction. + +;; Put cmpsi first among compare insns so it matches two CONST_INT operands. + +(define_expand "cmpsi" + [(set (reg:CC 100) + (compare:CC (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "arith_operand" "")))] + "" + " +{ + sparc_compare_op0 = operands[0]; + sparc_compare_op1 = operands[1]; + DONE; +}") + +(define_expand "cmpdi" + [(set (reg:CCX 100) + (compare:CCX (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "arith_double_operand" "")))] + "TARGET_ARCH64 || TARGET_V8PLUS" + " +{ + sparc_compare_op0 = operands[0]; + sparc_compare_op1 = operands[1]; + DONE; +}") + +(define_expand "cmpsf" + ;; The 96 here isn't ever used by anyone. + [(set (reg:CCFP 96) + (compare:CCFP (match_operand:SF 0 "register_operand" "") + (match_operand:SF 1 "register_operand" "")))] + "TARGET_FPU" + " +{ + sparc_compare_op0 = operands[0]; + sparc_compare_op1 = operands[1]; + DONE; +}") + +(define_expand "cmpdf" + ;; The 96 here isn't ever used by anyone. + [(set (reg:CCFP 96) + (compare:CCFP (match_operand:DF 0 "register_operand" "") + (match_operand:DF 1 "register_operand" "")))] + "TARGET_FPU" + " +{ + sparc_compare_op0 = operands[0]; + sparc_compare_op1 = operands[1]; + DONE; +}") + +(define_expand "cmptf" + ;; The 96 here isn't ever used by anyone. + [(set (reg:CCFP 96) + (compare:CCFP (match_operand:TF 0 "register_operand" "") + (match_operand:TF 1 "register_operand" "")))] + "TARGET_FPU" + " +{ + sparc_compare_op0 = operands[0]; + sparc_compare_op1 = operands[1]; + DONE; +}") + +;; Now the compare DEFINE_INSNs. + +(define_insn "*cmpsi_insn" + [(set (reg:CC 100) + (compare:CC (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "arith_operand" "rI")))] + "" + "cmp %0,%1" + [(set_attr "type" "compare")]) + +(define_insn "*cmpdi_sp64" + [(set (reg:CCX 100) + (compare:CCX (match_operand:DI 0 "register_operand" "r") + (match_operand:DI 1 "arith_double_operand" "rHI")))] + "TARGET_ARCH64" + "cmp %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") + (match_operand:SF 2 "register_operand" "f")))] + "TARGET_FPU" + "* +{ + if (TARGET_V9) + return \"fcmpes %0,%1,%2\"; + return \"fcmpes %1,%2\"; +}" + [(set_attr "type" "fpcmp")]) + +(define_insn "*cmpdf_fpe" + [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") + (compare:CCFPE (match_operand:DF 1 "register_operand" "e") + (match_operand:DF 2 "register_operand" "e")))] + "TARGET_FPU" + "* +{ + if (TARGET_V9) + return \"fcmped %0,%1,%2\"; + return \"fcmped %1,%2\"; +}" + [(set_attr "type" "fpcmp")]) + +(define_insn "*cmptf_fpe" + [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") + (compare:CCFPE (match_operand:TF 1 "register_operand" "e") + (match_operand:TF 2 "register_operand" "e")))] + "TARGET_FPU && TARGET_HARD_QUAD" + "* +{ + if (TARGET_V9) + return \"fcmpeq %0,%1,%2\"; + return \"fcmpeq %1,%2\"; +}" + [(set_attr "type" "fpcmp")]) + +(define_insn "*cmpsf_fp" + [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") + (compare:CCFP (match_operand:SF 1 "register_operand" "f") + (match_operand:SF 2 "register_operand" "f")))] + "TARGET_FPU" + "* +{ + if (TARGET_V9) + return \"fcmps %0,%1,%2\"; + return \"fcmps %1,%2\"; +}" + [(set_attr "type" "fpcmp")]) + +(define_insn "*cmpdf_fp" + [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") + (compare:CCFP (match_operand:DF 1 "register_operand" "e") + (match_operand:DF 2 "register_operand" "e")))] + "TARGET_FPU" + "* +{ + if (TARGET_V9) + return \"fcmpd %0,%1,%2\"; + return \"fcmpd %1,%2\"; +}" + [(set_attr "type" "fpcmp")]) + +(define_insn "*cmptf_fp" + [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") + (compare:CCFP (match_operand:TF 1 "register_operand" "e") + (match_operand:TF 2 "register_operand" "e")))] + "TARGET_FPU && TARGET_HARD_QUAD" + "* +{ + if (TARGET_V9) + return \"fcmpq %0,%1,%2\"; + return \"fcmpq %1,%2\"; +}" + [(set_attr "type" "fpcmp")]) + +;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this +;; without jumps using the addx/subx instructions. For seq/sne on v9 we use +;; the same code as v8 (the addx/subx method has more applications). The +;; exception to this is "reg != 0" which can be done in one instruction on v9 +;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do +;; branches. + +;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they +;; generate addcc/subcc instructions. + +(define_expand "seqsi_special" + [(set (match_dup 3) + (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "register_operand" ""))) + (parallel [(set (match_operand:SI 0 "register_operand" "") + (eq:SI (match_dup 3) (const_int 0))) + (clobber (reg:CC 100))])] + "! TARGET_LIVE_G0" + "{ operands[3] = gen_reg_rtx (SImode); }") + +(define_expand "seqdi_special" + [(set (match_dup 3) + (xor:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "register_operand" ""))) + (set (match_operand:DI 0 "register_operand" "") + (eq:DI (match_dup 3) (const_int 0)))] + "TARGET_ARCH64" + "{ operands[3] = gen_reg_rtx (DImode); }") + +(define_expand "snesi_special" + [(set (match_dup 3) + (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "register_operand" ""))) + (parallel [(set (match_operand:SI 0 "register_operand" "") + (ne:SI (match_dup 3) (const_int 0))) + (clobber (reg:CC 100))])] + "! TARGET_LIVE_G0" + "{ operands[3] = gen_reg_rtx (SImode); }") + +(define_expand "snedi_special" + [(set (match_dup 3) + (xor:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "register_operand" ""))) + (set (match_operand:DI 0 "register_operand" "") + (ne:DI (match_dup 3) (const_int 0)))] + "TARGET_ARCH64" + "{ operands[3] = gen_reg_rtx (DImode); }") + +(define_expand "seqdi_special_trunc" + [(set (match_dup 3) + (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)))] + "TARGET_ARCH64" + "{ operands[3] = gen_reg_rtx (DImode); }") + +(define_expand "snedi_special_trunc" + [(set (match_dup 3) + (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)))] + "TARGET_ARCH64" + "{ operands[3] = gen_reg_rtx (DImode); }") + +(define_expand "seqsi_special_extend" + [(set (match_dup 3) + (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))) + (clobber (reg:CC 100))])] + "TARGET_ARCH64" + "{ operands[3] = gen_reg_rtx (SImode); }") + +(define_expand "snesi_special_extend" + [(set (match_dup 3) + (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))) + (clobber (reg:CC 100))])] + "TARGET_ARCH64" + "{ operands[3] = gen_reg_rtx (SImode); }") + +;; ??? v9: Operand 0 needs a mode, so SImode was chosen. +;; However, the code handles both SImode and DImode. +(define_expand "seq" + [(set (match_operand:SI 0 "intreg_operand" "") + (eq:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (GET_MODE (sparc_compare_op0) == SImode) + { + rtx pat; + + if (GET_MODE (operands[0]) == SImode) + pat = gen_seqsi_special (operands[0], sparc_compare_op0, + sparc_compare_op1); + else if (! TARGET_ARCH64) + FAIL; + else + pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0, + sparc_compare_op1); + emit_insn (pat); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == DImode) + { + rtx pat; + + if (! TARGET_ARCH64) + FAIL; + else if (GET_MODE (operands[0]) == SImode) + pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0, + sparc_compare_op1); + else + pat = gen_seqdi_special (operands[0], sparc_compare_op0, + sparc_compare_op1); + emit_insn (pat); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); + emit_insn (gen_sne (operands[0])); + DONE; + } + else if (TARGET_V9) + { + if (gen_v9_scc (EQ, operands)) + DONE; + /* fall through */ + } + operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); +}") + +;; ??? v9: Operand 0 needs a mode, so SImode was chosen. +;; However, the code handles both SImode and DImode. +(define_expand "sne" + [(set (match_operand:SI 0 "intreg_operand" "") + (ne:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (GET_MODE (sparc_compare_op0) == SImode) + { + rtx pat; + + if (GET_MODE (operands[0]) == SImode) + pat = gen_snesi_special (operands[0], sparc_compare_op0, + sparc_compare_op1); + else if (! TARGET_ARCH64) + FAIL; + else + pat = gen_snesi_special_extend (operands[0], sparc_compare_op0, + sparc_compare_op1); + emit_insn (pat); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == DImode) + { + rtx pat; + + if (! TARGET_ARCH64) + FAIL; + else if (GET_MODE (operands[0]) == SImode) + pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0, + sparc_compare_op1); + else + pat = gen_snedi_special (operands[0], sparc_compare_op0, + sparc_compare_op1); + emit_insn (pat); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); + emit_insn (gen_sne (operands[0])); + DONE; + } + else if (TARGET_V9) + { + if (gen_v9_scc (NE, operands)) + DONE; + /* fall through */ + } + operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sgt" + [(set (match_operand:SI 0 "intreg_operand" "") + (gt:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); + emit_insn (gen_sne (operands[0])); + DONE; + } + else if (TARGET_V9) + { + if (gen_v9_scc (GT, operands)) + DONE; + /* fall through */ + } + operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "slt" + [(set (match_operand:SI 0 "intreg_operand" "") + (lt:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); + emit_insn (gen_sne (operands[0])); + DONE; + } + else if (TARGET_V9) + { + if (gen_v9_scc (LT, operands)) + DONE; + /* fall through */ + } + operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sge" + [(set (match_operand:SI 0 "intreg_operand" "") + (ge:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); + emit_insn (gen_sne (operands[0])); + DONE; + } + else if (TARGET_V9) + { + if (gen_v9_scc (GE, operands)) + DONE; + /* fall through */ + } + operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sle" + [(set (match_operand:SI 0 "intreg_operand" "") + (le:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); + emit_insn (gen_sne (operands[0])); + DONE; + } + else if (TARGET_V9) + { + if (gen_v9_scc (LE, operands)) + DONE; + /* fall through */ + } + operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sgtu" + [(set (match_operand:SI 0 "intreg_operand" "") + (gtu:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (! TARGET_V9) + { + rtx tem; + + /* We can do ltu easily, so if both operands are registers, swap them and + do a LTU. */ + if ((GET_CODE (sparc_compare_op0) == REG + || GET_CODE (sparc_compare_op0) == SUBREG) + && (GET_CODE (sparc_compare_op1) == REG + || GET_CODE (sparc_compare_op1) == SUBREG)) + { + tem = sparc_compare_op0; + sparc_compare_op0 = sparc_compare_op1; + sparc_compare_op1 = tem; + emit_insn (gen_sltu (operands[0])); + DONE; + } + } + else + { + if (gen_v9_scc (GTU, operands)) + DONE; + } + operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sltu" + [(set (match_operand:SI 0 "intreg_operand" "") + (ltu:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (TARGET_V9) + { + if (gen_v9_scc (LTU, operands)) + DONE; + } + operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sgeu" + [(set (match_operand:SI 0 "intreg_operand" "") + (geu:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (TARGET_V9) + { + if (gen_v9_scc (GEU, operands)) + DONE; + } + operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "sleu" + [(set (match_operand:SI 0 "intreg_operand" "") + (leu:SI (match_dup 1) (const_int 0)))] + "! TARGET_LIVE_G0" + " +{ + if (! TARGET_V9) + { + rtx tem; + + /* We can do geu easily, so if both operands are registers, swap them and + do a GEU. */ + if ((GET_CODE (sparc_compare_op0) == REG + || GET_CODE (sparc_compare_op0) == SUBREG) + && (GET_CODE (sparc_compare_op1) == REG + || GET_CODE (sparc_compare_op1) == SUBREG)) + { + tem = sparc_compare_op0; + sparc_compare_op0 = sparc_compare_op1; + sparc_compare_op1 = tem; + emit_insn (gen_sgeu (operands[0])); + DONE; + } + } + else + { + if (gen_v9_scc (LEU, operands)) + DONE; + } + operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); +}") + +;; 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. + +(define_insn "*snesi_zero" + [(set (match_operand:SI 0 "register_operand" "=r") + (ne:SI (match_operand:SI 1 "register_operand" "r") + (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")]) + +(define_insn "*neg_snesi_zero" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r") + (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")]) + +(define_insn "*snesi_zero_extend" + [(set (match_operand:DI 0 "register_operand" "=r") + (ne:SI (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_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_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_insn "*snedi_zero_trunc" + [(set (match_operand:SI 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_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")]) + +(define_insn "*neg_seqsi_zero" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r") + (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")]) + +(define_insn "*seqsi_zero_extend" + [(set (match_operand:DI 0 "register_operand" "=r") + (eq:SI (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_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_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_insn "*seqdi_zero_trunc" + [(set (match_operand:SI 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")]) + +;; 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. + +(define_insn "*x_plus_i_ne_0" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r") + (const_int 0)) + (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_insn "*x_minus_i_ne_0" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 2 "register_operand" "r") + (ne:SI (match_operand:SI 1 "register_operand" "r") + (const_int 0)))) + (clobber (reg:CC 100))] + "! TARGET_LIVE_G0" + "subcc %%g0,%1,%%g0\;subx %2,0,%0" + [(set_attr "length" "2")]) + +(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") + (const_int 0)) + (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_insn "*x_minus_i_eq_0" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 2 "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\;addx %2,-1,%0" + [(set_attr "length" "2")]) + +;; 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. + +(define_insn "*sltu_insn" + [(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")]) + +(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")]) + +;; ??? Combine should canonicalize these next two to the same pattern. +(define_insn "*neg_sltu_minus_x" + [(set (match_operand:SI 0 "register_operand" "=r") + (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")]) + +(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")]) + +(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")]) + +(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")]) + +;; 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 +;; versions for v9. + +(define_insn "*sltu_plus_x" + [(set (match_operand:SI 0 "register_operand" "=r") + (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")]) + +(define_insn "*sltu_plus_x_plus_y" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) + (plus:SI (match_operand:SI 1 "arith_operand" "%r") + (match_operand:SI 2 "arith_operand" "rI"))))] + "" + "addx %1,%2,%0") + +(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")]) + +;; ??? 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") + (match_operand:SI 2 "arith_operand" "rI")) + (ltu:SI (reg:CC 100) (const_int 0))))] + "" + "subx %1,%2,%0") + +(define_insn "*x_minus_sltu_plus_y" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "register_operand" "r") + (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) + (match_operand:SI 2 "arith_operand" "rI"))))] + "" + "subx %1,%2,%0") + +(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")]) + +(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")]) + +(define_split + [(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)]))] + ;; 32 bit LTU/GEU are better implemented using addx/subx + "TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG + && (GET_MODE (operands[1]) == CCXmode + || (GET_CODE (operands[2]) != LTU && GET_CODE (operands[2]) != GEU))" + [(set (match_dup 0) (const_int 0)) + (set (match_dup 0) + (if_then_else:SI (match_op_dup:SI 2 [(match_dup 1) (const_int 0)]) + (const_int 1) + (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 + +;; The quad-word fp compare library routines all return nonzero to indicate +;; true, which is different from the equivalent libgcc routines, so we must +;; handle them specially here. + +(define_expand "beq" + [(set (pc) + (if_then_else (eq (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode) + { + emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); + emit_jump_insn (gen_bne (operands[0])); + DONE; + } + operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bne" + [(set (pc) + (if_then_else (ne (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode) + { + emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); + emit_jump_insn (gen_bne (operands[0])); + DONE; + } + operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bgt" + [(set (pc) + (if_then_else (gt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode) + { + emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); + emit_jump_insn (gen_bne (operands[0])); + DONE; + } + operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bgtu" + [(set (pc) + (if_then_else (gtu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "blt" + [(set (pc) + (if_then_else (lt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode) + { + emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); + emit_jump_insn (gen_bne (operands[0])); + DONE; + } + operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bltu" + [(set (pc) + (if_then_else (ltu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bge" + [(set (pc) + (if_then_else (ge (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode) + { + emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); + emit_jump_insn (gen_bne (operands[0])); + DONE; + } + operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bgeu" + [(set (pc) + (if_then_else (geu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "ble" + [(set (pc) + (if_then_else (le (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode) + { + emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]); + DONE; + } + else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) + { + emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); + emit_jump_insn (gen_bne (operands[0])); + DONE; + } + operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); +}") + +(define_expand "bleu" + [(set (pc) + (if_then_else (leu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); +}") + +;; Now match both normal and inverted jump. + +(define_insn "*normal_branch" + [(set (pc) + (if_then_else (match_operator 0 "noov_compare_op" + [(reg 100) (const_int 0)]) + (label_ref (match_operand 1 "" "")) + (pc)))] + "" + "* +{ + return output_cbranch (operands[0], 1, 0, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence, insn); +}" + [(set_attr "type" "branch")]) + +(define_insn "*inverted_branch" + [(set (pc) + (if_then_else (match_operator 0 "noov_compare_op" + [(reg 100) (const_int 0)]) + (pc) + (label_ref (match_operand 1 "" ""))))] + "" + "* +{ + return output_cbranch (operands[0], 1, 1, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence, insn); +}" + [(set_attr "type" "branch")]) + +(define_insn "*normal_fp_branch" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand:CCFP 0 "fcc_reg_operand" "c") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "* +{ + return output_cbranch (operands[1], 2, 0, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence, insn); +}" + [(set_attr "type" "branch")]) + +(define_insn "*inverted_fp_branch" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand:CCFP 0 "fcc_reg_operand" "c") + (const_int 0)]) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "* +{ + return output_cbranch (operands[1], 2, 1, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence, insn); +}" + [(set_attr "type" "branch")]) + +(define_insn "*normal_fpe_branch" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand:CCFPE 0 "fcc_reg_operand" "c") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "* +{ + return output_cbranch (operands[1], 2, 0, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence, insn); +}" + [(set_attr "type" "branch")]) + +(define_insn "*inverted_fpe_branch" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand:CCFPE 0 "fcc_reg_operand" "c") + (const_int 0)]) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "* +{ + return output_cbranch (operands[1], 2, 1, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence, insn); +}" + [(set_attr "type" "branch")]) + +;; Sparc V9-specific jump insns. None of these are guaranteed to be +;; in the architecture. + +;; There are no 32 bit brreg insns. + +(define_insn "*normal_int_branch_sp64" + [(set (pc) + (if_then_else (match_operator 0 "v9_regcmp_op" + [(match_operand:DI 1 "register_operand" "r") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "TARGET_ARCH64" + "* +{ + return output_v9branch (operands[0], 1, 2, 0, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence); +}" + [(set_attr "type" "branch")]) + +(define_insn "*inverted_int_branch_sp64" + [(set (pc) + (if_then_else (match_operator 0 "v9_regcmp_op" + [(match_operand:DI 1 "register_operand" "r") + (const_int 0)]) + (pc) + (label_ref (match_operand 2 "" ""))))] + "TARGET_ARCH64" + "* +{ + return output_v9branch (operands[0], 1, 2, 1, + final_sequence && INSN_ANNULLED_BRANCH_P (insn), + ! final_sequence); +}" + [(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")]) + +(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" + [(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")]) + +;; 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")]) + +(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" + "* +{ + /* 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); + + 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")]) + +;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add? + +(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")]) + +(define_insn "*sethi_di_sp32" + [(set (match_operand:DI 0 "register_operand" "=r") + (high:DI (match_operand 1 "" "")))] + "! TARGET_ARCH64 && check_pic (1)" + "* +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + + if (GET_CODE (op1) == CONST_INT) + { + operands[0] = operand_subword (op0, 1, 0, DImode); + output_asm_insn (\"sethi %%hi(%a1),%0\", operands); + + operands[0] = operand_subword (op0, 0, 0, DImode); + if (INTVAL (op1) < 0) + return \"mov -1,%0\"; + else + return \"mov 0,%0\"; + } + else if (GET_CODE (op1) == CONST_DOUBLE) + { + operands[0] = operand_subword (op0, 1, 0, DImode); + operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1)); + output_asm_insn (\"sethi %%hi(%a1),%0\", operands); + + operands[0] = operand_subword (op0, 0, 0, DImode); + operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1)); + return singlemove_string (operands); + } + 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))])] + "TARGET_ARCH64" + "") + +(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)" + "* +{ +#if HOST_BITS_PER_WIDE_INT == 32 + rtx high, low; + + split_double (operands[1], &high, &low); + + if (high == const0_rtx) + { + operands[1] = low; + output_asm_insn (\"sethi %%hi(%a1),%0\", operands); + } + else + { + operands[1] = high; + output_asm_insn (singlemove_string (operands), operands); + + 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); + } +#else + rtx op = operands[1]; + + if (! SPARC_SETHI_P (INTVAL(op))) + { + operands[1] = GEN_INT (INTVAL (op) >> 32); + output_asm_insn (singlemove_string (operands), operands); + + output_asm_insn (\"sllx %0,32,%0\", operands); + if (INTVAL (op) & 0xffffffff) + { + operands[1] = GEN_INT (INTVAL (op) & 0xffffffff); + output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands); + } + } + else + { + output_asm_insn (\"sethi %%hi(%a1),%0\", operands); + } +#endif + + 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. + +(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" + [(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") + (set_attr "length" "1")]) + +;; WARNING: %0 gets %hi(%1)+%g4. +;; You cannot OR in %lo(%1), it must be added in. + +(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" + [(set_attr "type" "move") + (set_attr "length" "2")]) + +(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" + [(set_attr "type" "move") + (set_attr "length" "5")]) + +;; Move instructions + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, QImode)) + DONE; +}") + +(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") + (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_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, HImode)) + DONE; +}") + +(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)" + "@ + mov %1,%0 + sethi %%hi(%a1),%0 + lduh %1,%0 + sth %r1,%0" + [(set_attr "type" "move,move,load,store") + (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")]) + +(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_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, SImode)) + DONE; +}") + +;; We must support both 'r' and 'f' registers here, because combine may +;; convert SFmode hard registers to SImode hard registers when simplifying +;; subreg sets. + +;; 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 "*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")]) + +(define_expand "movdi" + [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, DImode)) + 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)" + "* +{ + 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 V9 deprecates std. Split it here. +(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. +(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]);") + +(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)" + "* +{ + 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)" + "* +{ + switch (which_alternative) + { + 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 (); + } +}" + [(set_attr "type" "move,move,load,store,fp,fpload,fpstore") + (set_attr "length" "1,2,1,1,1,1,1")]) + +;; ??? 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"))] + "TARGET_FPU + && GET_CODE (operands[1]) == CONST_DOUBLE + && (GET_CODE (operands[0]) == REG + || fp_zero_operand (operands[1]))" + "* +{ + switch (which_alternative) + { + 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 (); + } +}" + [(set_attr "type" "fpload,fpmove,store,load") + (set_attr "length" "1,1,1,2")]) + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, SFmode)) + DONE; +}") + +(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"))] + "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")]) + +;; 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"))] + "! 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")]) + +;; 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 "*movdf_const_insn" + [(set (match_operand:DF 0 "general_operand" "=?r,e,o,d") + (match_operand:DF 1 "" "?F,m,G,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_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\"; + } + else + { + operands[1] = adj_offsettable_operand (operands[0], 4); + return \"st %%g0,%0\;st %%g0,%1\"; + } + case 3: + return \"fzero %0\"; + default: + abort (); + } +}" + [(set_attr "type" "load,fpload,store,fpmove") + (set_attr "length" "3,3,3,1")]) + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, DFmode)) + DONE; +}") + +(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"))] + "TARGET_FPU + && (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"))] + "! TARGET_FPU + && (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")]) + +;; Must handle overlapping registers here, since parameters can be unaligned +;; in registers. + +(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))] + " +{ + rtx first_set = operand_subword (operands[0], 0, 0, DFmode); + rtx second_use = operand_subword (operands[1], 1, 0, DFmode); + + if (REGNO (first_set) == REGNO (second_use)) + { + 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); + } + 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; + } +}") + +(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" + "* +{ + output_asm_insn (\"sethi %%hi(%a0),%2\", operands); + if (which_alternative == 0) + return \"std %1,[%2+%%lo(%a0)]\"; + 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 (); + } +}" + [(set_attr "type" "load,fpload,store") + (set_attr "length" "5,5,5")]) + +(define_expand "movtf" + [(set (match_operand:TF 0 "general_operand" "") + (match_operand:TF 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, TFmode)) + DONE; +}") + +(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"))] + "TARGET_FPU + && (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")]) + +;; 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"))] + "! TARGET_FPU + && (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" "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" + "* +{ + output_asm_insn (\"sethi %%hi(%a0),%2\", operands); + if (which_alternative == 0) + return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; + 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")]) + +;; Sparc V9 conditional move instructions. + +;; We can handle larger constants here for some flavors, but for now we keep +;; it simple and only allow those constants supported by all flavours. +;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand +;; 3 contains the constant if one is present, but we handle either for +;; generality (sparc.c puts a constant in operand 2). + +(define_expand "movqicc" + [(set (match_operand:QI 0 "register_operand" "") + (if_then_else:QI (match_operand 1 "comparison_operator" "") + (match_operand:QI 2 "arith10_operand" "") + (match_operand:QI 3 "arith10_operand" "")))] + "TARGET_V9" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (GET_MODE (sparc_compare_op0) == DImode + && ! TARGET_ARCH64) + FAIL; + + if (sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode + && v9_regcmp_p (code)) + { + operands[1] = gen_rtx_fmt_ee (code, DImode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + } +}") + +(define_expand "movhicc" + [(set (match_operand:HI 0 "register_operand" "") + (if_then_else:HI (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "arith10_operand" "") + (match_operand:HI 3 "arith10_operand" "")))] + "TARGET_V9" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (GET_MODE (sparc_compare_op0) == DImode + && ! TARGET_ARCH64) + FAIL; + + if (sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode + && v9_regcmp_p (code)) + { + operands[1] = gen_rtx_fmt_ee (code, DImode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + } +}") + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "arith10_operand" "") + (match_operand:SI 3 "arith10_operand" "")))] + "TARGET_V9" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + enum machine_mode op0_mode = GET_MODE (sparc_compare_op0); + + 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)))) + { + operands[1] = gen_rtx_fmt_ee (code, op0_mode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), + cc_reg, const0_rtx); + } +}") + +(define_expand "movdicc" + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (match_operand 1 "comparison_operator" "") + (match_operand:DI 2 "arith10_double_operand" "") + (match_operand:DI 3 "arith10_double_operand" "")))] + "TARGET_ARCH64" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode + && v9_regcmp_p (code)) + { + operands[1] = gen_rtx_fmt_ee (code, DImode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), + cc_reg, const0_rtx); + } +}") + +(define_expand "movsfcc" + [(set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "register_operand" "") + (match_operand:SF 3 "register_operand" "")))] + "TARGET_V9 && TARGET_FPU" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (GET_MODE (sparc_compare_op0) == DImode + && ! TARGET_ARCH64) + FAIL; + + if (sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode + && v9_regcmp_p (code)) + { + operands[1] = gen_rtx_fmt_ee (code, DImode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + } +}") + +(define_expand "movdfcc" + [(set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (match_operand 1 "comparison_operator" "") + (match_operand:DF 2 "register_operand" "") + (match_operand:DF 3 "register_operand" "")))] + "TARGET_V9 && TARGET_FPU" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (GET_MODE (sparc_compare_op0) == DImode + && ! TARGET_ARCH64) + FAIL; + + if (sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode + && v9_regcmp_p (code)) + { + operands[1] = gen_rtx_fmt_ee (code, DImode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + } +}") + +(define_expand "movtfcc" + [(set (match_operand:TF 0 "register_operand" "") + (if_then_else:TF (match_operand 1 "comparison_operator" "") + (match_operand:TF 2 "register_operand" "") + (match_operand:TF 3 "register_operand" "")))] + "TARGET_V9 && TARGET_FPU" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (GET_MODE (sparc_compare_op0) == DImode + && ! TARGET_ARCH64) + FAIL; + + if (sparc_compare_op1 == const0_rtx + && GET_CODE (sparc_compare_op0) == REG + && GET_MODE (sparc_compare_op0) == DImode + && v9_regcmp_p (code)) + { + operands[1] = gen_rtx_fmt_ee (code, DImode, + sparc_compare_op0, sparc_compare_op1); + } + else + { + rtx cc_reg = gen_compare_reg (code, + sparc_compare_op0, sparc_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + } +}") + +;; Conditional move define_insns. + +(define_insn "*movqi_cc_sp64" + [(set (match_operand:QI 0 "register_operand" "=r,r") + (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")))] + "TARGET_V9" + "@ + mov%C1 %x2,%3,%0 + mov%c1 %x2,%4,%0" + [(set_attr "type" "cmove")]) + +(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")))] + "TARGET_V9" + "@ + mov%C1 %x2,%3,%0 + mov%c1 %x2,%4,%0" + [(set_attr "type" "cmove")]) + +(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")))] + "TARGET_V9" + "@ + mov%C1 %x2,%3,%0 + mov%c1 %x2,%4,%0" + [(set_attr "type" "cmove")]) + +;; ??? The constraints of operands 3,4 need work. +(define_insn "*movdi_cc_sp64" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (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")))] + "TARGET_ARCH64" + "@ + mov%C1 %x2,%3,%0 + mov%c1 %x2,%4,%0" + [(set_attr "type" "cmove")]) + +(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")))] + "TARGET_V9 && TARGET_FPU" + "@ + fmovs%C1 %x2,%3,%0 + fmovs%c1 %x2,%4,%0" + [(set_attr "type" "fpcmove")]) + +(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")))] + "TARGET_V9 && TARGET_FPU" + "@ + fmovd%C1 %x2,%3,%0 + fmovd%c1 %x2,%4,%0" + [(set_attr "type" "fpcmove")]) + +(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")))] + "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" + "@ + fmovq%C1 %x2,%3,%0 + fmovq%c1 %x2,%4,%0" + [(set_attr "type" "fpcmove")]) + +(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")))] + "TARGET_ARCH64" + "@ + movr%D1 %2,%r3,%0 + movr%d1 %2,%r4,%0" + [(set_attr "type" "cmove")]) + +(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")))] + "TARGET_ARCH64" + "@ + movr%D1 %2,%r3,%0 + movr%d1 %2,%r4,%0" + [(set_attr "type" "cmove")]) + +(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")))] + "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\"; +}" + [(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")]) + +;; ??? The constraints of operands 3,4 need work. +(define_insn "*movdi_cc_reg_sp64" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (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")))] + "TARGET_ARCH64" + "@ + movr%D1 %2,%r3,%0 + movr%d1 %2,%r4,%0" + [(set_attr "type" "cmove")]) + +(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")))] + "TARGET_ARCH64 && TARGET_FPU" + "@ + fmovrs%D1 %2,%3,%0 + fmovrs%d1 %2,%4,%0" + [(set_attr "type" "fpcmove")]) + +(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")))] + "TARGET_ARCH64 && TARGET_FPU" + "@ + fmovrd%D1 %2,%3,%0 + fmovrd%d1 %2,%4,%0" + [(set_attr "type" "fpcmove")]) + +(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")))] + "TARGET_ARCH64 && TARGET_FPU" + "@ + fmovrq%D1 %2,%3,%0 + fmovrq%d1 %2,%4,%0" + [(set_attr "type" "fpcmove")]) + +;;- zero extension instructions + +;; These patterns originally accepted general_operands, however, slightly +;; better code is generated by only accepting register_operands, and then +;; letting combine generate the ldu[hb] insns. + +(define_expand "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_16 = GEN_INT (16); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, + op1_subword), + shift_16)); + emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); + DONE; +}") + +(define_insn "*zero_extendhisi2_insn" + [(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")]) + +(define_expand "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] + "" + "") + +(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")))] + "GET_CODE (operands[1]) != CONST_INT" + "@ + and %1,0xff,%0 + ldub %1,%0" + [(set_attr "type" "unary,load") + (set_attr "length" "1")]) + +(define_expand "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] + "" + "") + +(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")))] + "GET_CODE (operands[1]) != CONST_INT" + "@ + and %1,0xff,%0 + ldub %1,%0" + [(set_attr "type" "unary,load") + (set_attr "length" "1")]) + +(define_expand "zero_extendqidi2" + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI (match_operand:QI 1 "register_operand" "")))] + "TARGET_ARCH64" + "") + +(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")))] + "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT" + "@ + and %1,0xff,%0 + ldub %1,%0" + [(set_attr "type" "unary,load") + (set_attr "length" "1")]) + +(define_expand "zero_extendhidi2" + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI (match_operand:HI 1 "register_operand" "")))] + "TARGET_ARCH64" + " +{ + rtx temp = gen_reg_rtx (DImode); + rtx shift_48 = GEN_INT (48); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, + op1_subword), + shift_48)); + emit_insn (gen_lshrdi3 (operand0, temp, shift_48)); + DONE; +}") + +(define_insn "*zero_extendhidi2_insn" + [(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")]) + + +;; ??? Write truncdisi pattern using sra? + +(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" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))] + "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT" + "@ + srl %1,0,%0 + lduw %1,%0" + [(set_attr "type" "unary,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")]) + +;; Simplify comparisons of extended values. + +(define_insn "*cmp_zero_extendqisi2" + [(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")]) + +(define_insn "*cmp_zero_extendqisi2_set" + [(set (reg:CC 100) + (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_dup 1)))] + "" + "andcc %1,0xff,%0" + [(set_attr "type" "unary")]) + +;; Similarly, handle SI->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")]) + +(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))] + "" + "andcc %1,0xff,%0" + [(set_attr "type" "unary")]) + +;;- sign extension instructions + +;; These patterns originally accepted general_operands, however, slightly +;; better code is generated by only accepting register_operands, and then +;; letting combine generate the lds[hb] insns. + +(define_expand "extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_16 = GEN_INT (16); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, + op1_subword), + shift_16)); + emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); + DONE; +}") + +(define_insn "*sign_extendhisi2_insn" + [(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")]) + +(define_expand "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "") + (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_24 = GEN_INT (24); + int op1_subword = 0; + int op0_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + if (GET_CODE (operand0) == SUBREG) + { + op0_subword = SUBREG_WORD (operand0); + operand0 = XEXP (operand0, 0); + } + emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, + op1_subword), + shift_24)); + if (GET_MODE (operand0) != SImode) + operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subword); + emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); + DONE; +}") + +(define_insn "*sign_extendqihi2_insn" + [(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")]) + +(define_expand "extendqisi2" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_24 = GEN_INT (24); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, + op1_subword), + shift_24)); + emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); + DONE; +}") + +(define_insn "*sign_extendqisi2_insn" + [(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")]) + +(define_expand "extendqidi2" + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI (match_operand:QI 1 "register_operand" "")))] + "TARGET_ARCH64" + " +{ + rtx temp = gen_reg_rtx (DImode); + rtx shift_56 = GEN_INT (56); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, + op1_subword), + shift_56)); + emit_insn (gen_ashrdi3 (operand0, temp, shift_56)); + DONE; +}") + +(define_insn "*sign_extendqidi2_insn" + [(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")]) + +(define_expand "extendhidi2" + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI (match_operand:HI 1 "register_operand" "")))] + "TARGET_ARCH64" + " +{ + rtx temp = gen_reg_rtx (DImode); + rtx shift_48 = GEN_INT (48); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, + op1_subword), + shift_48)); + emit_insn (gen_ashrdi3 (operand0, temp, shift_48)); + DONE; +}") + +(define_insn "*sign_extendhidi2_insn" + [(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")]) + +(define_expand "extendsidi2" + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI (match_operand:SI 1 "register_operand" "")))] + "TARGET_ARCH64" + "") + +(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")))] + "TARGET_ARCH64" + "@ + sra %1,0,%0 + ldsw %1,%0" + [(set_attr "type" "unary,sload") + (set_attr "length" "1")]) + +;; Special pattern for optimizing bit-field compares. This is needed +;; because combine uses this as a canonical form. + +(define_insn "*cmp_zero_extract" + [(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")) + (const_int 0)))] + "INTVAL (operands[2]) > 19" + "* +{ + int len = INTVAL (operands[1]); + int pos = 32 - INTVAL (operands[2]) - len; + unsigned mask = ((1 << len) - 1) << pos; + + operands[1] = GEN_INT (mask); + return \"andcc %0,%1,%%g0\"; +}") + +(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")) + (const_int 0)))] + "TARGET_ARCH64 && INTVAL (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; + + operands[1] = GEN_INT (mask); + return \"andcc %0,%1,%%g0\"; +}") + +;; Conversions between float, double and long double. + +(define_insn "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=e") + (float_extend:DF + (match_operand:SF 1 "register_operand" "f")))] + "TARGET_FPU" + "fstod %1,%0" + [(set_attr "type" "fp")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +;; Conversion between fixed point and floating point. + +(define_insn "floatsisf2" + [(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")]) + +(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")]) + +(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")]) + +;; Now the same for 64 bit sources. + +(define_insn "floatdisf2" + [(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")]) + +(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")]) + +(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")]) + +;; Convert a float to an actual integer. +;; Truncation is performed as part of the conversion. + +(define_insn "fix_truncsfsi2" + [(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")]) + +(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")]) + +(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")]) + +;; Now the same, for V9 targets + +(define_insn "fix_truncsfdi2" + [(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")]) + +(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")]) + +(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")]) + +;;- 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")))] + "" + " +{ + if (! TARGET_ARCH64) + { + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, + gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_PLUS (DImode, operands[1], + operands[2])), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (CCmode, SPARC_ICC_REG))))); + DONE; + } +}") + +(define_insn "*adddi3_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") + (match_operand:DI 2 "arith_double_operand" "rHI"))) + (clobber (reg:CC 100))] + "! TARGET_ARCH64 && reload_completed" + [(parallel [(set (reg:CC_NOOV 100) + (compare:CC_NOOV (plus:SI (match_dup 4) + (match_dup 5)) + (const_int 0))) + (set (match_dup 3) + (plus:SI (match_dup 4) (match_dup 5)))]) + (set (match_dup 6) + (plus:SI (plus:SI (match_dup 7) + (match_dup 8)) + (ltu:SI (reg:CC_NOOV 100) (const_int 0))))] + " +{ + operands[3] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_lowpart (SImode, operands[2]); + operands[6] = gen_highpart (SImode, operands[0]); + operands[7] = gen_highpart (SImode, operands[1]); + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) < 0) + operands[8] = constm1_rtx; + else + operands[8] = const0_rtx; + } + else + operands[8] = gen_highpart (SImode, operands[2]); +}") + +(define_split + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (match_operand:DI 1 "arith_double_operand" "r") + (match_operand:DI 2 "arith_double_operand" "rHI"))) + (clobber (reg:CC 100))] + "! TARGET_ARCH64 && reload_completed" + [(parallel [(set (reg:CC_NOOV 100) + (compare:CC_NOOV (minus:SI (match_dup 4) + (match_dup 5)) + (const_int 0))) + (set (match_dup 3) + (minus:SI (match_dup 4) (match_dup 5)))]) + (set (match_dup 6) + (minus:SI (minus:SI (match_dup 7) + (match_dup 8)) + (ltu:SI (reg:CC_NOOV 100) (const_int 0))))] + " +{ + operands[3] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_lowpart (SImode, operands[2]); + operands[6] = gen_highpart (SImode, operands[0]); + operands[7] = gen_highpart (SImode, operands[1]); + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) < 0) + operands[8] = constm1_rtx; + else + operands[8] = const0_rtx; + } + else + operands[8] = gen_highpart (SImode, operands[2]); +}") + +;; LTU here means "carry set" +(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")]) + +(define_insn "*subx" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI")) + (ltu:SI (reg:CC_NOOV 100) (const_int 0))))] + "" + "subx %1,%2,%0" + [(set_attr "type" "unary")]) + +(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"))) + (clobber (reg:CC 100))] + "! TARGET_ARCH64" + "addcc %L2,%1,%L0\;addx %H2,0,%H0" + [(set_attr "type" "multi")]) + +(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") + +(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")]) + +(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")]) + +(define_insn "*cmp_ccx_plus" + [(set (reg:CCX_NOOV 100) + (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r") + (match_operand:DI 1 "arith_double_operand" "rHI")) + (const_int 0)))] + "TARGET_ARCH64" + "addcc %0,%1,%%g0" + [(set_attr "type" "compare")]) + +(define_insn "*cmp_cc_plus_set" + [(set (reg:CC_NOOV 100) + (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r") + (match_operand:SI 2 "arith_operand" "rI")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "addcc %1,%2,%0") + +(define_insn "*cmp_ccx_plus_set" + [(set (reg:CCX_NOOV 100) + (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") + (match_operand:DI 2 "arith_double_operand" "rHI")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_dup 1) (match_dup 2)))] + "TARGET_ARCH64" + "addcc %1,%2,%0") + +(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")))] + "" + " +{ + if (! TARGET_ARCH64) + { + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, + gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_MINUS (DImode, operands[1], + operands[2])), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (CCmode, SPARC_ICC_REG))))); + DONE; + } +}") + +(define_insn "*subdi3_sp32" + [(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"))) + (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 (\"sub %H1,%2,%H0\", xoperands); + else + output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands); + return \"\"; + } + return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\"; +}" + [(set_attr "length" "2")]) + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (match_operand:DI 1 "register_operand" "r") + (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")]) + +(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") + +(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")]) + +(define_insn "*cmp_minus_cc" + [(set (reg:CC_NOOV 100) + (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "arith_operand" "rI")) + (const_int 0)))] + "" + "subcc %0,%1,%%g0" + [(set_attr "type" "compare")]) + +(define_insn "*cmp_minus_ccx" + [(set (reg:CCX_NOOV 100) + (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r") + (match_operand:DI 1 "arith_double_operand" "rHI")) + (const_int 0)))] + "TARGET_ARCH64" + "subcc %0,%1,%%g0" + [(set_attr "type" "compare")]) + +(define_insn "*cmp_minus_cc_set" + [(set (reg:CC_NOOV 100) + (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r") + (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") + +(define_insn "*cmp_minus_ccx_set" + [(set (reg:CCX_NOOV 100) + (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "arith_double_operand" "rHI")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (match_dup 1) (match_dup 2)))] + "TARGET_ARCH64" + "subcc %1,%2,%0") + +;; Integer Multiply/Divide. + +;; The 32 bit multiply/divide instructions are deprecated on v9 and shouldn't +;; we used. We still use them in 32 bit v9 compilers. +;; The 64 bit v9 compiler will (/should) widen the args and use muldi3. + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (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")]) + +(define_expand "muldi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (match_operand:DI 1 "arith_double_operand" "%r") + (match_operand:DI 2 "arith_double_operand" "rHI")))] + "TARGET_ARCH64 || TARGET_V8PLUS" + " +{ + if (TARGET_V8PLUS) + { + emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2])); + DONE; + } +}") + +(define_insn "*muldi3_sp64" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (match_operand:DI 1 "arith_double_operand" "%r") + (match_operand:DI 2 "arith_double_operand" "rHI")))] + "TARGET_ARCH64" + "mulx %1,%2,%0") + +;; V8plus wide multiply. +(define_insn "muldi3_v8plus" + [(set (match_operand:DI 0 "register_operand" "=r,h") + (mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0") + (match_operand:DI 2 "arith_double_operand" "rHI,rHI"))) + (clobber (match_scratch:SI 3 "=&h,X")) + (clobber (match_scratch:SI 4 "=&h,X"))] + "TARGET_V8PLUS" + "* +{ + if (sparc_check_64 (operands[1], insn) <= 0) + output_asm_insn (\"srl %L1,0,%L1\", operands); + if (which_alternative == 1) + output_asm_insn (\"sllx %H1,32,%H1\", operands); + if (sparc_check_64 (operands[2], insn) <= 0) + output_asm_insn (\"srl %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\"; + 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\"; +}" + [(set_attr "length" "9,8")]) + +;; It is not known whether this will match. + +(define_insn "*cmp_mul_set" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (match_operand:SI 1 "arith_operand" "%r") + (match_operand:SI 2 "arith_operand" "rI"))) + (set (reg:CC_NOOV 100) + (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")]) + +(define_expand "mulsidi3" + [(set (match_operand:DI 0 "register_operand" "") + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) + (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))] + "TARGET_HARD_MUL" + " +{ + if (CONSTANT_P (operands[2])) + { + if (TARGET_V8PLUS) + { + emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1], + operands[2])); + DONE; + } + emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2])); + DONE; + } + if (TARGET_V8PLUS) + { + emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2])); + DONE; + } +}") + +;; 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. +(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")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))) + (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" + [(set_attr "length" "2,3")]) + +(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")) + (match_operand:SI 2 "small_int" "I,I"))) + (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" + [(set_attr "length" "2,3")]) + +(define_insn "*mulsidi3_sp32" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] + "TARGET_HARD_MUL32" + "* +{ + return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "sparclet") + (const_int 1) (const_int 2)))]) + +;; Extra pattern, because sign_extend of a constant isn't valid. + +(define_insn "const_mulsidi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "small_int" "I")))] + "TARGET_HARD_MUL" + "* +{ + return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "sparclet") + (const_int 1) (const_int 2)))]) + +(define_expand "smulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "") + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) + (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))) + (const_int 32))))] + "TARGET_HARD_MUL" + " +{ + if (CONSTANT_P (operands[2])) + { + if (TARGET_V8PLUS) + { + emit_insn (gen_const_smulsi3_highpart_v8plus (operands[0], + operands[1], + operands[2], + GEN_INT (32))); + DONE; + } + emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2])); + DONE; + } + if (TARGET_V8PLUS) + { + emit_insn (gen_smulsi3_highpart_v8plus (operands[0], operands[1], + operands[2], GEN_INT (32))); + DONE; + } +}") + +(define_insn "smulsi3_highpart_v8plus" + [(set (match_operand:SI 0 "register_operand" "=h,r") + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))) + (match_operand:SI 3 "const_int_operand" "i,i")))) + (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" + [(set_attr "length" "2")]) + +;; The combiner changes TRUNCATE in the previous pattern to SUBREG. +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=h,r") + (subreg:SI + (lshiftrt:DI + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))) + (match_operand:SI 3 "const_int_operand" "i,i")) + 1)) + (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" + [(set_attr "length" "2")]) + +(define_insn "const_smulsi3_highpart_v8plus" + [(set (match_operand:SI 0 "register_operand" "=h,r") + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r")) + (match_operand 2 "small_int" "i,i")) + (match_operand:SI 3 "const_int_operand" "i,i")))) + (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" + [(set_attr "length" "2")]) + +(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" + [(set_attr "length" "2")]) + +(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" + [(set_attr "length" "2")]) + +(define_expand "umulsidi3" + [(set (match_operand:DI 0 "register_operand" "") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) + (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))] + "TARGET_HARD_MUL" + " +{ + if (CONSTANT_P (operands[2])) + { + if (TARGET_V8PLUS) + { + emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1], + operands[2])); + DONE; + } + emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2])); + DONE; + } + if (TARGET_V8PLUS) + { + emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2])); + DONE; + } +}") + +(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")) + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))) + (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" + [(set_attr "length" "2,3")]) + +(define_insn "*umulsidi3_sp32" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] + "TARGET_HARD_MUL32" + "* +{ + return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "sparclet") + (const_int 1) (const_int 2)))]) + +;; Extra pattern, because sign_extend of a constant isn't valid. + +(define_insn "const_umulsidi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "uns_small_int" "")))] + "TARGET_HARD_MUL32" + "* +{ + return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "sparclet") + (const_int 1) (const_int 2)))]) + +(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")) + (match_operand:SI 2 "uns_small_int" ""))) + (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" + [(set_attr "length" "2,3")]) + +(define_expand "umulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "") + (truncate:SI + (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) + (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))) + (const_int 32))))] + "TARGET_HARD_MUL" + " +{ + if (CONSTANT_P (operands[2])) + { + if (TARGET_V8PLUS) + { + emit_insn (gen_const_umulsi3_highpart_v8plus (operands[0], + operands[1], + operands[2], + GEN_INT (32))); + DONE; + } + emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2])); + DONE; + } + if (TARGET_V8PLUS) + { + emit_insn (gen_umulsi3_highpart_v8plus (operands[0], operands[1], + operands[2], GEN_INT (32))); + DONE; + } +}") + +(define_insn "umulsi3_highpart_v8plus" + [(set (match_operand:SI 0 "register_operand" "=h,r") + (truncate:SI + (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r")) + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r"))) + (match_operand:SI 3 "const_int_operand" "i,i")))) + (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" + [(set_attr "length" "2")]) + +(define_insn "const_umulsi3_highpart_v8plus" + [(set (match_operand:SI 0 "register_operand" "=h,r") + (truncate:SI + (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r")) + (match_operand:SI 2 "uns_small_int" "")) + (match_operand:SI 3 "const_int_operand" "i,i")))) + (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" + [(set_attr "length" "2")]) + +(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" + [(set_attr "length" "2")]) + +(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" + [(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. + +(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"))) + (clobber (match_scratch:SI 3 "=&r,&r"))] + "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" + "* +{ + if (which_alternative == 0) + if (TARGET_V9) + return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\"; + else + return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\"; + else + if (TARGET_V9) + return \"sra %1,31,%3\;wr %%g0,%3,%%y\;ld %2,%3\;sdiv %1,%3,%0\"; + else + return \"sra %1,31,%3\;wr %%g0,%3,%%y\;ld %2,%3\;nop\;nop\;sdiv %1,%3,%0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "v9") + (const_int 4) (const_int 7)))]) + +(define_insn "divdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (div:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "arith_double_operand" "rHI")))] + "TARGET_ARCH64" + "sdivx %1,%2,%0") + +;; It is not known whether this will match. + +(define_insn "*cmp_sdiv_cc_set" + [(set (match_operand:SI 0 "register_operand" "=r") + (div:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI"))) + (set (reg:CC 100) + (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" + "* +{ + if (TARGET_V9) + return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdivcc %1,%2,%0\"; + else + return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "v9") + (const_int 3) (const_int 6)))]) + +(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" + "* +{ + output_asm_insn (\"wr %%g0,%%g0,%%y\", operands); + switch (which_alternative) + { + default: + if (TARGET_V9) + return \"udiv %1,%2,%0\"; + return \"nop\;nop\;nop\;udiv %1,%2,%0\"; + case 1: + return \"ld %2,%0\;nop\;nop\;udiv %1,%0,%0\"; + case 2: + return \"ld %1,%0\;nop\;nop\;udiv %0,%2,%0\"; + } +}" + [(set (attr "length") + (if_then_else (and (eq_attr "isa" "v9") + (eq_attr "alternative" "0")) + (const_int 2) (const_int 5)))]) + +(define_insn "udivdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (udiv:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "arith_double_operand" "rHI")))] + "TARGET_ARCH64" + "udivx %1,%2,%0") + +;; It is not known whether this will match. + +(define_insn "*cmp_udiv_cc_set" + [(set (match_operand:SI 0 "register_operand" "=r") + (udiv:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI"))) + (set (reg:CC 100) + (compare:CC (udiv:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" + "* +{ + if (TARGET_V9) + return \"wr %%g0,%%g0,%%y\;udivcc %1,%2,%0\"; + else + return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0\"; +}" + [(set (attr "length") + (if_then_else (eq_attr "isa" "v9") + (const_int 2) (const_int 5)))]) + +; sparclet multiply/accumulate insns + +(define_insn "*smacsi" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "arith_operand" "rI")) + (match_operand:SI 3 "register_operand" "0")))] + "TARGET_SPARCLET" + "smac %1,%2,%0" + [(set_attr "type" "imul")]) + +(define_insn "*smacdi" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (mult:DI (sign_extend:DI + (match_operand:SI 1 "register_operand" "%r")) + (sign_extend:DI + (match_operand:SI 2 "register_operand" "r"))) + (match_operand:DI 3 "register_operand" "0")))] + "TARGET_SPARCLET" + "smacd %1,%2,%L0" + [(set_attr "type" "imul")]) + +(define_insn "*umacdi" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (mult:DI (zero_extend:DI + (match_operand:SI 1 "register_operand" "%r")) + (zero_extend:DI + (match_operand:SI 2 "register_operand" "r"))) + (match_operand:DI 3 "register_operand" "0")))] + "TARGET_SPARCLET" + "umacd %1,%2,%L0" + [(set_attr "type" "imul")]) + +;;- Boolean instructions +;; We define DImode `and' so with DImode `not' we can get +;; DImode `andn'. Other combinations are possible. + +(define_expand "anddi3" + [(set (match_operand:DI 0 "register_operand" "") + (and:DI (match_operand:DI 1 "arith_double_operand" "") + (match_operand:DI 2 "arith_double_operand" "")))] + "" + "") + +(define_insn "*anddi3_sp32" + [(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" + "* +{ + 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")]) + +(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")))] + "TARGET_ARCH64" + "and %1,%2,%0") + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r,d") + (and:SI (match_operand:SI 1 "arith_operand" "%r,d") + (match_operand:SI 2 "arith_operand" "rI,d")))] + "" + "@ + and %1,%2,%0 + fands %1,%2,%0" + [(set_attr "type" "ialu,fp")]) + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (and:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" ""))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT32 (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))] + " +{ + operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff); +}") + +;; Split DImode logical operations requiring two instructions. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (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" + [(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)]))] + " +{ + operands[4] = gen_highpart (SImode, operands[0]); + operands[5] = gen_lowpart (SImode, operands[0]); + operands[6] = gen_highpart (SImode, operands[2]); + operands[7] = gen_lowpart (SImode, operands[2]); + if (GET_CODE (operands[3]) == CONST_INT) + { + if (INTVAL (operands[3]) < 0) + operands[8] = constm1_rtx; + else + operands[8] = const0_rtx; + } + else + operands[8] = gen_highpart (SImode, operands[3]); + operands[9] = gen_lowpart (SImode, operands[3]); +}") + +(define_insn "*and_not_di_sp32" + [(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 %R2,%R1,%R0 + fandnot1 %1,%2,%0" + [(set_attr "length" "2,1")]) + +(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")))] + "TARGET_ARCH64" + "andn %2,%1,%0") + +(define_insn "*and_not_si" + [(set (match_operand:SI 0 "register_operand" "=r,d") + (and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d")) + (match_operand:SI 2 "register_operand" "r,d")))] + "" + "@ + andn %2,%1,%0 + fandnot1s %1,%2,%0" + [(set_attr "type" "ialu,fp")]) + +(define_expand "iordi3" + [(set (match_operand:DI 0 "register_operand" "") + (ior:DI (match_operand:DI 1 "arith_double_operand" "") + (match_operand:DI 2 "arith_double_operand" "")))] + "" + "") + +(define_insn "*iordi3_sp32" + [(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" + "* +{ + 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")]) + +(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")))] + "TARGET_ARCH64" + "or %1,%2,%0") + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,d") + (ior:SI (match_operand:SI 1 "arith_operand" "%r,d") + (match_operand:SI 2 "arith_operand" "rI,d")))] + "" + "@ + or %1,%2,%0 + fors %1,%2,%0" + [(set_attr "type" "ialu,fp")]) + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (ior:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" ""))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT32 (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))] + " +{ + operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff); +}") + +(define_insn "*or_not_di_sp32" + [(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 %R2,%R1,%R0 + fornot1 %1,%2,%0" + [(set_attr "length" "2,1")]) + +(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")))] + "TARGET_ARCH64" + "orn %2,%1,%0") + +(define_insn "*or_not_si" + [(set (match_operand:SI 0 "register_operand" "=r,d") + (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d")) + (match_operand:SI 2 "register_operand" "r,d")))] + "" + "@ + orn %2,%1,%0 + fornot1s %1,%2,%0" + [(set_attr "type" "ialu,fp")]) + +(define_expand "xordi3" + [(set (match_operand:DI 0 "register_operand" "") + (xor:DI (match_operand:DI 1 "arith_double_operand" "") + (match_operand:DI 2 "arith_double_operand" "")))] + "" + "") + +(define_insn "*xordi3_sp32" + [(set (match_operand:DI 0 "register_operand" "=r,b") + (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\"; +}" + [(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")))] + "TARGET_ARCH64" + "xor %r1,%2,%0") + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,d") + (xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d") + (match_operand:SI 2 "arith_operand" "rI,d")))] + "" + "@ + xor %r1,%2,%0 + fxors %1,%2,%0" + [(set_attr "type" "ialu,fp")]) + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" ""))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT32 (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))] + " +{ + operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff); +}") + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (not:SI (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" "")))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT32 (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))] + " +{ + operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff); +}") + +;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b). +;; Combine now canonicalizes to the rightmost expression. +(define_insn "*xor_not_di_sp32" + [(set (match_operand:DI 0 "register_operand" "=r,b") + (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b") + (match_operand:DI 2 "register_operand" "r,b"))))] + "! TARGET_ARCH64" + "@ + xnor %1,%2,%0\;xnor %R1,%R2,%R0 + fxnor %1,%2,%0" + [(set_attr "length" "2,1") + (set_attr "type" "ialu,fp")]) + +(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"))))] + "TARGET_ARCH64" + "xnor %r1,%2,%0" + [(set_attr "type" "ialu")]) + +(define_insn "*xor_not_si" + [(set (match_operand:SI 0 "register_operand" "=r,d") + (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d") + (match_operand:SI 2 "arith_operand" "rI,d"))))] + "" + "@ + xnor %r1,%2,%0 + fxnors %1,%2,%0" + [(set_attr "type" "ialu,fp")]) + +;; These correspond to the above in the case where we also (or only) +;; want to set the condition code. + +(define_insn "*cmp_cc_arith_op" + [(set (reg:CC 100) + (compare:CC + (match_operator:SI 2 "cc_arithop" + [(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")]) + +(define_insn "*cmp_ccx_arith_op" + [(set (reg:CCX 100) + (compare:CCX + (match_operator:DI 2 "cc_arithop" + [(match_operand:DI 0 "arith_double_operand" "%r") + (match_operand:DI 1 "arith_double_operand" "rHI")]) + (const_int 0)))] + "TARGET_ARCH64" + "%A2cc %0,%1,%%g0" + [(set_attr "type" "compare")]) + +(define_insn "*cmp_cc_arith_op_set" + [(set (reg:CC 100) + (compare:CC + (match_operator:SI 3 "cc_arithop" + [(match_operand:SI 1 "arith_operand" "%r") + (match_operand:SI 2 "arith_operand" "rI")]) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (match_dup 3))] + "" + "%A3cc %1,%2,%0") + +(define_insn "*cmp_ccx_arith_op_set" + [(set (reg:CCX 100) + (compare:CCX + (match_operator:DI 3 "cc_arithop" + [(match_operand:DI 1 "arith_double_operand" "%r") + (match_operand:DI 2 "arith_double_operand" "rHI")]) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (match_dup 3))] + "TARGET_ARCH64" + "%A3cc %1,%2,%0") + +(define_insn "*cmp_cc_xor_not" + [(set (reg:CC 100) + (compare:CC + (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")]) + +(define_insn "*cmp_ccx_xor_not" + [(set (reg:CCX 100) + (compare:CCX + (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ") + (match_operand:DI 1 "arith_double_operand" "rHI"))) + (const_int 0)))] + "TARGET_ARCH64" + "xnorcc %r0,%1,%%g0" + [(set_attr "type" "compare")]) + +(define_insn "*cmp_cc_xor_not_set" + [(set (reg:CC 100) + (compare:CC + (not:SI (xor: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") + (not:SI (xor:SI (match_dup 1) (match_dup 2))))] + "" + "xnorcc %r1,%2,%0") + +(define_insn "*cmp_ccx_xor_not_set" + [(set (reg:CCX 100) + (compare:CCX + (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") + (match_operand:DI 2 "arith_double_operand" "rHI"))) + (const_int 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") + +(define_insn "*cmp_cc_arith_op_not" + [(set (reg:CC 100) + (compare:CC + (match_operator:SI 2 "cc_arithopn" + [(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")]) + +(define_insn "*cmp_ccx_arith_op_not" + [(set (reg:CCX 100) + (compare:CCX + (match_operator:DI 2 "cc_arithopn" + [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI")) + (match_operand:DI 1 "reg_or_0_operand" "rJ")]) + (const_int 0)))] + "TARGET_ARCH64" + "%B2cc %r1,%0,%%g0" + [(set_attr "type" "compare")]) + +(define_insn "*cmp_cc_arith_op_not_set" + [(set (reg:CC 100) + (compare:CC + (match_operator:SI 3 "cc_arithopn" + [(not:SI (match_operand:SI 1 "arith_operand" "rI")) + (match_operand:SI 2 "reg_or_0_operand" "rJ")]) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (match_dup 3))] + "" + "%B3cc %r2,%1,%0") + +(define_insn "*cmp_ccx_arith_op_not_set" + [(set (reg:CCX 100) + (compare:CCX + (match_operator:DI 3 "cc_arithopn" + [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI")) + (match_operand:DI 2 "reg_or_0_operand" "rJ")]) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (match_dup 3))] + "TARGET_ARCH64" + "%B3cc %r2,%1,%0") + +;; We cannot use the "neg" pseudo insn because the Sun assembler +;; does not know how to make it work for constants. + +(define_expand "negdi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (match_operand:DI 1 "register_operand" "r")))] + "" + " +{ + if (! TARGET_ARCH64) + { + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, + gen_rtx_SET (VOIDmode, operand0, + gen_rtx_NEG (DImode, operand1)), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (CCmode, SPARC_ICC_REG))))); + DONE; + } +}") + +(define_insn "*negdi2_sp32" + [(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\"; +}" + [(set_attr "type" "unary") + ;; ??? This is wrong for TARGET_LIVE_G0 but it's not critical. + (set_attr "length" "2")]) + +(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" + [(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")))] + "" + "* +{ + if (TARGET_LIVE_G0) + return \"and %%g0,0,%%g0\;sub %%g0,%1,%0\"; + return \"sub %%g0,%1,%0\"; +}" + [(set_attr "type" "unary") + (set (attr "length") + (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 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")]) + +(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")]) + +(define_insn "*cmp_cc_set_neg" + [(set (reg:CC_NOOV 100) + (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI")) + (const_int 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")]) + +(define_insn "*cmp_ccx_set_neg" + [(set (reg:CCX_NOOV 100) + (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (match_dup 1)))] + "TARGET_ARCH64" + "subcc %%g0,%1,%0" + [(set_attr "type" "unary")]) + +;; We cannot use the "not" pseudo insn because the Sun assembler +;; does not know how to make it work for constants. +(define_expand "one_cmpldi2" + [(set (match_operand:DI 0 "register_operand" "") + (not:DI (match_operand:DI 1 "register_operand" "")))] + "" + "") + +(define_insn "*one_cmpldi2_sp32" + [(set (match_operand:DI 0 "register_operand" "=r,b") + (not:DI (match_operand:DI 1 "register_operand" "r,b")))] + "! TARGET_ARCH64" + "@ + xnor %1,0,%0\;xnor %R1,0,%R0 + fnot1 %1,%0" + [(set_attr "type" "unary,fp") + (set_attr "length" "2,1")]) + +(define_insn "*one_cmpldi2_sp64" + [(set (match_operand:DI 0 "register_operand" "=r") + (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] + "TARGET_ARCH64" + "xnor %1,0,%0" + [(set_attr "type" "unary")]) + +(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")))] + "" + "* +{ + 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)])]) + +(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")]) + +(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")]) + +(define_insn "*cmp_cc_set_not" + [(set (reg:CC 100) + (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI")) + (const_int 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")]) + +(define_insn "*cmp_ccx_set_not" + [(set (reg:CCX 100) + (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=r") + (not:DI (match_dup 1)))] + "TARGET_ARCH64" + "xnorcc %%g0,%1,%0" + [(set_attr "type" "unary")]) + +;; Floating point arithmetic instructions. + +(define_insn "addtf3" + [(set (match_operand:TF 0 "register_operand" "=e") + (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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +;; don't have timing for quad-prec. divide. +(define_insn "divtf3" + [(set (match_operand:TF 0 "register_operand" "=e") + (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")]) + +(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")]) + +(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")]) + +(define_insn "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\"; +}" + [(set_attr "type" "fpmove") + (set_attr_alternative "length" + [(const_int 1) + (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])]) + +(define_insn "negdf2" + [(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\"; +}" + [(set_attr "type" "fpmove") + (set_attr_alternative "length" + [(const_int 1) + (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])]) + +(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")]) + +(define_insn "abstf2" + [(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" + "* +{ + /* 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\"; +}" + [(set_attr "type" "fpmove") + (set_attr_alternative "length" + [(const_int 1) + (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])]) + +(define_insn "absdf2" + [(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\"; +}" + [(set_attr "type" "fpmove") + (set_attr_alternative "length" + [(const_int 1) + (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])]) + +(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")]) + +(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")]) + +(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")]) + +(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")]) + +;;- arithmetic shift instructions + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (ashift:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI")))] + "" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + + return \"sll %1,%2,%0\"; +}" + [(set_attr "type" "shift")]) + +(define_expand "ashldi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (match_operand:DI 1 "register_operand" "r") + (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_ashldi3_v8plus (operands[0], operands[1], operands[2])); + DONE; + } +}") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI")))] + "TARGET_ARCH64" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); + + return \"sllx %1,%2,%0\"; +}") + +(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") + (match_operand:SI 2 "arith_operand" "rI,rI,rI"))) + (clobber (match_scratch:SI 3 "=X,X,&h"))] + "TARGET_V8PLUS" + "*return sparc_v8plus_shift (operands, insn, \"sllx\");" + [(set_attr "length" "5,5,6")]) + +;; Optimize (1LL< 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + + return \"sra %1,%2,%0\"; +}" + [(set_attr "type" "shift")]) + +(define_expand "ashrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") + (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; + }") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI")))] + "TARGET_ARCH64" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); + + return \"srax %1,%2,%0\"; +}") + +(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") + (match_operand:SI 2 "arith_operand" "rI,rI,rI"))) + (clobber (match_scratch:SI 3 "=X,X,&h"))] + "TARGET_V8PLUS" + "*return sparc_v8plus_shift (operands, insn, \"srax\");" + [(set_attr "length" "5,5,6")]) + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI")))] + "" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + + return \"srl %1,%2,%0\"; +}" + [(set_attr "type" "shift")]) + +(define_expand "lshrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") + (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; + }") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI")))] + "TARGET_ARCH64" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); + + return \"srlx %1,%2,%0\"; +}") + +(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") + (match_operand:SI 2 "arith_operand" "rI,rI,rI"))) + (clobber (match_scratch:SI 3 "=X,X,&h"))] + "TARGET_V8PLUS" + "*return sparc_v8plus_shift (operands, insn, \"srlx\");" + [(set_attr "length" "5,5,6")]) + +;; Unconditional and other jump instructions +;; On the Sparc, by setting the annul bit on an unconditional branch, the +;; following insn is never executed. This saves us a nop. Dbx does not +;; handle such branches though, so we only use them when optimizing. +(define_insn "jump" + [(set (pc) (label_ref (match_operand 0 "" "")))] + "" + "* +{ + /* Some implementations (e.g. TurboSparc) are reported to have problems + 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 + && (insn_addresses[INSN_UID (operands[0])] + == insn_addresses[INSN_UID (insn)])) + return \"b %l0%#\"; + else + return \"b%* %l0%(\"; +}" + [(set_attr "type" "uncond_branch")]) + +(define_expand "tablejump" + [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))])] + "" + " +{ + if (GET_MODE (operands[0]) != Pmode) + abort (); + + /* In pic mode, our address differences are against the base of the + table. Add that base value back in; CSE ought to be able to combine + the two address loads. */ + if (flag_pic) + { + rtx tmp, tmp2; + tmp = gen_rtx_LABEL_REF (Pmode, operands[1]); + tmp2 = operands[0]; + tmp = gen_rtx_PLUS (Pmode, tmp2, tmp); + operands[0] = memory_address (Pmode, tmp); + } +}") + +(define_insn "*tablejump_sp32" + [(set (pc) (match_operand:SI 0 "address_operand" "p")) + (use (label_ref (match_operand 1 "" "")))] + "! TARGET_PTR64" + "jmp %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%#" + [(set_attr "type" "uncond_branch")]) + +;; This pattern recognizes the "instruction" that appears in +;; a function call that wants a structure value, +;; to inform the called function if compiled with Sun CC. +;(define_insn "*unimp_insn" +; [(match_operand:SI 0 "immediate_operand" "")] +; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0" +; "unimp %0" +; [(set_attr "type" "marker")]) + +;;- jump to subroutine +(define_expand "call" + ;; Note that this expression is not used for generating RTL. + ;; All the RTL is generated explicitly below. + [(call (match_operand 0 "call_operand" "") + (match_operand 3 "" "i"))] + ;; operands[2] is next_arg_register + ;; operands[3] is struct_value_size_rtx. + "" + " +{ + rtx fn_rtx, nregs_rtx; + + if (GET_MODE (operands[0]) != FUNCTION_MODE) + abort (); + + if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF) + { + /* This is really a PIC sequence. We want to represent + it as a funny jump so its delay slots can be filled. + + ??? But if this really *is* a CALL, will not it clobber the + call-clobbered registers? We lose this if it is a JUMP_INSN. + Why cannot we have delay slots filled if it were a CALL? */ + + if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0) + emit_jump_insn + (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (3, + gen_rtx_SET (VOIDmode, pc_rtx, + XEXP (operands[0], 0)), + GEN_INT (INTVAL (operands[3]) & 0xfff), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (Pmode, 15))))); + else + emit_jump_insn + (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, + gen_rtx_SET (VOIDmode, pc_rtx, + XEXP (operands[0], 0)), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (Pmode, 15))))); + goto finish_call; + } + + fn_rtx = operands[0]; + + /* Count the number of parameter registers being used by this call. + if that argument is NULL, it means we are using them all, which + means 6 on the sparc. */ +#if 0 + if (operands[2]) + nregs_rtx = GEN_INT (REGNO (operands[2]) - 8); + else + nregs_rtx = GEN_INT (6); +#else + nregs_rtx = const0_rtx; +#endif + + if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0) + emit_call_insn + (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx), + GEN_INT (INTVAL (operands[3]) & 0xfff), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (Pmode, 15))))); + else + emit_call_insn + (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_REG (Pmode, 15))))); + + finish_call: +#if 0 + /* If this call wants a structure value, + emit an unimp insn to let the called function know about this. */ + if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0) + { + rtx insn = emit_insn (operands[3]); + SCHED_GROUP_P (insn) = 1; + } +#endif + + DONE; +}") + +;; We can't use the same pattern for these two insns, because then registers +;; in the address may not be properly reloaded. + +(define_insn "*call_address_sp32" + [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) + (match_operand 1 "" "")) + (clobber (reg:SI 15))] + ;;- Do not use operand 1 for most machines. + "! TARGET_PTR64" + "call %a0,%1%#" + [(set_attr "type" "call")]) + +(define_insn "*call_symbolic_sp32" + [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) + (match_operand 1 "" "")) + (clobber (reg:SI 15))] + ;;- Do not use operand 1 for most machines. + "! TARGET_PTR64" + "call %a0,%1%#" + [(set_attr "type" "call")]) + +(define_insn "*call_address_sp64" + [(call (mem:SI (match_operand:DI 0 "address_operand" "p")) + (match_operand 1 "" "")) + (clobber (reg:DI 15))] + ;;- Do not use operand 1 for most machines. + "TARGET_PTR64" + "call %a0,%1%#" + [(set_attr "type" "call")]) + +(define_insn "*call_symbolic_sp64" + [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s")) + (match_operand 1 "" "")) + (clobber (reg:DI 15))] + ;;- Do not use operand 1 for most machines. + "TARGET_PTR64" + "call %a0,%1%#" + [(set_attr "type" "call")]) + +;; This is a call that wants a structure value. +;; There is no such critter for v9 (??? we may need one anyway). +(define_insn "*call_address_struct_value_sp32" + [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) + (match_operand 1 "" "")) + (match_operand 2 "immediate_operand" "") + (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" + [(set_attr "type" "call_no_delay_slot")]) + +;; This is a call that wants a structure value. +;; There is no such critter for v9 (??? we may need one anyway). +(define_insn "*call_symbolic_struct_value_sp32" + [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) + (match_operand 1 "" "")) + (match_operand 2 "immediate_operand" "") + (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" + [(set_attr "type" "call_no_delay_slot")]) + +;; This is a call that may want a structure value. This is used for +;; untyped_calls. +(define_insn "*call_address_untyped_struct_value_sp32" + [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) + (match_operand 1 "" "")) + (match_operand 2 "immediate_operand" "") + (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" + [(set_attr "type" "call_no_delay_slot")]) + +;; This is a call that wants a structure value. +(define_insn "*call_symbolic_untyped_struct_value_sp32" + [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) + (match_operand 1 "" "")) + (match_operand 2 "immediate_operand" "") + (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" + [(set_attr "type" "call_no_delay_slot")]) + +(define_expand "call_value" + ;; Note that this expression is not used for generating RTL. + ;; All the RTL is generated explicitly below. + [(set (match_operand 0 "register_operand" "=rf") + (call (match_operand:SI 1 "" "") + (match_operand 4 "" "")))] + ;; operand 2 is stack_size_rtx + ;; operand 3 is next_arg_register + "" + " +{ + rtx fn_rtx, nregs_rtx; + rtvec vec; + + if (GET_MODE (operands[1]) != FUNCTION_MODE) + abort (); + + fn_rtx = operands[1]; + +#if 0 + if (operands[3]) + nregs_rtx = GEN_INT (REGNO (operands[3]) - 8); + else + nregs_rtx = GEN_INT (6); +#else + nregs_rtx = const0_rtx; +#endif + + vec = gen_rtvec (2, + gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)), + gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15))); + + emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec)); + + DONE; +}") + +(define_insn "*call_value_address_sp32" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "address_operand" "p")) + (match_operand 2 "" ""))) + (clobber (reg:SI 15))] + ;;- Do not use operand 2 for most machines. + "! TARGET_PTR64" + "call %a1,%2%#" + [(set_attr "type" "call")]) + +(define_insn "*call_value_symbolic_sp32" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s")) + (match_operand 2 "" ""))) + (clobber (reg:SI 15))] + ;;- Do not use operand 2 for most machines. + "! TARGET_PTR64" + "call %a1,%2%#" + [(set_attr "type" "call")]) + +(define_insn "*call_value_address_sp64" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:DI 1 "address_operand" "p")) + (match_operand 2 "" ""))) + (clobber (reg:DI 15))] + ;;- Do not use operand 2 for most machines. + "TARGET_PTR64" + "call %a1,%2%#" + [(set_attr "type" "call")]) + +(define_insn "*call_value_symbolic_sp64" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s")) + (match_operand 2 "" ""))) + (clobber (reg:DI 15))] + ;;- Do not use operand 2 for most machines. + "TARGET_PTR64" + "call %a1,%2%#" + [(set_attr "type" "call")]) + +(define_expand "untyped_call" + [(parallel [(call (match_operand 0 "" "") + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] + "" + " +{ + int i; + + /* Pass constm1 to indicate that it may expect a structure value, but + we don't know what size it is. */ + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx)); + + for (i = 0; i < XVECLEN (operands[2], 0); i++) + { + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); + } + + /* The optimizer does not know that the call sets the function value + registers we stored in the result block. We avoid problems by + claiming that all hard registers are used and clobbered at this + point. */ + emit_insn (gen_blockage ()); + + DONE; +}") + +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] + "" + "") + +;; Prepare to return any type including a structure value. + +(define_expand "untyped_return" + [(match_operand:BLK 0 "memory_operand" "") + (match_operand 1 "" "")] + "" + " +{ + rtx valreg1 = gen_rtx_REG (DImode, 24); + rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32); + rtx result = operands[0]; + + if (! TARGET_ARCH64) + { + rtx rtnreg = gen_rtx_REG (SImode, (leaf_function ? 15 : 31)); + rtx value = gen_reg_rtx (SImode); + + /* Fetch the instruction where we will return to and see if it's an unimp + instruction (the most significant 10 bits will be zero). If so, + update the return address to skip the unimp instruction. */ + emit_move_insn (value, + gen_rtx_MEM (SImode, plus_constant (rtnreg, 8))); + emit_insn (gen_lshrsi3 (value, value, GEN_INT (22))); + emit_insn (gen_update_return (rtnreg, value)); + } + + /* Reload the function value registers. */ + emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0))); + emit_move_insn (valreg2, + change_address (result, TARGET_ARCH64 ? TFmode : DFmode, + plus_constant (XEXP (result, 0), 8))); + + /* Put USE insns before the return. */ + emit_insn (gen_rtx_USE (VOIDmode, valreg1)); + emit_insn (gen_rtx_USE (VOIDmode, valreg2)); + + /* Construct the return. */ + expand_null_return (); + + DONE; +}") + +;; This is a bit of a hack. We're incrementing a fixed register (%i7), +;; and parts of the compiler don't want to believe that the add is needed. + +(define_insn "update_return" + [(unspec:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] 1)] + "! TARGET_ARCH64" + "cmp %1,0\;be,a .+8\;add %0,4,%0" + [(set_attr "type" "multi")]) + +(define_insn "return" + [(return) + (use (reg:SI 31))] + "! TARGET_EPILOGUE" + "* return output_return (operands);" + [(set_attr "type" "return")]) + +(define_peephole + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "arith_operand" "rI")) + (parallel [(return) + (use (reg:SI 31))])] + "sparc_return_peephole_ok (operands[0], operands[1])" + "return %%i7+8\;mov %Y1,%Y0") + +(define_insn "nop" + [(const_int 0)] + "" + "nop") + +(define_expand "indirect_jump" + [(set (pc) (match_operand 0 "address_operand" "p"))] + "" + "") + +(define_insn "*branch_sp32" + [(set (pc) (match_operand:SI 0 "address_operand" "p"))] + "! TARGET_PTR64" + "jmp %a0%#" + [(set_attr "type" "uncond_branch")]) + +(define_insn "*branch_sp64" + [(set (pc) (match_operand:DI 0 "address_operand" "p"))] + "TARGET_PTR64" + "jmp %a0%#" + [(set_attr "type" "uncond_branch")]) + +;; ??? Doesn't work with -mflat. +(define_expand "nonlocal_goto" + [(match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" "") + (match_operand:SI 3 "" "")] + "" + " +{ + rtx chain = operands[0]; + rtx fp = operands[1]; + rtx stack = operands[2]; + rtx lab = operands[3]; + rtx labreg; + + /* Trap instruction to flush all the register windows. */ + emit_insn (gen_flush_register_windows ()); + + /* Load the fp value for the containing fn into %fp. This is needed + because STACK refers to %fp. Note that virtual register instantiation + fails if the virtual %fp isn't set from a register. */ + if (GET_CODE (fp) != REG) + fp = force_reg (Pmode, fp); + emit_move_insn (virtual_stack_vars_rtx, fp); + + /* Find the containing function's current nonlocal goto handler, + which will do any cleanups and then jump to the label. */ + labreg = gen_rtx_REG (Pmode, 8); + emit_move_insn (labreg, lab); + + /* Restore %fp from stack pointer value for containing function. + The restore insn that follows will move this to %sp, + and reload the appropriate value into %fp. */ + emit_move_insn (frame_pointer_rtx, stack); + + /* USE of frame_pointer_rtx added for consistency; not clear if + really needed. */ + /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/ + emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); + /* Return, restoring reg window and jumping to goto handler. */ + if (TARGET_V9 && GET_CODE (chain) == CONST_INT + && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff)) + { + emit_insn (gen_goto_handler_and_restore_v9 (labreg, static_chain_rtx, + chain)); + emit_barrier (); + DONE; + } + /* Put in the static chain register the nonlocal label address. */ + emit_move_insn (static_chain_rtx, chain); + emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx)); + emit_insn (gen_goto_handler_and_restore (labreg)); + emit_barrier (); + DONE; +}") + +;; Special trap insn to flush register windows. +(define_insn "flush_register_windows" + [(unspec_volatile [(const_int 0)] 1)] + "" + "* return TARGET_V9 ? \"flushw\" : \"ta 3\";" + [(set_attr "type" "misc")]) + +(define_insn "goto_handler_and_restore" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r")] 2)] + "" + "jmp %0+0\;restore" + [(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")]) + +;; Pattern for use after a setjmp to store FP and the return register +;; into the stack area. + +(define_expand "setjmp" + [(const_int 0)] + "" + " +{ + if (TARGET_ARCH64) + emit_insn (gen_setjmp_64 ()); + else + emit_insn (gen_setjmp_32 ()); + DONE; +}") + +(define_expand "setjmp_32" + [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0)) + (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))] + "" + " +{ operands[0] = frame_pointer_rtx; }") + +(define_expand "setjmp_64" + [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0)) + (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))] + "" + " +{ operands[0] = frame_pointer_rtx; }") + +;; Special pattern for the FLUSH instruction. + +(define_insn "flush" + [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)] + "" + "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";" + [(set_attr "type" "misc")]) + +;; find first set. + +;; The scan instruction searches from the most significant bit while ffs +;; searches from the least significant bit. The bit index and treatment of +;; zero also differ. It takes at least 7 instructions to get the proper +;; result. Here is an obvious 8 instruction sequence. + +(define_insn "ffssi2" + [(set (match_operand:SI 0 "register_operand" "=&r") + (ffs:SI (match_operand:SI 1 "register_operand" "r"))) + (clobber (match_scratch:SI 2 "=&r"))] + "TARGET_SPARCLITE || TARGET_SPARCLET" + "* +{ + if (TARGET_LIVE_G0) + output_asm_insn (\"and %%g0,0,%%g0\", operands); + return \"sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + +;; ??? This should be a define expand, so that the extra instruction have +;; a chance of being optimized away. + +;; Disabled because none of the UltraSparcs implement popc. The HAL R1 +;; does, but no one uses that and we don't have a switch for it. +; +;(define_insn "ffsdi2" +; [(set (match_operand:DI 0 "register_operand" "=&r") +; (ffs:DI (match_operand:DI 1 "register_operand" "r"))) +; (clobber (match_scratch:DI 2 "=&r"))] +; "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. + +;; Optimize consecutive loads or stores into ldd and std when possible. +;; The conditions in which we do this are very restricted and are +;; explained in the code for {registers,memory}_ok_for_ldd functions. + +(define_peephole + [(set (match_operand:SI 0 "memory_operand" "") + (const_int 0)) + (set (match_operand:SI 1 "memory_operand" "") + (const_int 0))] + "TARGET_V9 + && ! 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") + +(define_peephole + [(set (match_operand:SI 0 "memory_operand" "") + (const_int 0)) + (set (match_operand:SI 1 "memory_operand" "") + (const_int 0))] + "TARGET_V9 + && ! 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") + +(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]) + && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" + "ldd %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]) + && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" + "std %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]) + && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" + "ldd %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") + +(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") + +(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") + +(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") + +(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") + +;; 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. +;; This can result from a float to fix conversion. + +(define_peephole + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "register_operand" "r")) + (set (reg:CC 100) + (compare:CC (match_operand:SI 2 "register_operand" "r") + (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") + +(define_peephole + [(set (match_operand:DI 0 "register_operand" "=r") + (match_operand:DI 1 "register_operand" "r")) + (set (reg:CCX 100) + (compare:CCX (match_operand:DI 2 "register_operand" "r") + (const_int 0)))] + "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") + +;; Return peepholes. First the "normal" ones. +;; These are necessary to catch insns ending up in the epilogue delay list. + +(define_insn "*return_qi" + [(set (match_operand:QI 0 "restore_operand" "") + (match_operand:QI 1 "arith_operand" "rI")) + (return)] + "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" + "* +{ + if (! TARGET_ARCH64 && current_function_returns_struct) + return \"jmp %%i7+12\;restore %%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\"; + else + return \"ret\;restore %%g0,%1,%Y0\"; +}" + [(set_attr "type" "multi")]) + +(define_insn "*return_hi" + [(set (match_operand:HI 0 "restore_operand" "") + (match_operand:HI 1 "arith_operand" "rI")) + (return)] + "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" + "* +{ + if (! TARGET_ARCH64 && current_function_returns_struct) + return \"jmp %%i7+12\;restore %%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\"; + else + return \"ret\;restore %%g0,%1,%Y0\"; +}" + [(set_attr "type" "multi")]) + +(define_insn "*return_si" + [(set (match_operand:SI 0 "restore_operand" "") + (match_operand:SI 1 "arith_operand" "rI")) + (return)] + "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" + "* +{ + if (! TARGET_ARCH64 && current_function_returns_struct) + return \"jmp %%i7+12\;restore %%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\"; + else + 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. +(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" + "* +{ + if (! TARGET_ARCH64 && current_function_returns_struct) + return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; + else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])) + return \"return %%i7+8\;mov %Y1,%Y0\"; + else + return \"ret\;restore %%g0,%1,%Y0\"; +}" + [(set_attr "type" "multi")]) + +(define_insn "*return_addsi" + [(set (match_operand:SI 0 "restore_operand" "") + (plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith_operand" "rI"))) + (return)] + "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" + "* +{ + if (! TARGET_ARCH64 && current_function_returns_struct) + return \"jmp %%i7+12\;restore %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\"; + else + return \"ret\;restore %r1,%2,%Y0\"; +}" + [(set_attr "type" "multi")]) + +(define_insn "*return_di" + [(set (match_operand:DI 0 "restore_operand" "") + (match_operand:DI 1 "arith_double_operand" "rHI")) + (return)] + "TARGET_ARCH64 && ! TARGET_EPILOGUE" + "ret\;restore %%g0,%1,%Y0" + [(set_attr "type" "multi")]) + +(define_insn "*return_adddi" + [(set (match_operand:DI 0 "restore_operand" "") + (plus:DI (match_operand:DI 1 "arith_operand" "%r") + (match_operand:DI 2 "arith_double_operand" "rHI"))) + (return)] + "TARGET_ARCH64 && ! TARGET_EPILOGUE" + "ret\;restore %r1,%2,%Y0" + [(set_attr "type" "multi")]) + +;; The following pattern is only generated by delayed-branch scheduling, +;; when the insn winds up in the epilogue. +(define_insn "*return_sf" + [(set (reg:SF 32) + (match_operand:SF 0 "register_operand" "f")) + (return)] + "! TARGET_EPILOGUE" + "ret\;fmovs %0,%%f0" + [(set_attr "type" "multi")]) + +;; Now peepholes to do a call followed by a jump. + +(define_peephole + [(parallel [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps")) + (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") + +(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") + +(define_peephole + [(parallel [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps")) + (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") + +(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") + +;; 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. + +(define_insn "nonlocal_goto_receiver" + [(unspec_volatile [(const_int 0)] 4)] + "flag_pic" + "") + +(define_insn "trap" + [(trap_if (const_int 1) (const_int 5))] + "" + "ta 5" + [(set_attr "type" "misc")]) + +(define_expand "conditional_trap" + [(trap_if (match_operator 0 "noov_compare_op" + [(match_dup 2) (match_dup 3)]) + (match_operand:SI 1 "arith_operand" ""))] + "" + "operands[2] = gen_compare_reg (GET_CODE (operands[0]), + sparc_compare_op0, sparc_compare_op1); + operands[3] = const0_rtx;") + +(define_insn "" + [(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")]) + +(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")]) + diff --git a/contrib/gcc/config/sparc/splet.h b/contrib/gcc/config/sparc/splet.h new file mode 100644 index 0000000..23c6414 --- /dev/null +++ b/contrib/gcc/config/sparc/splet.h @@ -0,0 +1,53 @@ +/* Definitions of target machine for GNU compiler, for SPARClet. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Doug Evans (dje@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. */ + +#include "sparc/aout.h" + +/* -mbroken-saverestore is not included here because the long term + default is -mno-broken-saverestore. */ +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE) + +/* -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}, + +#undef ASM_SPEC +#define ASM_SPEC "%{mlittle-endian:-EL} %(asm_cpu)" + +/* Require the user to supply crt0.o. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef LINK_SPEC +#define LINK_SPEC "%{mlittle-endian:-EL}" + +/* sparclet chips are bi-endian. */ +#undef BYTES_BIG_ENDIAN +#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) +#undef WORDS_BIG_ENDIAN +#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) diff --git a/contrib/gcc/config/sparc/sun4gas.h b/contrib/gcc/config/sparc/sun4gas.h new file mode 100644 index 0000000..3cea956 --- /dev/null +++ b/contrib/gcc/config/sparc/sun4gas.h @@ -0,0 +1,27 @@ +/* Definitions of target machine for GNU compiler, for SunOS 4.x with gas + Copyright (C) 1997 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. */ + +/* gas supports unaligned data. */ +#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword" +#define UNALIGNED_INT_ASM_OP ".uaword" +#define UNALIGNED_SHORT_ASM_OP ".uahalf" + +/* defaults.h will define DWARF2_UNWIND_INFO for us. */ +#undef DWARF2_UNWIND_INFO diff --git a/contrib/gcc/config/sparc/sun4o3.h b/contrib/gcc/config/sparc/sun4o3.h new file mode 100644 index 0000000..10c7391 --- /dev/null +++ b/contrib/gcc/config/sparc/sun4o3.h @@ -0,0 +1,29 @@ +#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)) + +/* LINK_SPEC is needed only for SunOS 4. */ + +#undef LINK_SPEC + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); diff --git a/contrib/gcc/config/sparc/sunos4.h b/contrib/gcc/config/sparc/sunos4.h new file mode 100644 index 0000000..14c7a43 --- /dev/null +++ b/contrib/gcc/config/sparc/sunos4.h @@ -0,0 +1,49 @@ +/* Definitions of target machine for GNU compiler, for SunOS 4.x + Copyright (C) 1994 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 SUNOS4_SHARED_LIBRARIES 1 + +/* Use N_BINCL stabs. */ + +#define DBX_USE_BINCL + +#include "sparc/sparc.h" + +/* The Sun as doesn't like unaligned data. */ +#define DWARF2_UNWIND_INFO 0 + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); diff --git a/contrib/gcc/config/sparc/sysv4.h b/contrib/gcc/config/sparc/sysv4.h new file mode 100644 index 0000000..7e90bdd --- /dev/null +++ b/contrib/gcc/config/sparc/sysv4.h @@ -0,0 +1,231 @@ +/* Target definitions for GNU compiler for Sparc running System V.4 + Copyright (C) 1991, 92, 95, 96, 97, 1998 Free Software Foundation, Inc. + Contributed 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, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "sparc/sparc.h" + +/* Undefine some symbols which are defined in "sparc.h" but which are + appropriate only for SunOS 4.x, and not for svr4. */ + +#undef WORD_SWITCH_TAKES_ARG +#undef ASM_OUTPUT_SOURCE_LINE +#undef SELECT_SECTION +#undef ASM_DECLARE_FUNCTION_NAME +#undef TEXT_SECTION_ASM_OP +#undef DATA_SECTION_ASM_OP + +#include "svr4.h" + +/* ??? Put back the SIZE_TYPE/PTRDIFF_TYPE definitions set by sparc.h. + Why, exactly, is svr4.h messing with this? Seems like the chip + would know best. */ + +#undef SIZE_TYPE +#define SIZE_TYPE (TARGET_ARCH64 ? "long unsigned int" : "unsigned int") + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE (TARGET_ARCH64 ? "long int" : "int") + +/* Undefined some symbols which are defined in "svr4.h" but which are + appropriate only for typical svr4 systems, but not for the specific + case of svr4 running on a Sparc. */ + +#undef INIT_SECTION_ASM_OP +#undef FINI_SECTION_ASM_OP +#undef CONST_SECTION_ASM_OP +#undef TYPE_OPERAND_FMT +#undef PUSHSECTION_FORMAT +#undef STRING_ASM_OP +#undef COMMON_ASM_OP +#undef SKIP_ASM_OP +#undef SET_ASM_OP /* Has no equivalent. See ASM_OUTPUT_DEF below. */ + +/* Provide a set of pre-definitions and pre-assertions appropriate for + the Sparc running svr4. __svr4__ is our extension. */ + +#define CPP_PREDEFINES \ +"-Dsparc -Dunix -D__svr4__ -Asystem(unix) -Asystem(svr4)" + +/* 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 + +/* Pass -K to the assembler when PIC. */ +#undef ASM_SPEC +#define ASM_SPEC \ + "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \ + %{fpic:-K PIC} %{fPIC:-K PIC} %(asm_cpu)" + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ +} + +/* Define the names of various pseudo-op used by the Sparc/svr4 assembler. + Note that many of these are different from the typical pseudo-ops used + by most svr4 assemblers. That is probably due to a (misguided?) attempt + to keep the Sparc/svr4 assembler somewhat compatible with the Sparc/SunOS + assembler. */ + +#define STRING_ASM_OP ".asciz" +#define COMMON_ASM_OP ".common" +#define SKIP_ASM_OP ".skip" +#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword" +#define UNALIGNED_INT_ASM_OP ".uaword" +#define UNALIGNED_SHORT_ASM_OP ".uahalf" +#define PUSHSECTION_ASM_OP ".pushsection" +#define POPSECTION_ASM_OP ".popsection" + +/* This is defined in sparc.h but is not used by svr4.h. */ +#undef ASM_LONG +#define ASM_LONG ".long" + +/* This is the format used to print the second operand of a .type pseudo-op + for the Sparc/svr4 assembler. */ + +#define TYPE_OPERAND_FMT "#%s" + +/* This is the format used to print a .pushsection pseudo-op (and its operand) + for the Sparc/svr4 assembler. */ + +#define PUSHSECTION_FORMAT "\t%s\t\"%s\"\n" + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \ +do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \ + ASM_OUTPUT_INTERNAL_LABEL ((FILE), PREFIX, NUM); \ + } while (0) + +/* This is how to equate one symbol to another symbol. The syntax used is + `SYM1=SYM2'. Note that this is different from the way equates are done + with most svr4 assemblers, where the syntax is `.set SYM1,SYM2'. */ + +#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) + +/* Define how the Sparc registers should be numbered for Dwarf output. + The numbering provided here should be compatible with the native + svr4 SDB debugger in the Sparc/svr4 reference port. The numbering + is as follows: + + Assembly name gcc internal regno Dwarf regno + ---------------------------------------------------------- + g0-g7 0-7 0-7 + o0-o7 8-15 8-15 + l0-l7 16-23 16-23 + i0-i7 24-31 24-31 + f0-f31 32-63 40-71 +*/ + +#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 32 ? (REGNO) : (REGNO) + 8) + +/* A set of symbol definitions for assembly pseudo-ops which will + get us switched to various sections of interest. These are used + in all places where we simply want to switch to a section, and + *not* to push the previous section name onto the assembler's + section names stack (as we do often in dwarfout.c). */ + +#define TEXT_SECTION_ASM_OP ".section\t\".text\"" +#define DATA_SECTION_ASM_OP ".section\t\".data\"" +#define BSS_SECTION_ASM_OP ".section\t\".bss\"" +#define CONST_SECTION_ASM_OP ".section\t\".rodata\"" +#define INIT_SECTION_ASM_OP ".section\t\".init\"" +#define FINI_SECTION_ASM_OP ".section\t\".fini\"" + +/* 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.) */ + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP ".section\t\".ctors\",#alloc,#write" +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP ".section\t\".dtors\",#alloc,#write" +#undef EH_FRAME_SECTION_ASM_OP +#define EH_FRAME_SECTION_ASM_OP ".section\t\".eh_frame\",#alloc,#write" + +/* 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 /* Override svr4.h's definition. */ +#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)); \ + 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 + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#undef ASM_OUTPUT_ALIGNED_BSS +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) diff --git a/contrib/gcc/config/sparc/t-elf b/contrib/gcc/config/sparc/t-elf new file mode 100644 index 0000000..da9df38 --- /dev/null +++ b/contrib/gcc/config/sparc/t-elf @@ -0,0 +1,39 @@ +# we need to supply our own assembly versions of libgcc1.c files, +# since the user may not have native 'cc' available + +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = sparc/lb1spc.asm +LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 + +# crt0 is built elsewhere +LIBGCC1_TEST = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +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 should have msparclite too, but we'd have to make +# gas build... +#MULTILIB_OPTIONS = msoft-float mcpu=v8 +MULTILIB_OPTIONS = msoft-float +#MULTILIB_DIRNAMES = soft v8 +MULTILIB_DIRNAMES = soft +#MULTILIB_MATCHES = msoft-float=mno-fpu mcpu?v8=mv8 +MULTILIB_MATCHES = msoft-float=mno-fpu + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +# Assemble startup files. +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 diff --git a/contrib/gcc/config/sparc/t-sol2 b/contrib/gcc/config/sparc/t-sol2 new file mode 100644 index 0000000..d41254a --- /dev/null +++ b/contrib/gcc/config/sparc/t-sol2 @@ -0,0 +1,30 @@ +# we need to supply our own assembly versions of libgcc1.c files, +# since the user may not have native 'cc' available + +LIBGCC1 = +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 + +# 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 + +# 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++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fPIC when compiling the +# routines in crtstuff.c. + +CRTSTUFF_T_CFLAGS = -fPIC +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/sparc/t-sp64 b/contrib/gcc/config/sparc/t-sp64 new file mode 100644 index 0000000..99acd5d --- /dev/null +++ b/contrib/gcc/config/sparc/t-sp64 @@ -0,0 +1,2 @@ +LIBGCC1 = +CROSS_LIBGCC1 = diff --git a/contrib/gcc/config/sparc/t-sparcbare b/contrib/gcc/config/sparc/t-sparcbare new file mode 100644 index 0000000..8bd978b --- /dev/null +++ b/contrib/gcc/config/sparc/t-sparcbare @@ -0,0 +1,26 @@ +# configuration file for a bare sparc cpu + +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = sparc/lb1spc.asm +LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +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 should have msparclite too, but we'd have to make +# gas build... +MULTILIB_OPTIONS = msoft-float mcpu=v8 +MULTILIB_DIRNAMES = soft v8 +MULTILIB_MATCHES = msoft-float=mno-fpu mcpu?v8=mv8 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/contrib/gcc/config/sparc/t-sparclite b/contrib/gcc/config/sparc/t-sparclite new file mode 100644 index 0000000..7cdfbb0 --- /dev/null +++ b/contrib/gcc/config/sparc/t-sparclite @@ -0,0 +1,24 @@ +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = sparc/lb1spl.asm +LIB1ASMFUNCS = _divsi3 _udivsi3 _modsi3 _umodsi3 + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define US_SOFTWARE_GOFAST' > dp-bit.c + cat $(srcdir)/config/fp-bit.c >> dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +MULTILIB_OPTIONS = mfpu mflat +MULTILIB_DIRNAMES = +MULTILIB_MATCHES = mfpu=mhard-float mfpu=mcpu?f934 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/contrib/gcc/config/sparc/t-splet b/contrib/gcc/config/sparc/t-splet new file mode 100644 index 0000000..3409f5d --- /dev/null +++ b/contrib/gcc/config/sparc/t-splet @@ -0,0 +1,23 @@ +# configuration file for a bare sparclet cpu, aout format files + +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = sparc/lb1spc.asm +LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +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 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/contrib/gcc/config/sparc/t-sunos40 b/contrib/gcc/config/sparc/t-sunos40 new file mode 100644 index 0000000..3e10575 --- /dev/null +++ b/contrib/gcc/config/sparc/t-sunos40 @@ -0,0 +1,7 @@ +# SunOS 4.0.* +# /bin/as doesn't recognize the v8 instructions, so we can't do a v8 +# multilib build. + +LIBGCC1 = +CROSS_LIBGCC1 = +LIBGCC1_TEST = diff --git a/contrib/gcc/config/sparc/t-sunos41 b/contrib/gcc/config/sparc/t-sunos41 new file mode 100644 index 0000000..5783d6a --- /dev/null +++ b/contrib/gcc/config/sparc/t-sunos41 @@ -0,0 +1,16 @@ +# SunOS 4.1.* + +LIBGCC1 = +CROSS_LIBGCC1 = +LIBGCC1_TEST = + +MULTILIB_OPTIONS = fpic/fPIC mcpu=v8 +MULTILIB_DIRNAMES = pic ucpic v8 +MULTILIB_MATCHES = mcpu?v8=mv8 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +# The native linker doesn't handle linking -fpic code with -fPIC code. Ugh. +# We cope by building both variants of libgcc. +#TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/sparc/t-vxsparc b/contrib/gcc/config/sparc/t-vxsparc new file mode 100644 index 0000000..0c7a14a --- /dev/null +++ b/contrib/gcc/config/sparc/t-vxsparc @@ -0,0 +1,17 @@ +LIBGCC1 = +CROSS_LIBGCC1 = + +# We don't want to build .umul, etc., because VxWorks provides them, +# which means that libgcc1-test will fail. +LIBGCC1_TEST = + +# We don't want to put exit in libgcc.a for VxWorks, because VxWorks +# does not have _exit. +TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit + +MULTILIB_OPTIONS=msoft-float mv8 +MULTILIB_DIRNAMES=soft v8 +MULTILIB_MATCHES=msoft-float=mno-fpu + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/contrib/gcc/config/sparc/vxsim.h b/contrib/gcc/config/sparc/vxsim.h new file mode 100644 index 0000000..6c80375 --- /dev/null +++ b/contrib/gcc/config/sparc/vxsim.h @@ -0,0 +1,131 @@ +/* Definitions of target machine for GNU compiler, for SPARC VxSim + Copyright 1996 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. */ + +/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */ +#include "sparc/sysv4.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-DCPU=SIMSPARCSOLARIS -D__vxworks -D__vxworks__ -Dsparc -D__svr4__ -D__SVR4 \ + -Asystem(embedded) -Asystem(svr4) -Acpu(sparc) -Amachine(sparc)\ + -D__GCC_NEW_VARARGS__" + +#undef CPP_SPEC +#define CPP_SPEC "" + +#undef CC1_SPEC +#define CC1_SPEC "-fno-builtin %{sun4:} %{target:}" + +/* 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:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \ + %{fpic:-K PIC} %{fPIC:-K PIC}" + +/* However it appears that Solaris 2.0 uses the same reg numbering as + the old BSD-style system did. */ + +#undef DBX_REGISTER_NUMBER +/* Same as sparc.h */ +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* We use stabs-in-elf for debugging, because that is what the native + toolchain uses. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */ +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.skip %u\n", (SIZE)) + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* 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'. */ + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + + + +#undef LIB_SPEC +#define LIB_SPEC "" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "" + +#undef LINK_SPEC +#define LINK_SPEC "-r" + +/* This defines which switch letters take arguments. + It is as in svr4.h but with -R added. */ + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + ( (CHAR) == 'D' \ + || (CHAR) == 'U' \ + || (CHAR) == 'o' \ + || (CHAR) == 'e' \ + || (CHAR) == 'u' \ + || (CHAR) == 'I' \ + || (CHAR) == 'm' \ + || (CHAR) == 'L' \ + || (CHAR) == 'R' \ + || (CHAR) == 'A' \ + || (CHAR) == 'h' \ + || (CHAR) == 'z') + +/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h. + Instead, it is enabled here, because it does work under Solaris. */ +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. */ +#define LONG_DOUBLE_TYPE_SIZE 64 diff --git a/contrib/gcc/config/sparc/vxsparc.h b/contrib/gcc/config/sparc/vxsparc.h new file mode 100644 index 0000000..18ce6ed --- /dev/null +++ b/contrib/gcc/config/sparc/vxsparc.h @@ -0,0 +1,61 @@ +/* Definitions of target machine for GNU compiler. Vxworks SPARC version. + Copyright (C) 1994, 1996 Free Software Foundation, Inc. + Contributed by David Henkel-Wallace (gumby@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. */ + +#include "sparc/aout.h" + +/* Specify what to link with. */ +/* VxWorks does all the library stuff itself. */ + +#undef LIB_SPEC +#define LIB_SPEC "" + +/* Provide required defaults for linker -e. */ +#undef LINK_SPEC +#define LINK_SPEC "%{!nostdlib:%{!r*:%{!e*:-e start}}}" + +/* VxWorks provides the functionality of crt0.o and friends itself. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)" + +/* Note that we define CPU here even if the user has specified -ansi. + This violates user namespace, but the VxWorks headers, and potentially + user code, all explicitly rely upon the definition of CPU in order to get + the proper processor information. */ +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) -DCPU=SPARC" + +#undef PTRDIFF_TYPE +#undef SIZE_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE + +#define PTRDIFF_TYPE "long int" +#define SIZE_TYPE "unsigned int" +#define WCHAR_TYPE "char" +#define WCHAR_TYPE_SIZE 8 + +/* US Software GOFAST library support. */ +#include "gofast.h" +#undef INIT_SUBTARGET_OPTABS +#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS diff --git a/contrib/gcc/config/sparc/x-sysv4 b/contrib/gcc/config/sparc/x-sysv4 new file mode 100644 index 0000000..2a661e3 --- /dev/null +++ b/contrib/gcc/config/sparc/x-sysv4 @@ -0,0 +1,2 @@ +X_CFLAGS=-DSVR4 +ALLOCA=alloca.o diff --git a/contrib/gcc/config/sparc/xm-linux.h b/contrib/gcc/config/sparc/xm-linux.h new file mode 100644 index 0000000..691c7d1 --- /dev/null +++ b/contrib/gcc/config/sparc/xm-linux.h @@ -0,0 +1,26 @@ +/* Configuration for GCC for SPARC running Linux-based GNU systems. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Eddie C. Dost (ecd@skynet.be) + +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 inhibit_libc +#include +#include +#include +#endif diff --git a/contrib/gcc/config/sparc/xm-lynx.h b/contrib/gcc/config/sparc/xm-lynx.h new file mode 100644 index 0000000..90fef85 --- /dev/null +++ b/contrib/gcc/config/sparc/xm-lynx.h @@ -0,0 +1,39 @@ +/* Configuration for GNU C-compiler for sparc platforms running LynxOS. + Copyright (C) 1995 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 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +#define HOST_WORDS_BIG_ENDIAN 1 + +/* Include to define the exit status access macros. */ +#include +#include + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + +#include "tm.h" diff --git a/contrib/gcc/config/sparc/xm-openbsd.h b/contrib/gcc/config/sparc/xm-openbsd.h new file mode 100644 index 0000000..2df7fb3 --- /dev/null +++ b/contrib/gcc/config/sparc/xm-openbsd.h @@ -0,0 +1,23 @@ +/* Configuration file for an host running sparc OpenBSD. + 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 +#include + diff --git a/contrib/gcc/config/sparc/xm-pbd.h b/contrib/gcc/config/sparc/xm-pbd.h new file mode 100644 index 0000000..1c3f475 --- /dev/null +++ b/contrib/gcc/config/sparc/xm-pbd.h @@ -0,0 +1,10 @@ +/* Host environment for the tti "Unicom" PBB 68020 boards */ + +#include "sparc/xm-sparc.h" + +#define USG + +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif + diff --git a/contrib/gcc/config/sparc/xm-sol2.h b/contrib/gcc/config/sparc/xm-sol2.h new file mode 100644 index 0000000..5613b08 --- /dev/null +++ b/contrib/gcc/config/sparc/xm-sol2.h @@ -0,0 +1,4 @@ +/* If not compiled with GNU C, include the system's header. */ +#ifndef __GNUC__ +#include +#endif diff --git a/contrib/gcc/config/sparc/xm-sp64.h b/contrib/gcc/config/sparc/xm-sp64.h new file mode 100644 index 0000000..5954aff --- /dev/null +++ b/contrib/gcc/config/sparc/xm-sp64.h @@ -0,0 +1,25 @@ +/* Configuration for GCC for Sparc v9 running 64-bit native. + Copyright (C) 1997 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 + +/* This describes the machine the compiler is hosted on. */ +#undef HOST_BITS_PER_LONG +#define HOST_BITS_PER_LONG 64 diff --git a/contrib/gcc/config/sparc/xm-sparc.h b/contrib/gcc/config/sparc/xm-sparc.h new file mode 100644 index 0000000..e553a0d --- /dev/null +++ b/contrib/gcc/config/sparc/xm-sparc.h @@ -0,0 +1,49 @@ +/* Configuration for GNU C-compiler for Sun Sparc. + Copyright (C) 1988, 1993, 1995, 1997 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@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. */ + + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Doubles are stored in memory with the high order word first. This + matters when cross-compiling. */ +#define HOST_WORDS_BIG_ENDIAN 1 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ +#include "tm.h" + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* If compiled with Sun CC, the use of alloca requires this #include. */ +#ifndef __GNUC__ +#include "alloca.h" +#endif diff --git a/contrib/gcc/config/sparc/xm-sysv4.h b/contrib/gcc/config/sparc/xm-sysv4.h new file mode 100644 index 0000000..6e663d1 --- /dev/null +++ b/contrib/gcc/config/sparc/xm-sysv4.h @@ -0,0 +1,48 @@ +/* Configuration for GNU C-compiler for Sun Sparc running System V.4. + Copyright (C) 1992, 1993, 1998 Free Software Foundation, Inc. + 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. */ + + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Doubles are stored in memory with the high order word first. This + matters when cross-compiling. */ +#define HOST_WORDS_BIG_ENDIAN 1 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ +#include "tm.h" + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +#ifndef __GNUC__ +#define ONLY_INT_FIELDS +#endif diff --git a/contrib/gcc/config/svr3.h b/contrib/gcc/config/svr3.h index fc6e262..3475561 100644 --- a/contrib/gcc/config/svr3.h +++ b/contrib/gcc/config/svr3.h @@ -1,8 +1,7 @@ -/* svr3.h -- operating system specific defines to be used when - targeting GCC for some generic System V Release 3 system. - Copyright (C) 1991 Free Software Foundation, Inc. - - Written by Ron Guilmette (rfg@netcom.com). +/* Operating system specific defines to be used when targeting GCC for + generic System V Release 3 system. + Copyright (C) 1991, 1996 Free Software Foundation, Inc. + Contributed by Ron Guilmette (rfg@monkeys.com). This file is part of GNU CC. @@ -103,7 +102,11 @@ Boston, MA 02111-1307, USA. #define STARTFILE_SPEC \ "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}" +#ifdef CROSS_COMPILE +#define LIB_SPEC "-lc crtn.o%s" +#else #define LIB_SPEC "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -lc crtn.o%s" +#endif /* Special flags for the linker. I don't know what they do. */ @@ -156,14 +159,13 @@ Boston, MA 02111-1307, USA. #undef ASM_BYTE_OP #define ASM_BYTE_OP "\t.byte" -/* This is how to output a reference to a user-level label named NAME. - `assemble_name' uses this. +/* The prefix to add to user-visible assembler symbols. For System V Release 3 the convention is to prepend a leading underscore onto user-level symbol names. */ -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "_%s", NAME) +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "_" /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. @@ -247,29 +249,17 @@ do { \ #endif /* STACK_GROWS_DOWNWARD */ -/* Add extra sections .init and .fini, in addition to .bss from att386.h. */ +/* Add extra sections .rodata, .init and .fini. */ #undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_bss, in_init, in_fini +#define EXTRA_SECTIONS in_const, in_init, in_fini #undef EXTRA_SECTION_FUNCTIONS #define EXTRA_SECTION_FUNCTIONS \ CONST_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION \ INIT_SECTION_FUNCTION \ FINI_SECTION_FUNCTION -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "\t%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} - #define INIT_SECTION_FUNCTION \ void \ init_section () \ diff --git a/contrib/gcc/config/svr4.h b/contrib/gcc/config/svr4.h index 41c6ffa..4737697 100644 --- a/contrib/gcc/config/svr4.h +++ b/contrib/gcc/config/svr4.h @@ -1,7 +1,7 @@ /* Operating system specific defines to be used when targeting GCC for some generic System V Release 4 system. - Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. - Contributed by Ron Guilmette (rfg@segfault.us.com). + Copyright (C) 1991, 94-97, 1998 Free Software Foundation, Inc. + Contributed by Ron Guilmette (rfg@monkeys.com). This file is part of GNU CC. @@ -53,16 +53,9 @@ Boston, MA 02111-1307, USA. thing as a -T option for svr4. */ #define SWITCH_TAKES_ARG(CHAR) \ - ( (CHAR) == 'D' \ - || (CHAR) == 'U' \ - || (CHAR) == 'o' \ - || (CHAR) == 'e' \ - || (CHAR) == 'u' \ - || (CHAR) == 'I' \ - || (CHAR) == 'm' \ - || (CHAR) == 'L' \ - || (CHAR) == 'A' \ + (DEFAULT_SWITCH_TAKES_ARG (CHAR) \ || (CHAR) == 'h' \ + || (CHAR) == 'x' \ || (CHAR) == 'z') /* This defines which multi-letter switches take arguments. On svr4, @@ -82,7 +75,7 @@ Boston, MA 02111-1307, USA. /* Provide an ASM_SPEC appropriate for svr4. Here we try to support as many of the specialized svr4 assembler options as seems reasonable, given that there are certain options which we can't (or shouldn't) - support directly due to the fact that they conflict with other options + support directly due to the fact that they conflict with other options for other svr4 tools (e.g. ld) or with other options for GCC itself. For example, we don't support the -o (output file) or -R (remove input file) options because GCC already handles these things. We @@ -97,7 +90,7 @@ Boston, MA 02111-1307, USA. #undef ASM_SPEC #define ASM_SPEC \ - "%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}" + "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}" /* svr4 assemblers need the `-' (indicating input from stdin) to come after the -o option (and its argument) for some reason. If we try to put it @@ -108,19 +101,23 @@ Boston, MA 02111-1307, USA. messages. */ #undef ASM_FINAL_SPEC -#define ASM_FINAL_SPEC "%{pipe:-}" +#define ASM_FINAL_SPEC "%|" /* Under svr4, the normal location of the `ld' and `as' programs is the /usr/ccs/bin directory. */ +#ifndef CROSS_COMPILE #undef MD_EXEC_PREFIX #define MD_EXEC_PREFIX "/usr/ccs/bin/" +#endif /* Under svr4, the normal location of the various *crt*.o files is the /usr/ccs/lib directory. */ +#ifndef CROSS_COMPILE #undef MD_STARTFILE_PREFIX #define MD_STARTFILE_PREFIX "/usr/ccs/lib/" +#endif /* Provide a LIB_SPEC appropriate for svr4. Here we tack on the default standard C library (unless we are building a shared library). */ @@ -128,12 +125,6 @@ Boston, MA 02111-1307, USA. #undef LIB_SPEC #define LIB_SPEC "%{!shared:%{!symbolic:-lc}}" -/* Provide a LIBGCC_SPEC appropriate for svr4. We also want to exclude - libgcc when -symbolic. */ - -#undef LIBGCC_SPEC -#define LIBGCC_SPEC "%{!shared:%{!symbolic:-lgcc}}" - /* Provide an ENDFILE_SPEC appropriate for svr4. Here we tack on our own magical crtend.o file (see crtstuff.c) which provides part of the support for getting C++ file-scope static object constructed before @@ -141,7 +132,7 @@ Boston, MA 02111-1307, USA. which is either `gcrtn.o' or `crtn.o'. */ #undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}" +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o%s}%{!pg:crtn.o%s}" /* Provide a LINK_SPEC appropriate for svr4. Here we provide support for the special GCC options -static, -shared, and -symbolic which @@ -150,7 +141,7 @@ Boston, MA 02111-1307, USA. support here for as many of the other svr4 linker options as seems reasonable, given that some of them conflict with options for other svr4 tools (e.g. the assembler). In particular, we do support the - -h*, -z*, -V, -b, -t, -Qy, -Qn, and -YP* options here, and the -e*, + -z*, -V, -b, -t, -Qy, -Qn, and -YP* options here, and the -e*, -l*, -o*, -r, -s, -u*, and -L* options are directly supported by gcc.c itself. We don't directly support the -m (generate load map) option because that conflicts with the -m (run m4) option of @@ -167,16 +158,27 @@ Boston, MA 02111-1307, USA. not being done. */ #undef LINK_SPEC -#define LINK_SPEC "%{h*} %{V} %{v:%{!V:-V}} \ +#ifdef CROSS_COMPILE +#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,*} \ + %{Qy:} %{!Qn:-Qy}" +#else +#define LINK_SPEC "%{h*} %{v:-V} \ %{b} %{Wl,*:%*} \ %{static:-dn -Bstatic} \ - %{shared:-G -dy -z text %{!h*:%{o*:-h %*}}} \ - %{symbolic:-Bsymbolic -G -dy -z text %{!h*:%{o*:-h %*}}} \ + %{shared:-G -dy -z text} \ + %{symbolic:-Bsymbolic -G -dy -z text} \ %{G:-G} \ %{YP,*} \ %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ %{!p:-Y P,/usr/ccs/lib:/usr/lib}} \ %{Qy:} %{!Qn:-Qy}" +#endif /* Gcc automatically adds in one of the files /usr/ccs/lib/values-Xc.o, /usr/ccs/lib/values-Xa.o, or /usr/ccs/lib/values-Xt.o for each final @@ -243,6 +245,10 @@ do { \ #define DWARF_DEBUGGING_INFO +/* All ELF targets can support DWARF-2. */ + +#define DWARF2_DEBUGGING_INFO + /* The numbers used to denote specific machine registers in the System V Release 4 DWARF debugging information are quite likely to be totally different from the numbers used in BSD stabs debugging information @@ -259,6 +265,10 @@ do { \ #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 @@ -320,8 +330,13 @@ while (0) embedded stabs. */ #define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ - fprintf (FILE, \ - "\t.text\n\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO) +do \ + { \ + text_section (); \ + fprintf (FILE, \ + "\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO); \ + } \ +while (0) /* Define the actual types of some ANSI-mandated types. (These definitions should work for most SVR4 systems). */ @@ -368,14 +383,13 @@ while (0) #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. +/* The prefix to add to user-visible assembler symbols. 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) +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. @@ -400,7 +414,7 @@ do { \ #undef ASM_GENERATE_INTERNAL_LABEL #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ do { \ - sprintf (LABEL, "*.%s%d", PREFIX, NUM); \ + sprintf (LABEL, "*.%s%d", PREFIX, (unsigned) (NUM)); \ } while (0) /* Output the label which precedes a jumptable. Note that for all svr4 @@ -463,6 +477,13 @@ do { \ ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ } while (0) +/* 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) + /* 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. */ @@ -573,15 +594,81 @@ dtors_section () \ } /* 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") + read-only for a const data decl, and writable for a non-const data decl. + + If the section has already been defined, we must not + emit the attributes here. The SVR4 assembler does not + recognize section redefinitions. + If DECL is NULL, no attributes are emitted. */ + +#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)) \ + prefix = "."; \ + 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. */ @@ -610,7 +697,9 @@ dtors_section () \ #define SELECT_SECTION(DECL,RELOC) \ { \ - if (TREE_CODE (DECL) == STRING_CST) \ + if (flag_pic && RELOC) \ + data_section (); \ + else if (TREE_CODE (DECL) == STRING_CST) \ { \ if (! flag_writable_strings) \ const_section (); \ @@ -619,11 +708,7 @@ dtors_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)))) \ + if (! DECL_READONLY_SECTION (DECL, RELOC)) \ data_section (); \ else \ const_section (); \ @@ -707,7 +792,10 @@ dtors_section () \ 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))); \ + putc (',', FILE); \ + fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \ + int_size_in_bytes (TREE_TYPE (DECL))); \ + fputc ('\n', FILE); \ } \ ASM_OUTPUT_LABEL(FILE, NAME); \ } while (0) @@ -729,7 +817,10 @@ do { \ 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))); \ + putc (',', FILE); \ + fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \ + int_size_in_bytes (TREE_TYPE (DECL))); \ + fputc ('\n', FILE); \ } \ } while (0) @@ -807,7 +898,7 @@ 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++) \ + for (; (ch = *_limited_str); _limited_str++) \ { \ register int escape; \ switch (escape = ESCAPES[ch]) \ diff --git a/contrib/gcc/config/t-freebsd b/contrib/gcc/config/t-freebsd new file mode 100644 index 0000000..5164669 --- /dev/null +++ b/contrib/gcc/config/t-freebsd @@ -0,0 +1,5 @@ +# Don't run fixproto +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 new file mode 100644 index 0000000..58969f2 --- /dev/null +++ b/contrib/gcc/config/t-gnu @@ -0,0 +1,13 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1=libgcc1.null + +# The pushl in CTOR initialization interferes with frame pointer elimination. + +# 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++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fPIC when compiling the +# routines in crtstuff.c. + +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/t-libc-ok b/contrib/gcc/config/t-libc-ok index 712a4ca..43e4f5e 100644 --- a/contrib/gcc/config/t-libc-ok +++ b/contrib/gcc/config/t-libc-ok @@ -1,2 +1,3 @@ LIBGCC1=libgcc1.null CROSS_LIBGCC1=libgcc1.null +CRTSTUFF_T_FLAGS_S=-fPIC diff --git a/contrib/gcc/config/t-linux-aout b/contrib/gcc/config/t-linux-aout new file mode 100644 index 0000000..8826cdd --- /dev/null +++ b/contrib/gcc/config/t-linux-aout @@ -0,0 +1,11 @@ +# Don't run fixproto +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = + +# Do not build libgcc1. Let gcc generate those functions. The GNU/Linux +# C library can handle them. +LIBGCC1 = +CROSS_LIBGCC1 = +LIBGCC1_TEST = diff --git a/contrib/gcc/config/t-netbsd b/contrib/gcc/config/t-netbsd new file mode 100644 index 0000000..85d6057 --- /dev/null +++ b/contrib/gcc/config/t-netbsd @@ -0,0 +1,9 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1=libgcc1.null +LIBGCC1_TEST= + +# Don't run fixproto +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = diff --git a/contrib/gcc/config/t-openbsd b/contrib/gcc/config/t-openbsd new file mode 100644 index 0000000..6bd8123 --- /dev/null +++ b/contrib/gcc/config/t-openbsd @@ -0,0 +1,9 @@ +# Don't run fixproto +STMP_FIXPROTO = + +# We don't need GCC's own include files but we do need lang specific ones. +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-openbsd-thread b/contrib/gcc/config/t-openbsd-thread new file mode 100644 index 0000000..4b25f25 --- /dev/null +++ b/contrib/gcc/config/t-openbsd-thread @@ -0,0 +1,5 @@ +# This is currently needed to compile libgcc2 for threads support +TARGET_LIBGCC2_CFLAGS=-pthread +#T_CFLAGS=-pthread +#T_CPPFLAGS=-pthread + diff --git a/contrib/gcc/config/t-rtems b/contrib/gcc/config/t-rtems new file mode 100644 index 0000000..aa0ca66 --- /dev/null +++ b/contrib/gcc/config/t-rtems @@ -0,0 +1,6 @@ +# RTEMS uses newlib which does not require prototype fixing +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. RTEMS uses the one in newlib. +INSTALL_ASSERT_H = + diff --git a/contrib/gcc/config/t-svr4 b/contrib/gcc/config/t-svr4 index d4abf48..e6be0c3 100644 --- a/contrib/gcc/config/t-svr4 +++ b/contrib/gcc/config/t-svr4 @@ -2,6 +2,7 @@ # crtstuff.c. This is only really needed when we are going to use gcc/g++ # to produce a shared library, but since we don't know ahead of time when # we will be doing that, we just always use -fPIC when compiling the -# routines in crtstuff.c. +# routines in crtstuff.c. Likewise for libgcc2.c. CRTSTUFF_T_CFLAGS = -fPIC +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/x-linux b/contrib/gcc/config/x-linux index ea2a5f2..a7c0917 100644 --- a/contrib/gcc/config/x-linux +++ b/contrib/gcc/config/x-linux @@ -1,14 +1,5 @@ -# It is defined in config/xm-linux.h. -# X_CFLAGS = -DPOSIX - -# The following is needed when compiling stages 2 and 3 because gcc's -# limits.h must be picked up before /usr/include/limits.h. This is because -# each does an #include_next of the other if the other hasn't been included. -# /usr/include/limits.h loses if it gets found first because /usr/include is -# at the end of the search order. When a new version of gcc is released, -# gcc's limits.h hasn't been installed yet and hence isn't found. - -BOOT_CFLAGS = -O $(CFLAGS) -Iinclude - # Don't run fixproto STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = diff --git a/contrib/gcc/config/x-linux-aout b/contrib/gcc/config/x-linux-aout new file mode 100644 index 0000000..36ae68a --- /dev/null +++ b/contrib/gcc/config/x-linux-aout @@ -0,0 +1,14 @@ +# It is defined in config/xm-linux.h. +# X_CFLAGS = -DPOSIX + +# The following is needed when compiling stages 2 and 3 because gcc's +# limits.h must be picked up before /usr/include/limits.h. This is because +# each does an #include_next of the other if the other hasn't been included. +# /usr/include/limits.h loses if it gets found first because /usr/include is +# at the end of the search order. When a new version of gcc is released, +# gcc's limits.h hasn't been installed yet and hence isn't found. + +# BOOT_CFLAGS = -O $(CFLAGS) -Iinclude + +# Don't run fixproto +# STMP_FIXPROTO = diff --git a/contrib/gcc/config/xm-alloca.h b/contrib/gcc/config/xm-alloca.h new file mode 100644 index 0000000..3dbdc37 --- /dev/null +++ b/contrib/gcc/config/xm-alloca.h @@ -0,0 +1,4 @@ +/* If not compiled with GNU C, use the portable alloca. */ +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif diff --git a/contrib/gcc/config/xm-freebsd.h b/contrib/gcc/config/xm-freebsd.h index f73c9aa..b71ff56 100644 --- a/contrib/gcc/config/xm-freebsd.h +++ b/contrib/gcc/config/xm-freebsd.h @@ -22,12 +22,3 @@ Boston, MA 02111-1307, USA. */ running FreeBSD. This file should not be specified as $xm_file itself; instead $xm_file should be CPU/xm-freebsd.h, which should include both CPU/xm-CPU.h and this file xm-freebsd.h. */ - -/* FreeBSD has strerror. */ -#define HAVE_STRERROR - -/* We have _sys_siglist, but the declaration in conflicts with - the declarations in collect2.c and mips-tfile.c, so disable the declarations - in those files. */ - -#define DONT_DECLARE_SYS_SIGLIST diff --git a/contrib/gcc/config/xm-gnu.h b/contrib/gcc/config/xm-gnu.h index 57e74f2..64e8e2f 100644 --- a/contrib/gcc/config/xm-gnu.h +++ b/contrib/gcc/config/xm-gnu.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for hosts running GNU. - Copyright (C) 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -23,9 +23,10 @@ Boston, MA 02111-1307, USA. */ instead $xm_file should be CPU/xm-gnu.h, which should include both CPU/xm-CPU.h and this file xm-gnu.h. */ -#define HAVE_STRERROR /* GNU has strerror. */ #define POSIX /* GNU complies to POSIX.1. */ +#ifndef inhibit_libc /* Get a definition of O_RDONLY; some of the GCC files don't include this properly and will define it themselves to be zero. */ #include +#endif diff --git a/contrib/gcc/config/xm-linux.h b/contrib/gcc/config/xm-linux.h index 5ffb0f2..2cffdb7 100644 --- a/contrib/gcc/config/xm-linux.h +++ b/contrib/gcc/config/xm-linux.h @@ -1,5 +1,5 @@ -/* Configuration for GCC for Intel i386 running Linux. - Copyright (C) 1995 Free Software Foundation, Inc. +/* Configuration for GCC for Intel i386 running Linux-based GNU systems. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. @@ -19,22 +19,15 @@ 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 HAVE_VPRINTF - -#define HAVE_STRERROR +#undef HAVE_ATEXIT +#define HAVE_ATEXIT +#undef POSIX #define POSIX -#define DONT_DECLARE_SYS_SIGLIST - /* We do have one, but I'd like to use the one come with gcc since we have been doing that for a long time with USG defined. H.J. */ -#define NO_STAB_H +#undef HAVE_STAB_H #undef BSTRING #define BSTRING -#undef bcmp -#undef bcopy -#undef bzero -#undef index -#undef rindex diff --git a/contrib/gcc/config/xm-netbsd.h b/contrib/gcc/config/xm-netbsd.h index 00000ce..099a923 100644 --- a/contrib/gcc/config/xm-netbsd.h +++ b/contrib/gcc/config/xm-netbsd.h @@ -23,5 +23,4 @@ Boston, MA 02111-1307, USA. */ instead $xm_file should be CPU/xm-netbsd.h, which should include both CPU/xm-CPU.h and this file xm-netbsd.h. */ -#define HAVE_STRERROR #define HAVE_VPRINTF diff --git a/contrib/gcc/config/xm-openbsd.h b/contrib/gcc/config/xm-openbsd.h new file mode 100644 index 0000000..74a8421 --- /dev/null +++ b/contrib/gcc/config/xm-openbsd.h @@ -0,0 +1,35 @@ +/* Configuration fragment for hosts running a version of OpenBSD. + 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 gets included by all architectures. It holds stuff + that ought to be defined when hosting a compiler on an OpenBSD + machine, independently of the architecture. It's included by + ${cpu_type}/xm-openbsd.h, not included directly. */ + +/* OpenBSD is trying to be POSIX-compliant, to the point of fixing + problems that may occur with gcc's interpretation. */ +#undef POSIX +#define POSIX + +/* Ensure we get gnu C's defaults. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#endif + + diff --git a/contrib/gcc/config/xm-siglist.h b/contrib/gcc/config/xm-siglist.h new file mode 100644 index 0000000..d6133d6 --- /dev/null +++ b/contrib/gcc/config/xm-siglist.h @@ -0,0 +1,6 @@ +/* Some systems provide no sys_siglist, but do offer the same data under + another name. */ + +#define sys_siglist _sys_siglist +#undef SYS_SIGLIST_DECLARED +#define SYS_SIGLIST_DECLARED diff --git a/contrib/gcc/config/xm-std32.h b/contrib/gcc/config/xm-std32.h new file mode 100644 index 0000000..c52782e --- /dev/null +++ b/contrib/gcc/config/xm-std32.h @@ -0,0 +1,34 @@ +/* Configuration for GNU C-compiler for standard 32-bit host machine. + Copyright (C) 1997 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. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 diff --git a/contrib/gcc/config/xm-svr3.h b/contrib/gcc/config/xm-svr3.h index ac1000f..6f25250 100644 --- a/contrib/gcc/config/xm-svr3.h +++ b/contrib/gcc/config/xm-svr3.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for hosts running System V Release 3 - Copyright (C) 1991, 1993 Free Software Foundation, Inc. + Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -18,15 +18,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. */ -#define bcopy(src,dst,len) memcpy ((dst),(src),(len)) -#define bzero(dst,len) memset ((dst),0,(len)) -#define bcmp(left,right,len) memcmp ((left),(right),(len)) - -#define rindex strrchr -#define index strchr - #define USG -#define HAVE_VPRINTF #ifndef SVR3 #define SVR3 diff --git a/contrib/gcc/config/xm-svr4.h b/contrib/gcc/config/xm-svr4.h index 3008432..8534aaa 100644 --- a/contrib/gcc/config/xm-svr4.h +++ b/contrib/gcc/config/xm-svr4.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for hosts running System V Release 4 - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -18,18 +18,12 @@ 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 bcopy(src,dst,len) memcpy ((dst),(src),(len)) -#define bzero(dst,len) memset ((dst),0,(len)) -#define bcmp(left,right,len) memcmp ((left),(right),(len)) - -#define rindex strrchr -#define index strchr - #define USG -#define HAVE_VPRINTF #define POSIX /* SVR4 provides no sys_siglist, but does offer the same data under another name. */ #define sys_siglist _sys_siglist +#undef SYS_SIGLIST_DECLARED +#define SYS_SIGLIST_DECLARED diff --git a/contrib/gcc/configure b/contrib/gcc/configure index 9c2b12e..d341217 100755 --- a/contrib/gcc/configure +++ b/contrib/gcc/configure @@ -1,488 +1,2234 @@ -#!/bin/sh -# Configuration script for GNU CC -# Copyright (C) 1988, 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc. +#! /bin/sh -#This file is part of GNU CC. +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. -#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. +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-gnu-ld arrange to work with GNU ld." +ac_help="$ac_help + --with-gnu-as arrange to work with GNU as." +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." +ac_help="$ac_help + --with-local-prefix=DIR specifies directory to put local include." +ac_help="$ac_help + --with-gxx-include-dir=DIR + specifies directory to put g++ header files." +ac_help="$ac_help + --enable-checking enable expensive run-time checks." +ac_help="$ac_help + --enable-c-cpplib Use cpplib for C." +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." +ac_help="$ac_help + --with-fast-fixincludes Use a faster fixinclude program. Experimental" +ac_help="$ac_help + --enable-threads enable thread usage for target GCC. + --enable-threads=LIB use LIB thread package for target GCC." -#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. +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' -#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. +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 -# -# Shell script to create proper links to machine-dependent files in -# preparation for compiling gcc. -# -# Options: --srcdir=DIR specifies directory where sources are. -# --host=HOST specifies host configuration. -# --target=TARGET specifies target configuration. -# --build=TARGET specifies configuration of machine you are -# using to compile GCC. -# --prefix=DIR specifies directory to install in. -# --local-prefix=DIR specifies directory to put local ./include in. -# --gxx-include-dir=DIR specifies directory to put g++ header files in. -# --exec-prefix=DIR specifies directory to install executables in. -# --with-gnu-ld arrange to work with GNU ld. -# --with-gnu-as arrange to work with GAS. -# --with-stabs arrange to use stabs instead of host debug format. -# --with-elf arrange to use elf instead of host debug format. -# --enable-FOO, --enable-FOO=BAR include feature FOO (parameter BAR) -# --disable-FOO do not include feature FOO -# --nfp assume system has no FPU. -# --program-prefix=PREFIX specifies prefix for executable names. -# --program-suffix=SUFFIX specifies suffix for executable names. -# --program-transform-name=SED-EXPR specifies `sed' expression to -# apply to executable names. -# -# If configure succeeds, it leaves its status in config.status. -# If configure fails after disturbing the status quo, -# config.status is removed. -# +ac_prev= +for ac_option +do -progname=$0 + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi -# Default --srcdir to the directory where the script is found, -# if a directory was specified. -# The second sed call is to convert `.//configure' to `./configure'. -srcdir=`echo $0 | sed 's|//|/|' | sed 's|/[^/]*$||'` -if [ x$srcdir = x$0 ] -then -srcdir= + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi -host= +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=tree.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi -# Default prefix to /usr/local. -prefix=/usr/local -# On systems where GCC is the native compiler, $prefix should be -# /usr. But the user can change it with configure --prefix=/foo/bar -native_prefix=/usr - -# local_prefix specifies where to find the directory /usr/local/include -# We don't use $(prefix) for this -# because we always want GCC to search /usr/local/include -# even if GCC is installed somewhere other than /usr/local. -# Think THREE TIMES before specifying any other value for this! -# DO NOT make this use $prefix! -local_prefix=/usr/local -# Default is to let the Makefile set exec_prefix from $(prefix) -exec_prefix='$(prefix)' -# -# The default g++ include directory is $(libdir)/g++-include. -gxx_include_dir='$(libdir)/g++-include' -# Default --program-transform-name to nothing. -program_transform_name= -program_transform_set= remove=rm hard_link=ln symbolic_link='ln -s' copy=cp -# Record all the arguments, to write them in config.status. -arguments=$* +# Check for additional parameters + +# With GNU ld +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + gnu_ld_flag="$with_gnu_ld" +else + gnu_ld_flag=no +fi + + +# With GNU as +# Check whether --with-gnu-as or --without-gnu-as was given. +if test "${with_gnu_as+set}" = set; then + withval="$with_gnu_as" + gas_flag="$with_gnu_as" +else + gas_flag=no +fi + + +# With stabs +# Check whether --with-stabs or --without-stabs was given. +if test "${with_stabs+set}" = set; then + withval="$with_stabs" + stabs="$with_stabs" +else + stabs=no +fi + + +# With ELF +# Check whether --with-elf or --without-elf was given. +if test "${with_elf+set}" = set; then + withval="$with_elf" + elf="$with_elf" +else + elf=no +fi + + +# Specify the local prefix +local_prefix= +# Check whether --with-local-prefix or --without-local-prefix was given. +if test "${with_local_prefix+set}" = set; then + withval="$with_local_prefix" + case "${withval}" in +yes) { echo "configure: error: bad value ${withval} given for local include directory prefix" 1>&2; exit 1; } ;; +no) ;; +*) local_prefix=$with_local_prefix ;; +esac +fi + + +# Default local prefix if it is empty +if [ x$local_prefix = x ]; then + local_prefix=/usr/local +fi + +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 + withval="$with_gxx_include_dir" + 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 ;; +esac +fi + + +if test x${gxx_include_dir} = x; then + if test x${enable_version_specific_runtime_libs} = xyes; then + gxx_include_dir='${libsubdir}/include/g++' + else + gxx_include_dir='${prefix}/include/g++' + fi +fi + +# Enable expensive internal checks +# Check whether --enable-checking or --disable-checking was given. +if test "${enable_checking+set}" = set; then + enableval="$enable_checking" + case "${enableval}" in +yes) cat >> confdefs.h <<\EOF +#define ENABLE_CHECKING 1 +EOF + ;; +no) ;; +*) { echo "configure: error: bad value ${enableval} given for checking option" 1>&2; exit 1; } ;; +esac +fi + + +# Enable use of cpplib for C. +cpp_main=cccp +# 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 + cpp_main=cppmain +fi +fi + + +# Enable Haifa scheduler. +# Check whether --enable-haifa or --disable-haifa was given. +if test "${enable_haifa+set}" = set; then + enableval="$enable_haifa" + : +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 +# Pass with a value to specify a thread package +# 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 + enable_threads='' +fi +else + enable_threads='' +fi + + +enable_threads_flag=$enable_threads +# Check if a valid thread package +case x${enable_threads_flag} in + x | xno) + # No threads + target_thread_file='single' + ;; + xyes) + # default + target_thread_file='' + ;; + xdecosf1 | xirix | xmach | xos2 | xposix | xpthreads | xsingle | \ + xsolaris | xwin32 | xdce | xvxworks) + target_thread_file=$enable_threads_flag + ;; + *) + echo "$enable_threads is an unknown thread package" 1>&2 + exit 1 + ;; +esac + +# Determine the host, build, and target systems +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +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 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +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 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +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 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +# Find the native compiler +# 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 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # 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_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +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 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # 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 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # 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_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +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 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 961 "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 + 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 + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +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 "$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 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +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 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:1057: 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 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +# Find some useful tools +for ac_prog in mawk gawk 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 +if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # 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_AWK="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AWK="$ac_cv_prog_AWK" +if test -n "$AWK"; then + echo "$ac_t""$AWK" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AWK" && break +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 +if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # 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_LEX="flex" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex" +fi +fi +LEX="$ac_cv_prog_LEX" +if test -n "$LEX"; then + echo "$ac_t""$LEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$LEXLIB" +then + case "$LEX" in + flex*) ac_lib=fl ;; + *) 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 +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 +else + ac_save_LIBS="$LIBS" +LIBS="-l$ac_lib $LIBS" +cat > conftest.$ac_ext <&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 + LEXLIB="-l$ac_lib" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking whether ln works""... $ac_c" 1>&6 +echo "configure:1198: 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 + rm -f conftestdata_t +echo >conftestdata_f +if ln conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN="ln" +else + if ln -s conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN="ln -s" + else + gcc_cv_prog_LN=cp + fi +fi +rm -f conftestdata_f conftestdata_t + +fi +LN="$gcc_cv_prog_LN" +if test "$gcc_cv_prog_LN" = "ln"; then + echo "$ac_t""yes" 1>&6 +else + if test "$gcc_cv_prog_LN" = "ln -s"; then + echo "$ac_t""no, using ln -s" 1>&6 + else + echo "$ac_t""no, and neither does ln -s, so using cp" 1>&6 + fi +fi + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1230: 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 + rm -f conftestdata_t +echo >conftestdata_f +if ln -s conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN_S="ln -s" +else + if ln conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN_S=ln + else + gcc_cv_prog_LN_S=cp + fi +fi +rm -f conftestdata_f conftestdata_t + +fi +LN_S="$gcc_cv_prog_LN_S" +if test "$gcc_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + if test "$gcc_cv_prog_LN_S" = "ln"; then + echo "$ac_t""no, using ln" 1>&6 + else + echo "$ac_t""no, and neither does ln, so using cp" 1>&6 + fi +fi + +echo $ac_n "checking for volatile""... $ac_c" 1>&6 +echo "configure:1262: 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 <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_c_volatile=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_c_volatile=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_c_volatile" 1>&6 +if test $gcc_cv_c_volatile = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_VOLATILE 1 +EOF + +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 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # 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_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +for ac_prog in 'bison -y' byacc +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 +if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # 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_YACC="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +YACC="$ac_cv_prog_YACC" +if test -n "$YACC"; then + echo "$ac_t""$YACC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# 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 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +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 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +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; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +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; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +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; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +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 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +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; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +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 +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +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 +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +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 +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +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 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:1619: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 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 wait.h sys/wait.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 +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 +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; } +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 <&6 +fi +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 +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 +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; } +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 + have_thread_h=yes +else + echo "$ac_t""no" 1>&6 +have_thread_h= +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 +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 +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; } +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 + have_pthread_h=yes +else + echo "$ac_t""no" 1>&6 +have_pthread_h= +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 +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 <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_c_have_stringify=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_c_have_stringify=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_c_have_stringify" 1>&6 +if test $gcc_cv_c_have_stringify = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_CPP_STRINGIFY 1 +EOF + +fi + +# Use only if it exists, +# doesn't clash with , and declares intmax_t. +echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6 +echo "configure:1789: 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 < +#include +int main() { +intmax_t i = -1; +; return 0; } +EOF +if { (eval echo configure:1802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_header_inttypes_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_header_inttypes_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_header_inttypes_h" 1>&6 +if test $gcc_cv_header_inttypes_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_INTTYPES_H 1 +EOF + +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 +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1827: 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 < +/* 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:1855: \"$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 <&6 +fi +done + + +echo $ac_n "checking for vprintf""... $ac_c" 1>&6 +echo "configure:1881: 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 < +/* 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 vprintf(); + +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_vprintf) || defined (__stub___vprintf) +choke me +#else +vprintf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1909: \"$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 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_vprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_VPRINTF 1 +EOF + +else + echo "$ac_t""no" 1>&6 +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 +if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* 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 _doprnt(); + +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__doprnt) || defined (__stub____doprnt) +choke me +#else +_doprnt(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1961: \"$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 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func__doprnt=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_DOPRNT 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +fi + +vfprintf= +doprint= +if test $ac_cv_func_vprintf != yes ; then + vfprintf=vfprintf.o + if test $ac_cv_func__doprnt != yes ; then + doprint=doprint.o + fi +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 +if eval "test \"`echo '$''{'gcc_cv_func_printf_ptr'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + gcc_cv_func_printf_ptr=no +else + cat > conftest.$ac_ext < + +main() +{ + char buf[64]; + char *p = buf, *q = NULL; + sprintf(buf, "%p", p); + sscanf(buf, "%p", &q); + 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 +then + gcc_cv_func_printf_ptr=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + gcc_cv_func_printf_ptr=no +fi +rm -fr conftest* +fi + +rm -f core core.* *.core +fi + +echo "$ac_t""$gcc_cv_func_printf_ptr" 1>&6 +if test $gcc_cv_func_printf_ptr = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_PRINTF_PTR 1 +EOF + +fi + + +for ac_func in malloc realloc calloc free bcopy bzero bcmp \ + index rindex getenv atol sbrk abort atof strerror getcwd getwd +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 +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 < +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifndef HAVE_RINDEX +#define rindex strrchr +#endif +#ifndef HAVE_INDEX +#define index strchr +#endif -#for Test -#remove="echo rm" -#hard_link="echo ln" -#symbolic_link="echo ln -s" +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 + rm -rf conftest* + eval "gcc_cv_decl_needed_$ac_func=no" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "gcc_cv_decl_needed_$ac_func=yes" +fi +rm -f conftest* +fi -target= -host= -build= -name1= -name2= +if eval "test \"`echo '$gcc_cv_decl_needed_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + gcc_tr_decl=NEED_DECLARATION_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&2 - exit 1 - fi - ;; - esac +else + echo "$ac_t""no" 1>&6 +fi - case $arg in - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - next_arg=--srcdir - ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=`echo $arg | sed 's/-*s[a-z]*=//'` - ;; - -host | --host | --hos | --ho) - next_arg=--host - ;; - -host=* | --host=* | --hos=* | --ho=*) - host=`echo $arg | sed 's/-*h[a-z]*=//'` - ;; - -target | --target | --targe | --targ | --tar | --ta | --t) - next_arg=--target - ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target=`echo $arg | sed 's/-*t[a-z]*=//'` - ;; - -build | --build | --buil | --bui | --bu | --b) - next_arg=--build - ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) - build=`echo $arg | sed 's/-*b[a-z]*=//'` - ;; - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - next_arg=--prefix - ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=`echo $arg | sed 's/-*p[a-z]*=//'` - native_prefix=$prefix - ;; - -local-prefix | --local-prefix | --local-prefi | --local-pref | --local-pre \ - | --local-pr | --local-p | --local- | --local | --loc | --lo | --l) - next_arg=--local-prefix - ;; - -local-prefix=* | --local-prefix=* | --local-prefi=* | --local-pref=* \ - | --local-pre=* | --local-pr=* | --local-p=* | --local-=* | --local=* \ - | --loc=* | --lo=* | --l=*) - local_prefix=`echo $arg | sed 's/-*l[-a-z]*=//'` - ;; - -gxx-include-dir | --gxx-include-dir | --gxx-include \ - | --gxx-incl | --gxx-inc | --gxx-in | --gxx-i | --gxx- \ - | --gxx | --gxx | --gx | --g) - next_arg=--gxx-include-dir - ;; - -gxx-include-dir=* | --gxx-include-dir=* | --gxx-include=* \ - | --gxx-incl=* | --gxx-inc=* | --gxx-in=* | --gxx-i=* \ - | --gxx-=* | --gxx=* | --gxx=* | --gxx=* | --g=*) - gxx_include_dir=`echo $arg | sed 's/-*g[-a-z]*=//'` - ;; - -exec-prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre \ - | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e) - next_arg=--exec-prefix - ;; - -exec-prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* \ - | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* \ - | --exe=* | --ex=* | --e=*) - exec_prefix=`echo $arg | sed 's/-*e[-a-z]*=//'` - ;; - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- | --program-transform \ - | --program-transfor | --program-transfo | --program-transf \ - | --program-trans | --program-tran | --program-tra \ - | --program-tr | --program-t) - next_arg=--program-transform-name - ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* | --program-transfo=* \ - | --program-transf=* | --program-trans=* | --program-tran=* \ - | --program-tra=* | --program-tr=* | --program-t=*) - arg=`echo ${arg} | sed -e 's/^[-a-z_]*=//'` - # Double any \ or $ in the argument. - if [ -n "${arg}" ] ; then - program_transform_name="${program_transform_name} -e `echo ${arg} | sed -e 's/\\\\/\\\\\\\\/g' -e 's/\\\$/$$/g'`" - fi - program_transform_set=yes - ;; - -program-prefix | --program-prefix | --program-prefi \ - | --program-pref | --program-pre | --program-pr \ - | --program-p) - next_arg=--program-prefix - ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* \ - | --program-p=*) - arg=`echo ${arg} | sed -e 's/^[-a-z_]*=//'` - if [ -n "${arg}" ]; then - program_transform_name="${program_transform_name} -e s,^,`echo ${arg} | sed -e 's/\\\\/\\\\\\\\/g' -e 's/\\\$/$$/g'`," - fi - program_transform_set=yes - ;; - -program-suffix | --program-suffix | --program-suffi \ - | --program-suff | --program-suf | --program-su \ - | --program-s) - next_arg=--program-suffix - ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* \ - | --program-s=*) - arg=`echo ${arg} | sed -e 's/^[-a-z_]*=//'` - if [ -n "${arg}" ]; then - program_transform_name="${program_transform_name} -e s,\$\$,`echo ${arg} | sed -e 's/\\\\/\\\\\\\\/g' -e 's/\\\$/$$/g'`," - fi - program_transform_set=yes - ;; - -with-gnu-ld | --with-gnu-ld | --with-gnu-l) - gnu_ld=yes - ;; - -gas | --gas | --ga | --g | -with-gnu-as | --with-gnu-as | -with-gnu-a) - gas=yes - ;; - -nfp | --nfp | --nf | --n) - nfp=yes - ;; - -with-stabs | -with-stab | -with-sta | -with-st | -with-s \ - | --with-stabs | --with-stab | --with-sta | --with-st | --with-s \ - | -stabs | -stab | -sta | -st \ - | --stabs | --stab | --sta | --st) - stabs=yes - ;; - -with-elf | -with-el | -with-se \ - | --with-elf | --with-el | --with-e \ - | -elf | -el | -e \ - |--elf | --el | --e) - elf=yes - ;; - -with-* | --with-*) ;; #ignored - -without-* | --without-*) ;; #ignored - -disable-* | --disable-*) - enableopt=`echo ${arg} | sed 's:^-*disable-:enable_:;s:-:_:g'` - eval $enableopt=no - ;; - -enable-* | --enable-*) - case "$arg" in - *=*) optarg=`echo $arg | sed 's:^[^=]*=::;s:-:_:g'` ;; - *) optarg=yes ;; - esac - enableopt=`echo ${arg} | sed 's:^-*::;s:=.*$::;s:-:_:g'` - eval $enableopt="$optarg" - ;; - -x | --x) ;; # ignored - -x-*=* | --x-*=*) ;; # ignored - -x-* | --x-*) - next_arg=--x-ignored # ignored - ;; - --he*) ;; # ignored for now (--help) - --vers*) ;; # ignored for now (--version) - -v | -verb* | --verb*) ;; # ignored for now (--verbose) - --program-*) ;; #ignored (--program-prefix, --program-suffix) - --c*) ;; #ignored (--cache-file) - --q*) ;; #ignored (--quiet) - --si*) ;; #ignored (--silent) - -*) - echo "Invalid option \`$arg'" 1>&2 - exit 1 - ;; - *) -# Allow configure HOST TARGET. If just one name is given, it is used -# as both unless a host was previously given, in which case it is -# just the target. - if [ x$name1 != x ] - then - if [ x$name2 != x ] - then - echo "More than two configuration names." 1>&2 - exit 1 - fi - name2=$arg - elif [ x$host != x ] - then - name1=$host - name2=$arg - host= - else - name1=$arg - fi - ;; - esac - esac done -if [ x$name1 != x ] -then - if [ x$name2 = x ] - then - name2=$name1 - fi - if [ x$host != x ] - then - echo "Duplicate specification of host." 1>&2 - exit 1 - fi +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 +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 <&2 - exit 1 - fi +#include +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifndef HAVE_RINDEX +#define rindex strrchr +#endif +#ifndef HAVE_INDEX +#define index strchr +#endif +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif - host=$name1 - build=$name1 - target=$name2 +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 + rm -rf conftest* + eval "gcc_cv_decl_needed_$ac_func=no" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "gcc_cv_decl_needed_$ac_func=yes" fi - -# Find the source files, if location was not specified. -if [ x$srcdir = x ] -then - srcdirdefaulted=1 - srcdir=. - if [ ! -r tree.c ] - then - srcdir=.. - fi +rm -f conftest* fi -if [ ! -r ${srcdir}/tree.c ] -then - if [ x$srcdirdefaulted = x ] - then - echo "$progname: Can't find compiler sources in \`${srcdir}'" 1>&2 - else - echo "$progname: Can't find compiler sources in \`.' or \`..'" 1>&2 - fi - exit 1 -fi +if eval "test \"`echo '$gcc_cv_decl_needed_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + gcc_tr_decl=NEED_DECLARATION_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&2 - exit 1 +else + echo "$ac_t""no" 1>&6 fi -# Complain if an arg is missing -if [ x$build = x ] -then - # If host was specified, always use it for build also to avoid - # confusion. If someone wants a cross compiler where build != host, - # then they must specify build explicitly. Since this case is - # extremely rare, it does not matter that it is slightly inconvenient. - if [ x$host != x ] - then - build=$host - - # This way of testing the result of a command substitution is - # defined by Posix.2 (section 3.9.1) as well as traditional shells. - elif build=`${srcdir}/config.guess` - then - echo "This appears to be a ${build} system." 1>&2 +done - elif [ x$target != x ] - then - echo 'Config.guess failed to determine the host type. Defaulting to target.' - build=$target - else - echo 'Config.guess failed to determine the host type. You need to specify one.' 1>&2 - echo "\ -Usage: `basename $progname` [--host=HOST] [--build=BUILD] - [--prefix=DIR] [--gxx-include-dir=DIR] [--local-pref=DIR] [--exec-pref=DIR] - [--with-gnu-as] [--with-gnu-ld] [--with-stabs] [--with-elf] [--nfp] TARGET" 1>&2 - echo "Where HOST, TARGET and BUILD are three-part configuration names " 1>&2 - if [ -r config.status ] - then - tail +2 config.status 1>&2 - fi - exit 1 - fi -fi -# If $host was not specified, use $build. -if [ x$host = x ] -then - host=$build +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 +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 < +#include +/* NetBSD declares sys_siglist in unistd.h. */ +#ifdef HAVE_UNISTD_H +#include +#endif +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 + rm -rf conftest* + ac_cv_decl_sys_siglist=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_decl_sys_siglist=no +fi +rm -f conftest* fi -# If $target was not specified, use $host. -if [ x$target = x ] -then - target=$host +echo "$ac_t""$ac_cv_decl_sys_siglist" 1>&6 +if test $ac_cv_decl_sys_siglist = yes; then + cat >> confdefs.h <<\EOF +#define SYS_SIGLIST_DECLARED 1 +EOF + fi + +# File extensions +manext='.1' +objext='.o' + + + build_xm_file= +build_xm_defines= +build_install_headers_dir=install-headers-tar +build_exeext= host_xm_file= +host_xm_defines= host_xmake_file= -host_broken_install= -host_install_headers_dir=install-headers-tar host_truncate_target= - -# Validate the specs, and canonicalize them. -canon_build=`/bin/sh $srcdir/config.sub $build` || exit 1 -canon_host=`/bin/sh $srcdir/config.sub $host` || exit 1 -canon_target=`/bin/sh $srcdir/config.sub $target` || exit 1 +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; # then we decode the target machine and forget everything else # that came from the host machine. -for machine in $canon_build $canon_host $canon_target; do +for machine in $build $host $target; do - cpu_type= - xm_file= - tm_file= out_file= xmake_file= tmake_file= @@ -491,15 +2237,18 @@ for machine in $canon_build $canon_host $canon_target; do extra_parts= extra_programs= extra_objs= + extra_host_objs= extra_gcc_objs= + xm_defines= + float_format= # Set this to force installation and use of collect2. use_collect2= # Set this to override the default target model. target_cpu_default= - # Set this to force use of install.sh. - broken_install= # Set this to control which fixincludes program to use. - fixincludes=fixincludes + 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 @@ -509,6 +2258,74 @@ for machine in $canon_build $canon_host $canon_target; do truncate_target= # Set this if gdb needs a dir command with `dirname $out_file` gdb_needs_out_file_path= + # Set this if the build machine requires executables to have a + # file name suffix. + exeext= + # Set this to control which thread package will be used. + thread_file= + # Reinitialize these from the flag values every loop pass, since some + # configure entries modify them. + gas="$gas_flag" + gnu_ld="$gnu_ld_flag" + enable_threads=$enable_threads_flag + + # Set default cpu_type, tm_file and xm_file so it can be updated in + # each machine entry. + cpu_type=`echo $machine | sed 's/-.*$//'` + case $machine in + alpha*-*-*) + cpu_type=alpha + ;; + arm*-*-*) + cpu_type=arm + ;; + c*-convex-*) + cpu_type=convex + ;; + i[34567]86-*-*) + cpu_type=i386 + ;; + hppa*-*-*) + cpu_type=pa + ;; + m68000-*-*) + cpu_type=m68k + ;; + mips*-*-*) + cpu_type=mips + ;; + powerpc*-*-*) + cpu_type=rs6000 + ;; + pyramid-*-*) + cpu_type=pyr + ;; + sparc*-*-*) + cpu_type=sparc + ;; + esac + + tm_file=${cpu_type}/${cpu_type}.h + xm_file=${cpu_type}/xm-${cpu_type}.h + + # Common parts for linux-gnu and openbsd systems + case $machine in + *-*-linux-gnu*) + xm_defines="HAVE_ATEXIT POSIX BSTRING" + ;; + *-*-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 + if test x$enable_threads = xyes; then + thread_file='posix' + tmake_file="${tmake_file} t-openbsd-thread" + fi + ;; + esac case $machine in # Support site-specific machine types. @@ -529,74 +2346,138 @@ for machine in $canon_build $canon_host $canon_target; do 1750a-*-*) ;; a29k-*-bsd* | a29k-*-sym1*) - tm_file=a29k/unix.h - xm_file=a29k/xm-unix.h + tm_file="${tm_file} a29k/unix.h" + xm_defines=USG xmake_file=a29k/x-unix - tmake_file=a29k/t-a29k use_collect2=yes ;; a29k-*-udi | a29k-*-coff) + tm_file="${tm_file} dbxcoff.h a29k/udi.h" tmake_file=a29k/t-a29kbare - tm_file=a29k/a29k-udi.h ;; - a29k-*-vxworks*) + a29k-wrs-vxworks*) + tm_file="${tm_file} dbxcoff.h a29k/udi.h a29k/vx29k.h" tmake_file=a29k/t-vx29k - tm_file=a29k/vx29k.h extra_parts="crtbegin.o crtend.o" + thread_file='vxworks' ;; a29k-*-*) # Default a29k environment. use_collect2=yes ;; - alpha-dec-osf[23456789]*) - tm_file=alpha/osf2.h - if [ x$stabs = xyes ] - then - tm_file=alpha/gdb-osf2.h - fi - if [ x$gas != xyes ] - then - extra_passes="mips-tfile mips-tdump" - fi - broken_install=yes - use_collect2=yes + alpha*-*-linux-gnuecoff*) + tm_file="${tm_file} alpha/linux-ecoff.h alpha/linux.h" + target_cpu_default="MASK_GAS" + gas=no + xmake_file=none + gas=yes gnu_ld=yes + ;; + 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" + extra_parts="crtbegin.o crtend.o" + fixincludes=fixinc.wrap + xmake_file=none + gas=yes gnu_ld=yes + if [ 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" + extra_parts="crtbegin.o crtend.o" + xmake_file=none + fixincludes=Makefile.in + gas=yes gnu_ld=yes + if [ 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}" + target_cpu_default="MASK_GAS" + tmake_file="alpha/t-crtbe" + 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 ;; - alpha-dec-osf1.2) - tm_file=alpha/osf12.h + + alpha*-dec-osf*) if [ x$stabs = xyes ] then - tm_file=alpha/gdb-osf12.h + tm_file="${tm_file} dbx.h" fi if [ x$gas != xyes ] then extra_passes="mips-tfile mips-tdump" fi - broken_install=yes use_collect2=yes + case $machine in + *-*-osf1*) + tm_file="${tm_file} alpha/osf.h alpha/osf12.h alpha/osf2or3.h" + ;; + *-*-osf[23]*) + tm_file="${tm_file} alpha/osf.h alpha/osf2or3.h" + ;; + *-*-osf4*) + tm_file="${tm_file} alpha/osf.h" + # Some versions of OSF4 (specifically X4.0-9 296.7) have + # a broken tar, so we use cpio instead. + install_headers_dir=install-headers-cpio + ;; + esac + case $machine in + *-*-osf4.0[b-z] | *-*-osf4.[1-9]*) + target_cpu_default=MASK_SUPPORT_ARCH + ;; + esac ;; - alpha-*-osf*) - if [ x$stabs = xyes ] - then - tm_file=alpha/gdb.h - fi - if [ x$gas != xyes ] + alpha*-*-vxworks*) + tm_file="${tm_file} dbx.h alpha/vxworks.h" + if x$gas != xyes then extra_passes="mips-tfile mips-tdump" fi - broken_install=yes use_collect2=yes ;; - alpha-*-winnt3*) - tm_file=alpha/win-nt.h - xm_file=alpha/xm-winnt.h + alpha*-*-winnt*) + tm_file="${tm_file} alpha/win-nt.h" + xm_file="${xm_file} config/winnt/xm-winnt.h alpha/xm-winnt.h" tmake_file=t-libc-ok xmake_file=winnt/x-winnt - extra_objs=oldnames.o + extra_host_objs=oldnames.o extra_gcc_objs="spawnv.o oldnames.o" fixincludes=fixinc.winnt if [ x$gnu_ld != xyes ] then extra_programs=ld.exe fi + if [ 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 + ;; + arc-*-elf*) + extra_parts="crtinit.o crtfini.o" + ;; + arm-*-coff* | armel-*-coff*) + tm_file=arm/coff.h + tmake_file=arm/t-bare ;; arm-*-riscix1.[01]*) # Acorn RISC machine (early versions) tm_file=arm/riscix1-1.h @@ -614,51 +2495,65 @@ for machine in $canon_build $canon_host $canon_target; do use_collect2=yes ;; arm-semi-aout | armel-semi-aout) - cpu_type=arm tm_file=arm/semi.h tmake_file=arm/t-semi fixincludes=Makefile.in # There is nothing to fix ;; - arm-*-*) # generic version + 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}" + tmake_file="t-netbsd arm/t-netbsd" + # On NetBSD, the headers are already okay, except for math.h. + fixincludes=fixinc.wrap + ;; + arm-*-linux-gnuaout*) # ARM GNU/Linux + cpu_type=arm + xmake_file=x-linux + tm_file=arm/linux-gas.h + tmake_file=arm/t-linux + fixincludes=Makefile.in + gnu_ld=yes + ;; + arm-*-aout) + tm_file=arm/aout.h + tmake_file=arm/t-bare ;; c1-convex-*) # Convex C1 - cpu_type=convex - tm_file=convex/convex1.h + target_cpu_default=1 use_collect2=yes fixincludes=Makefile.in ;; c2-convex-*) # Convex C2 - cpu_type=convex - tm_file=convex/convex2.h + target_cpu_default=2 use_collect2=yes fixincludes=Makefile.in ;; c32-convex-*) - cpu_type=convex - tm_file=convex/convex32.h # Convex C32xx + target_cpu_default=4 use_collect2=yes fixincludes=Makefile.in ;; c34-convex-*) - cpu_type=convex - tm_file=convex/convex34.h # Convex C34xx + target_cpu_default=8 use_collect2=yes fixincludes=Makefile.in ;; c38-convex-*) - cpu_type=convex - tm_file=convex/convex38.h # Convex C38xx + target_cpu_default=16 use_collect2=yes fixincludes=Makefile.in ;; clipper-intergraph-clix*) - broken_install=yes - cpu_type=clipper + tm_file="${tm_file} svr3.h clipper/clix.h" xm_file=clipper/xm-clix.h - tm_file=clipper/clix.h + xmake_file=clipper/x-clix extra_headers=va-clipper.h extra_parts="crtbegin.o crtend.o" - xmake_file=clipper/x-clix install_headers_dir=install-headers-cpio ;; dsp16xx-*) @@ -670,182 +2565,196 @@ for machine in $canon_build $canon_host $canon_target; do # fx80-alliant-*) # Alliant FX/80 # ;; h8300-*-*) - cpu_type=h8300 + float_format=i32 + ;; + hppa*-*-openbsd*) + target_cpu_default="MASK_SNAKE" + tmake_file=pa/t-openbsd + ;; + hppa1.1-*-pro*) + tm_file="pa/pa-pro.h ${tm_file} pa/pa-pro-end.h libgloss.h" + xm_file=pa/xm-papro.h + tmake_file=pa/t-pro ;; hppa1.1-*-osf*) - cpu_type=pa - tm_file=pa/pa1-osf.h + target_cpu_default=1 + 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" + xm_file=pa/xm-papro.h + tmake_file=pa/t-pro + ;; hppa1.0-*-osf*) - cpu_type=pa - tm_file=pa/pa-osf.h + tm_file="${tm_file} pa/pa-osf.h" use_collect2=yes fixincludes=Makefile.in ;; hppa1.1-*-bsd*) - cpu_type=pa - tm_file=pa/pa1.h + target_cpu_default=1 use_collect2=yes fixincludes=Makefile.in ;; hppa1.0-*-bsd*) - cpu_type=pa use_collect2=yes fixincludes=Makefile.in ;; hppa1.0-*-hpux7*) - cpu_type=pa + tm_file="pa/pa-oldas.h ${tm_file} pa/pa-hpux7.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa-gux7.h - else - tm_file=pa/pa-hpux7.h + tm_file="${tm_file} pa/gas.h" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa1.0-*-hpux8.0[0-2]*) - cpu_type=pa + tm_file="${tm_file} pa/pa-hpux.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa-ghpux.h + tm_file="${tm_file} pa/pa-gas.h" else - tm_file=pa/pa-oldas.h + tm_file="pa/pa-oldas.h ${tm_file}" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa1.1-*-hpux8.0[0-2]*) - cpu_type=pa + target_cpu_default=1 + tm_file="${tm_file} pa/pa-hpux.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa1-ghpux.h + tm_file="${tm_file} pa/pa-gas.h" else - tm_file=pa/pa1-oldas.h + tm_file="pa/pa-oldas.h ${tm_file}" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.1-*-hpux8*) + target_cpu_default=1 + tm_file="${tm_file} pa/pa-hpux.h" + xm_file=pa/xm-pahpux.h + xmake_file=pa/x-pa-hpux + if [ x$gas = xyes ] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.0-*-hpux8*) + tm_file="${tm_file} pa/pa-hpux.h" + xm_file=pa/xm-pahpux.h + xmake_file=pa/x-pa-hpux + if [ x$gas = xyes ] + then + tm_file="${tm_file} pa/pa-gas.h" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; - hppa1.1-*-hpux9* | \ hppa1.1-*-hpux10*) - cpu_type=pa + target_cpu_default=1 + 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 ] then - tm_file=pa/pa1-ghpux9.h - else - tm_file=pa/pa1-hpux9.h + tm_file="${tm_file} pa/pa-gas.h" + fi + if [ x$enable_threads = x ]; then + enable_threads=$have_pthread_h + fi + if [ x$enable_threads = xyes ]; then + thread_file='dce' + tmake_file="${tmake_file} pa/t-dce-thr" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; - hppa1.0-*-hpux9* | \ hppa1.0-*-hpux10*) - cpu_type=pa + 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 ] then - tm_file=pa/pa-ghpux9.h - else - tm_file=pa/pa-hpux9.h + tm_file="${tm_file} pa/pa-gas.h" + fi + if [ x$enable_threads = x ]; then + enable_threads=$have_pthread_h + fi + if [ x$enable_threads = xyes ]; then + thread_file='dce' + tmake_file="${tmake_file} pa/t-dce-thr" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa1.1-*-hpux*) - cpu_type=pa + target_cpu_default=1 + tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux9.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa1-ghpux.h - else - tm_file=pa/pa1-hpux.h + tm_file="${tm_file} pa/pa-gas.h" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa1.0-*-hpux*) - cpu_type=pa + tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux9.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa-ghpux.h - else - tm_file=pa/pa-hpux.h + tm_file="${tm_file} pa/pa-gas.h" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa1.1-*-hiux*) - cpu_type=pa + target_cpu_default=1 + tm_file="${tm_file} pa/pa-hpux.h pa/pa-hiux.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa1-ghiux.h - else - tm_file=pa/pa1-hiux.h + tm_file="${tm_file} pa/pa-gas.h" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa1.0-*-hiux*) - cpu_type=pa + tm_file="${tm_file} pa/pa-hpux.h pa/pa-hiux.h" xm_file=pa/xm-pahpux.h xmake_file=pa/x-pa-hpux - tmake_file=pa/t-pa if [ x$gas = xyes ] then - tm_file=pa/pa-ghiux.h - else - tm_file=pa/pa-hiux.h + tm_file="${tm_file} pa/pa-gas.h" fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes ;; hppa*-*-lites*) - cpu_type=pa - tm_file=pa/pa1.h + target_cpu_default=1 use_collect2=yes fixincludes=Makefile.in ;; i370-*-mvs*) - cpu_type=i370 - tm_file=i370/mvs.h - xm_file=i370/xm-mvs.h - out_file=i370/mvs370.c ;; - i[3456]86-ibm-aix*) # IBM PS/2 running AIX - cpu_type=i386 + i[34567]86-ibm-aix*) # IBM PS/2 running AIX if [ x$gas = xyes ] then tm_file=i386/aix386.h @@ -855,28 +2764,34 @@ for machine in $canon_build $canon_host $canon_target; do tm_file=i386/aix386ng.h use_collect2=yes fi - xm_file=i386/xm-aix.h + xm_file="xm-alloca.h i386/xm-aix.h ${xm_file}" + xm_defines=USG xmake_file=i386/x-aix - broken_install=yes ;; - i486-ncr-sysv4*) # NCR 3000 - i486 running system V.4 - cpu_type=i386 - xm_file=i386/xm-sysv4.h + 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 - tm_file=i386/sysv4.h + if [ x$stabs = xyes -a x$gas = xyes ] + then + tm_file=i386/sysv4gdb.h + else + tm_file=i386/sysv4.h + fi extra_parts="crtbegin.o crtend.o" tmake_file=i386/t-crtpic ;; - i[3456]86-next-*) - cpu_type=i386 + i[34567]86-next-*) tm_file=i386/next.h - out_file=i386/next.c 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 + thread_file='mach' + fi ;; - i[3456]86-sequent-bsd*) # 80386 from Sequent - cpu_type=i386 + i[34567]86-sequent-bsd*) # 80386 from Sequent use_collect2=yes if [ x$gas = xyes ] then @@ -885,150 +2800,183 @@ for machine in $canon_build $canon_host $canon_target; do tm_file=i386/sequent.h fi ;; - i[3456]86-sequent-ptx1*) - cpu_type=i386 - xm_file=i386/xm-sysv3.h + i[34567]86-sequent-ptx1*) + 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 - broken_install=yes ;; - i[3456]86-sequent-ptx2* | i[3456]86-sequent-sysv*) - cpu_type=i386 - xm_file=i386/xm-sysv3.h + i[34567]86-sequent-ptx2* | i[34567]86-sequent-sysv3*) + 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 - broken_install=yes + ;; + i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*) + 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 - xm_file=i386/xm-sun.h + xm_defines=USG tm_file=i386/sun.h use_collect2=yes ;; - i[3456]86-*-aout*) - cpu_type=i386 + i[34567]86-wrs-vxworks*) + tm_file=i386/vxi386.h + tmake_file=i386/t-i386bare + ;; + i[34567]86-*-aout*) tm_file=i386/i386-aout.h tmake_file=i386/t-i386bare ;; - i[3456]86-*-bsdi* | i[3456]86-*-bsd386*) - cpu_type=i386 + i[34567]86-*-bsdi* | i[34567]86-*-bsd386*) tm_file=i386/bsd386.h - xm_file=i386/xm-bsd386.h # tmake_file=t-libc-ok ;; - i[3456]86-*-bsd*) - cpu_type=i386 + i[34567]86-*-bsd*) tm_file=i386/386bsd.h - xm_file=i386/xm-bsd386.h # tmake_file=t-libc-ok # Next line turned off because both 386BSD and BSD/386 use GNU ld. # use_collect2=yes ;; - i[3456]86-*-freebsd*) - cpu_type=i386 + 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 + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + tmake_file=i386/t-freebsd + gas=yes + gnu_ld=yes + stabs=yes + ;; + i[34567]86-*-freebsd*) tm_file=i386/freebsd.h - xm_file=i386/xm-freebsd.h - # On FreeBSD, the headers are already ok. - fixincludes=Makefile.in - xmake_file=i386/x-freebsd + # On FreeBSD, the headers are already ok, except for math.h. + fixincludes=fixinc.wrap + tmake_file=i386/t-freebsd ;; - i[3456]86-*-netbsd*) - cpu_type=i386 + i[34567]86-*-netbsd*) tm_file=i386/netbsd.h - xm_file=i386/xm-netbsd.h - # On NetBSD, the headers are already okay. - fixincludes=Makefile.in - tmake_file=t-libc-ok - xmake_file=x-netbsd - ;; - i[3456]86-*-coff*) - cpu_type=i386 + 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 + ;; + 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 ;; - i[3456]86-*-isc*) # 80386 running ISC system - cpu_type=i386 - xm_file=i386/xm-isc.h + i[34567]86-*-isc*) # 80386 running ISC system + xm_file="${xm_file} i386/xm-isc.h" + xm_defines="USG SVR3" case $machine in - i[3456]86-*-isc[34]*) + i[34567]86-*-isc[34]*) xmake_file=i386/x-isc3 ;; *) xmake_file=i386/x-isc ;; esac - echo $xmake_file if [ x$gas = xyes -a x$stabs = xyes ] then tm_file=i386/iscdbx.h tmake_file=i386/t-svr3dbx - extra_parts="crtbegin.o crtend.o svr3.ifile svr3z.ifile" + extra_parts="svr3.ifile svr3z.ifile" else tm_file=i386/isccoff.h tmake_file=i386/t-crtstuff extra_parts="crtbegin.o crtend.o" fi install_headers_dir=install-headers-cpio - broken_install=yes ;; - i[3456]86-*-linux*oldld*) # Intel 80386's running GNU/Linux - cpu_type=i386 # with a.out format using pre BFD linkers - xm_file=i386/xm-linux.h - xmake_file=x-linux + 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 # The headers are ok already. - broken_install=yes + fixincludes=Makefile.in #On Linux, the headers are ok already. gnu_ld=yes + float_format=i386 ;; - i[3456]86-*-linux*aout*) # Intel 80386's running GNU/Linux - cpu_type=i386 # with a.out format - xm_file=i386/xm-linux.h - xmake_file=x-linux + 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 # The headers are ok already. - broken_install=yes - gnu_ld=yes - ;; - i[3456]86-*-linux*gnulibc1) # Intel 80386's running GNU/Linux - cpu_type=i386 # with ELF format, using GNU libc v1. - xm_file=i386/xm-linux.h - xmake_file=x-linux - tmake_file=t-linux-gnulibc1 - tm_file=i386/linux.h - fixincludes=Makefile.in # The headers are ok already. - broken_install=yes + 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" - ;; - i[3456]86-*-linux*) # Intel 80386's running GNU/Linux - cpu_type=i386 # with ELF format - xm_file=i386/xm-linux.h + fixincludes=Makefile.in #On Linux, the headers are ok already. + gnu_ld=yes + float_format=i386 + if [ 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 - tmake_file=t-linux tm_file=i386/linux.h - fixincludes=Makefile.in # The headers are ok already. - broken_install=yes - gnu_ld=yes - # GNU libc version 2 does not supply these; - # we want them from GCC. + 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 + thread_file='posix' + fi + ;; + i[34567]86-*-gnu*) + 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 + ;; + i[34567]86-pc-msdosdjgpp*) + xm_file=i386/xm-go32.h + tm_file=i386/go32.h + tmake_file=i386/t-go32 + gnu_ld=yes + gas=yes ;; - i[3456]86-*-gnu*) - cpu_type=i386 # GNU supports this CPU; rest done below. + 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[3456]86-go32-msdos | i[3456]86-*-go32) - cpu_type=i386 - tm_file=i386/go32.h - ;; - i[3456]86-*-lynxos*) - cpu_type=i386 + i[34567]86-*-lynxos*) if [ x$gas = xyes ] then tm_file=i386/lynx.h @@ -1039,14 +2987,12 @@ for machine in $canon_build $canon_host $canon_target; do tmake_file=i386/t-i386bare xmake_file=x-lynx ;; - i[3456]86-*-mach*) - cpu_type=i386 + i[34567]86-*-mach*) tm_file=i386/mach.h # tmake_file=t-libc-ok use_collect2=yes ;; - i[3456]86-*-osfrose*) # 386 using OSF/rose - cpu_type=i386 + i[34567]86-*-osfrose*) # 386 using OSF/rose if [ x$elf = xyes ] then tm_file=i386/osfelf.h @@ -1055,16 +3001,48 @@ for machine in $canon_build $canon_host $canon_target; do tm_file=i386/osfrose.h use_collect2=yes fi - xm_file=i386/xm-osf.h + xm_file="i386/xm-osf.h ${xm_file}" xmake_file=i386/x-osfrose + tmake_file=i386/t-osf extra_objs=halfpic.o ;; - i[3456]86-*-sco3.2v4*) # 80386 running SCO 3.2v4 system + i[34567]86-go32-rtems*) cpu_type=i386 - xm_file=i386/xm-sco.h + xm_file=i386/xm-go32.h + tm_file=i386/go32-rtems.h + tmake_file="i386/t-go32 t-rtems" + ;; + i[34567]86-*-rtemself*) + cpu_type=i386 + tm_file=i386/rtemself.h + tmake_file="i386/t-i386bare t-rtems" + ;; + i[34567]86-*-rtems*) + 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 + 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 ] + then + tm_file="i386/sco5gas.h ${tm_file}" + tmake_file=i386/t-sco5gas + else + tmake_file=i386/t-sco5 + fi + extra_parts="crti.o crtbegin.o crtend.o crtbeginS.o crtendS.o" + ;; + i[34567]86-*-sco3.2v4*) # 80386 running SCO 3.2v4 system + 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 - broken_install=yes install_headers_dir=install-headers-cpio if [ x$stabs = xyes ] then @@ -1076,12 +3054,11 @@ for machine in $canon_build $canon_host $canon_target; do tmake_file=i386/t-crtstuff extra_parts="crtbegin.o crtend.o" fi + truncate_target=yes ;; - i[3456]86-*-sco*) # 80386 running SCO system - cpu_type=i386 + i[34567]86-*-sco*) # 80386 running SCO system xm_file=i386/xm-sco.h xmake_file=i386/x-sco - broken_install=yes install_headers_dir=install-headers-cpio if [ x$stabs = xyes ] then @@ -1095,32 +3072,70 @@ for machine in $canon_build $canon_host $canon_target; do fi truncate_target=yes ;; - i[3456]86-*-solaris2* | i[3456]86-*-sunos5*) - cpu_type=i386 - xm_file=i386/xm-sysv4.h - tm_file=i386/sol2.h + 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 ] + then + tm_file=i386/sol2dbg.h + else + tm_file=i386/sol2.h + fi tmake_file=i386/t-sol2 - extra_parts="crt1.o crti.o crtn.o crtbegin.o crtend.o" + extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o" xmake_file=x-svr4 - fixincludes=fixinc.svr4 - broken_install=yes + case $machine in + *-*-solaris2.[0-4]) + fixincludes=fixinc.svr4;; + *) + fixincludes=fixinc.wrap;; + esac + if [ x$enable_threads = xyes ]; then + thread_file='solaris' + fi ;; - i[3456]86-*-sysv4*) # Intel 80386's running system V.4 - cpu_type=i386 - xm_file=i386/xm-sysv4.h + 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 ] + 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 + ;; + 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 ] then - tm_file=i386/sysv4gdb.h - else - tm_file=i386/sysv4.h + tm_file="${tm_file} dbx.h" fi tmake_file=i386/t-crtpic xmake_file=x-svr4 extra_parts="crtbegin.o crtend.o" ;; - i[3456]86-*-sysv*) # Intel 80386's running system V + i[34567]86-*-osf1*) # Intel 80386's running OSF/1 1.3+ cpu_type=i386 - xm_file=i386/xm-sysv3.h + 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 ] + then + tm_file=i386/osf1elfgdb.h + else + tm_file=i386/osf1elf.h + fi + tmake_file=i386/t-osf1elf + 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 + xm_defines="USG SVR3" xmake_file=i386/x-sysv3 if [ x$gas = xyes ] then @@ -1141,106 +3156,156 @@ for machine in $canon_build $canon_host $canon_target; do fi ;; i386-*-vsta) # Intel 80386's running VSTa kernel - xm_file=i386/xm-vsta.h + xm_file="${xm_file} i386/xm-vsta.h" tm_file=i386/vsta.h tmake_file=i386/t-vsta xmake_file=i386/x-vsta ;; - i[3456]86-*-winnt3*) - cpu_type=i386 + 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 + extra_objs=winnt.o + fixincludes=Makefile.in + if [ x$enable_threads = xyes ]; then + thread_file='win32' + fi + exeext=.exe + ;; + 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" + extra_objs=winnt.o + xmake_file=i386/x-cygwin32 + fixincludes=Makefile.in + if [ x$enable_threads = xyes ]; then + thread_file='win32' + fi + exeext=.exe + case $machine in + *mingw32msv*) + ;; + *mingw32crt* | *mingw32*) + tm_file="${tm_file} i386/crtdll.h" + ;; + esac + ;; + i[34567]86-*-winnt3*) tm_file=i386/win-nt.h out_file=i386/i386.c - xm_file=i386/xm-winnt.h + xm_file="xm-winnt.h ${xm_file}" xmake_file=winnt/x-winnt tmake_file=i386/t-winnt - extra_objs="winnt.o oldnames.o" + extra_host_objs="winnt.o oldnames.o" extra_gcc_objs="spawnv.o oldnames.o" fixincludes=fixinc.winnt if [ x$gnu_ld != xyes ] then extra_programs=ld.exe fi + if [ x$enable_threads = xyes ]; then + thread_file='win32' + fi ;; + i[34567]86-dg-dgux*) + 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 - xm_file=i860/xm-fx2800.h + tm_file="${tm_file} svr4.h i860/sysv4.h i860/fx2800.h" + xm_file="${xm_file}" xmake_file=i860/x-fx2800 - tm_file=i860/fx2800.h tmake_file=i860/t-fx2800 extra_parts="crtbegin.o crtend.o" ;; i860-*-bsd*) + tm_file="${tm_file} i860/bsd.h" if [ x$gas = xyes ] then - tm_file=i860/bsd-gas.h - else - tm_file=i860/bsd.h + tm_file="${tm_file} i860/bsd-gas.h" fi use_collect2=yes ;; i860-*-mach*) - xm_file=i860/xm-i860.h - tm_file=i860/mach.h + tm_file="${tm_file} i860/mach.h" tmake_file=t-libc-ok ;; i860-*-osf*) # Intel Paragon XP/S, OSF/1AD - xm_file=i860/xm-paragon.h - tm_file=i860/paragon.h + tm_file="${tm_file} svr3.h i860/paragon.h" + xm_defines="USG SVR3" tmake_file=t-osf - broken_install=yes ;; i860-*-sysv3*) - xm_file=i860/xm-sysv3.h + tm_file="${tm_file} svr3.h i860/sysv3.h" + xm_defines="USG SVR3" xmake_file=i860/x-sysv3 - tm_file=i860/sysv3.h extra_parts="crtbegin.o crtend.o" ;; i860-*-sysv4*) - xm_file=i860/xm-sysv4.h + tm_file="${tm_file} svr4.h i860/sysv4.h" + xm_defines="USG SVR3" xmake_file=i860/x-sysv4 - tm_file=i860/sysv4.h tmake_file=t-svr4 extra_parts="crtbegin.o crtend.o" ;; i960-wrs-vxworks5 | i960-wrs-vxworks5.0*) + tm_file="${tm_file} i960/vx960.h" tmake_file=i960/t-vxworks960 - tm_file=i960/vx960.h use_collect2=yes + thread_file='vxworks' ;; - i960-wrs-vxworks5*) + i960-wrs-vxworks5* | i960-wrs-vxworks) + tm_file="${tm_file} dbxcoff.h i960/i960-coff.h i960/vx960-coff.h" tmake_file=i960/t-vxworks960 - tm_file=i960/vx960-coff.h use_collect2=yes + thread_file='vxworks' ;; i960-wrs-vxworks*) + tm_file="${tm_file} i960/vx960.h" tmake_file=i960/t-vxworks960 - tm_file=i960/vx960.h use_collect2=yes + thread_file='vxworks' ;; i960-*-coff*) + tm_file="${tm_file} dbxcoff.h i960/i960-coff.h libgloss.h" tmake_file=i960/t-960bare - tm_file=i960/i960-coff.h + use_collect2=yes + ;; + i960-*-rtems) + tmake_file="i960/t-960bare t-rtems" + tm_file="${tm_file} dbxcoff.h i960/rtems.h" use_collect2=yes ;; i960-*-*) # Default i960 environment. use_collect2=yes ;; + m32r-*-elf*) + extra_parts="crtinit.o crtfini.o" + ;; m68000-convergent-sysv*) - cpu_type=m68k - xm_file=m68k/xm-3b1.h tm_file=m68k/ctix.h + xm_file="m68k/xm-3b1.h ${xm_file}" + xm_defines=USG use_collect2=yes extra_headers=math-68881.h ;; m68000-hp-bsd*) # HP 9000/200 running BSD - cpu_type=m68k tm_file=m68k/hp2bsd.h xmake_file=m68k/x-hp2bsd use_collect2=yes extra_headers=math-68881.h ;; m68000-hp-hpux*) # HP 9000 series 300 - cpu_type=m68k - xm_file=m68k/xm-hp320.h + xm_file="xm_alloca.h ${xm_file}" + xm_defines="USG NO_SYS_SIGLIST" if [ x$gas = xyes ] then xmake_file=m68k/x-hp320g @@ -1249,26 +3314,23 @@ for machine in $canon_build $canon_host $canon_target; do xmake_file=m68k/x-hp320 tm_file=m68k/hp310.h fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes extra_headers=math-68881.h ;; m68000-sun-sunos3*) - cpu_type=m68k tm_file=m68k/sun2.h use_collect2=yes extra_headers=math-68881.h ;; m68000-sun-sunos4*) - cpu_type=m68k tm_file=m68k/sun2o4.h use_collect2=yes extra_headers=math-68881.h ;; m68000-att-sysv*) - cpu_type=m68k - xm_file=m68k/xm-3b1.h + xm_file="m68k/xm-3b1.h ${xm_file}" + xm_defines=USG if [ x$gas = xyes ] then tm_file=m68k/3b1g.h @@ -1278,17 +3340,40 @@ for machine in $canon_build $canon_host $canon_target; do use_collect2=yes extra_headers=math-68881.h ;; + m68k-apple-aux*) # Apple Macintosh running A/UX + xm_defines="USG AUX" + tmake_file=m68k/t-aux + install_headers_dir=install-headers-cpio + extra_headers=math-68881.h + extra_parts="crt1.o mcrt1.o maccrt1.o crt2.o crtn.o" + tm_file= + if [ "$gnu_ld" = yes ] + then + tm_file="${tm_file} m68k/auxgld.h" + else + tm_file="${tm_file} m68k/auxld.h" + fi + if [ "$gas" = yes ] + then + tm_file="${tm_file} m68k/auxgas.h" + else + tm_file="${tm_file} m68k/auxas.h" + fi + tm_file="${tm_file} m68k/a-ux.h" + float_format=m68k + ;; m68k-apollo-*) - xmake_file=m68k/x-apollo68 tm_file=m68k/apollo68.h + xmake_file=m68k/x-apollo68 use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-altos-sysv*) # Altos 3068 if [ x$gas = xyes ] then - xm_file=m68k/xm-altos3068.h tm_file=m68k/altos3068.h + xm_defines=USG else echo "The Altos is supported only with the GNU assembler" 1>&2 exit 1 @@ -1307,95 +3392,122 @@ for machine in $canon_build $canon_host $canon_target; do else tm_file=m68k/dpx2.h fi - xm_file=m68k/xm-m68kv.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG xmake_file=m68k/x-dpx2 use_collect2=yes extra_headers=math-68881.h ;; m68k-atari-sysv4*) # Atari variant of V.4. tm_file=m68k/atari.h - xm_file=m68k/xm-atari.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines="USG FULL_PROTOTYPES" tmake_file=t-svr4 extra_parts="crtbegin.o crtend.o" extra_headers=math-68881.h + float_format=m68k ;; m68k-motorola-sysv*) - xm_file=m68k/xm-mot3300.h - xmake_file=m68k/x-mot3300 + 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 ] then - tm_file=m68k/mot3300g.h + xmake_file=m68k/x-mot3300-gas + if [ x$gnu_ld = xyes ] + then + tmake_file=m68k/t-mot3300-gald + else + tmake_file=m68k/t-mot3300-gas + use_collect2=yes + fi else - tm_file=m68k/mot3300.h - gdb_needs_out_file_path=yes + xmake_file=m68k/x-mot3300 + if [ x$gnu_ld = xyes ] + then + tmake_file=m68k/t-mot3300-gld + else + tmake_file=m68k/t-mot3300 + use_collect2=yes + fi fi - use_collect2=yes + gdb_needs_out_file_path=yes + extra_parts="crt0.o mcrt0.o" extra_headers=math-68881.h + float_format=m68k ;; m68k-ncr-sysv*) # NCR Tower 32 SVR3 tm_file=m68k/tower-as.h - xm_file=m68k/xm-tower.h + xm_defines="USG SVR3" xmake_file=m68k/x-tower extra_parts="crtbegin.o crtend.o" extra_headers=math-68881.h ;; m68k-plexus-sysv*) tm_file=m68k/plexus.h - xm_file=m68k/xm-plexus.h + xm_file="xm-alloca.h m68k/xm-plexus.h ${xm_file}" + xm_defines=USG use_collect2=yes extra_headers=math-68881.h ;; m68k-tti-*) tm_file=m68k/pbb.h - xm_file=m68k/xm-m68kv.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG extra_headers=math-68881.h ;; m68k-crds-unos*) - xm_file=m68k/xm-crds.h + xm_file="xm-alloca.h m68k/xm-crds.h ${xm_file}" + xm_defines="USG unos" xmake_file=m68k/x-crds tm_file=m68k/crds.h - broken_install=yes use_collect2=yes extra_headers=math-68881.h ;; m68k-cbm-sysv4*) # Commodore variant of V.4. tm_file=m68k/amix.h - xm_file=m68k/xm-amix.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines="USG FULL_PROTOTYPES" xmake_file=m68k/x-amix tmake_file=t-svr4 extra_parts="crtbegin.o crtend.o" extra_headers=math-68881.h + float_format=m68k ;; m68k-ccur-rtu) tm_file=m68k/ccur-GAS.h xmake_file=m68k/x-ccur extra_headers=math-68881.h use_collect2=yes - broken_install=yes + float_format=m68k ;; 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 ;; m68k-hp-bsd*) # HP 9000/3xx running Berkeley Unix tm_file=m68k/hp3bsd.h use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-isi-bsd*) - if [ x$nfp = xyes ] + if [ x$with_fp = xno ] then tm_file=m68k/isi-nfp.h else tm_file=m68k/isi.h + float_format=m68k fi use_collect2=yes extra_headers=math-68881.h ;; m68k-hp-hpux7*) # HP 9000 series 300 running HPUX version 7. - xm_file=m68k/xm-hp320.h + xm_file="xm_alloca.h ${xm_file}" + xm_defines="USG NO_SYS_SIGLIST" if [ x$gas = xyes ] then xmake_file=m68k/x-hp320g @@ -1404,13 +3516,14 @@ for machine in $canon_build $canon_host $canon_target; do xmake_file=m68k/x-hp320 tm_file=m68k/hpux7.h fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-hp-hpux*) # HP 9000 series 300 - xm_file=m68k/xm-hp320.h + xm_file="xm_alloca.h ${xm_file}" + xm_defines="USG NO_SYS_SIGLIST" if [ x$gas = xyes ] then xmake_file=m68k/x-hp320g @@ -1419,15 +3532,16 @@ for machine in $canon_build $canon_host $canon_target; do xmake_file=m68k/x-hp320 tm_file=m68k/hp320.h fi - broken_install=yes install_headers_dir=install-headers-cpio use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-sun-mach*) tm_file=m68k/sun3mach.h use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-sony-newsos3*) if [ x$gas = xyes ] @@ -1438,6 +3552,7 @@ for machine in $canon_build $canon_host $canon_target; do fi use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-sony-bsd* | m68k-sony-newsos*) if [ x$gas = xyes ] @@ -1448,40 +3563,48 @@ for machine in $canon_build $canon_host $canon_target; do fi use_collect2=yes extra_headers=math-68881.h + float_format=m68k ;; m68k-next-nextstep2*) tm_file=m68k/next21.h - out_file=m68k/next.c - xm_file=m68k/xm-next.h + xm_file="m68k/xm-next.h ${xm_file}" tmake_file=m68k/t-next xmake_file=m68k/x-next + extra_objs=nextstep.o extra_headers=math-68881.h use_collect2=yes + float_format=m68k ;; m68k-next-nextstep3*) tm_file=m68k/next.h - out_file=m68k/next.c - xm_file=m68k/xm-next.h + xm_file="m68k/xm-next.h ${xm_file}" tmake_file=m68k/t-next xmake_file=m68k/x-next + extra_objs=nextstep.o extra_headers=math-68881.h + float_format=m68k + if [ x$enable_threads = xyes ]; then + thread_file='mach' + fi ;; m68k-sun-sunos3*) - if [ x$nfp = xyes ] + if [ x$with_fp = xno ] then tm_file=m68k/sun3n3.h else tm_file=m68k/sun3o3.h + float_format=m68k fi use_collect2=yes extra_headers=math-68881.h ;; m68k-sun-sunos*) # For SunOS 4 (the default). - if [ x$nfp = xyes ] + if [ x$with_fp = xno ] then tm_file=m68k/sun3n.h else tm_file=m68k/sun3.h + float_format=m68k fi use_collect2=yes extra_headers=math-68881.h @@ -1490,16 +3613,20 @@ for machine in $canon_build $canon_host $canon_target; do tm_file=m68k/vxm68k.h tmake_file=m68k/t-vxworks68 extra_headers=math-68881.h + thread_file='vxworks' + float_format=m68k ;; m68k-*-aout*) tmake_file=m68k/t-m68kbare - tm_file=m68k/m68k-aout.h + tm_file="m68k/m68k-aout.h libgloss.h" extra_headers=math-68881.h + float_format=m68k ;; m68k-*-coff*) tmake_file=m68k/t-m68kbare - tm_file=m68k/m68k-coff.h + tm_file="m68k/m68k-coff.h dbx.h libgloss.h" extra_headers=math-68881.h + float_format=m68k ;; m68k-*-lynxos*) if [ x$gas = xyes ] @@ -1512,85 +3639,111 @@ for machine in $canon_build $canon_host $canon_target; do xmake_file=x-lynx tmake_file=m68k/t-lynx extra_headers=math-68881.h + float_format=m68k ;; - m68k-*-netbsd*) - cpu_type=m68k + m68k*-*-netbsd*) tm_file=m68k/netbsd.h - xm_file=m68k/xm-netbsd.h - # On NetBSD, the headers are already okay. - fixincludes=Makefile.in - tmake_file=t-libc-ok - xmake_file=x-netbsd + 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 + ;; + m68k*-*-openbsd*) + float_format=m68k + # we need collect2 until our bug is fixed... + use_collect2=yes ;; m68k-*-sysv3*) # Motorola m68k's running system V.3 - xm_file=m68k/xm-m68kv.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG xmake_file=m68k/x-m68kv extra_parts="crtbegin.o crtend.o" extra_headers=math-68881.h + float_format=m68k ;; m68k-*-sysv4*) # Motorola m68k's running system V.4 tm_file=m68k/m68kv4.h - xm_file=m68k/xm-m68kv.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG tmake_file=t-svr4 extra_parts="crtbegin.o crtend.o" extra_headers=math-68881.h + float_format=m68k ;; - m68k-*-linux*aout*) # Motorola m68k's running GNU/Linux - xm_file=m68k/xm-linux.h # with a.out format + m68k-*-linux-gnuaout*) # Motorola m68k's running GNU/Linux + # with a.out format xmake_file=x-linux tm_file=m68k/linux-aout.h - tmake_file=m68k/t-linux + 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 ;; - m68k-*-linux*libc1) # Motorola m68k's running GNU/Linux - xm_file=m68k/xm-linux.h # with ELF format, using GNU libc v1. + m68k-*-linux-gnulibc1) # Motorola m68k's running GNU/Linux + # with ELF format using the + # GNU/Linux C library 5 xmake_file=x-linux tm_file=m68k/linux.h - tmake_file=m68k/t-linux-gnulibc1 + 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 - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" ;; - m68k-*-linux*) # Motorola m68k's running GNU/Linux - xm_file=m68k/xm-linux.h # with ELF format + m68k-*-linux-gnu*) # Motorola m68k's running GNU/Linux + # with ELF format using glibc 2 + # aka the GNU/Linux C library 6. xmake_file=x-linux tm_file=m68k/linux.h - tmake_file=m68k/t-linux + 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 - # GNU libc version 2 does not supply these; - # we want them from GCC. - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + if [ x$enable_threads = xyes ]; then + thread_file='posix' + fi + ;; + m68k-*-psos*) + tmake_file=m68k/t-m68kbare + tm_file=m68k/m68k-psos.h + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-*-rtems*) + tmake_file="m68k/t-m68kbare t-rtems" + tm_file=m68k/rtems.h + extra_headers=math-68881.h + float_format=m68k ;; + m88k-dg-dgux*) case $machine in m88k-dg-dguxbcs*) tm_file=m88k/dguxbcs.h - xmake_file=m88k/x-dguxbcs + tmake_file=m88k/t-dguxbcs ;; *) tm_file=m88k/dgux.h - xmake_file=m88k/x-dgux + tmake_file=m88k/t-dgux ;; esac extra_parts="crtbegin.o bcscrtbegin.o crtend.o m88kdgux.ld" - broken_install=yes + xmake_file=m88k/x-dgux if [ x$gas = xyes ] then tmake_file=m88k/t-dgux-gas - else - tmake_file=m88k/t-dgux 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="m88k/xm-sysv3.h ${xm_file}" xmake_file=m88k/x-dolph if [ x$gas = xyes ] then @@ -1600,7 +3753,7 @@ for machine in $canon_build $canon_host $canon_target; do m88k-tektronix-sysv3) tm_file=m88k/tekXD88.h extra_parts="crtbegin.o crtend.o" - xm_file=m88k/xm-sysv3.h + xm_file="m88k/xm-sysv3.h ${xm_file}" xmake_file=m88k/x-tekXD88 if [ x$gas = xyes ] then @@ -1608,11 +3761,9 @@ for machine in $canon_build $canon_host $canon_target; do fi ;; m88k-*-aout*) - cpu_type=m88k tm_file=m88k/m88k-aout.h ;; m88k-*-coff*) - cpu_type=m88k tm_file=m88k/m88k-coff.h tmake_file=m88k/t-bug ;; @@ -1626,10 +3777,13 @@ for machine in $canon_build $canon_host $canon_target; do tmake_file=m88k/t-luna fi ;; + m88k-*-openbsd*) + tmake_file="${tmake_file} m88k/t-luna-gas" + ;; m88k-*-sysv3*) tm_file=m88k/sysv3.h extra_parts="crtbegin.o crtend.o" - xm_file=m88k/xm-sysv3.h + xm_file="m88k/xm-sysv3.h ${xm_file}" xmake_file=m88k/x-sysv3 if [ x$gas = xyes ] then @@ -1645,52 +3799,83 @@ for machine in $canon_build $canon_host $canon_target; do mips-sgi-irix6*) # SGI System V.4., IRIX 6 tm_file=mips/iris6.h xm_file=mips/xm-iris6.h - broken_install=yes - fixincludes=Makefile.in + fixincludes=fixinc.irix xmake_file=mips/x-iris6 tmake_file=mips/t-iris6 - # See comment in mips/iris[56].h files. - use_collect2=yes + if [ x$enable_threads = xyes ]; then +: not ported yet thread_file='irix' + fi ;; + mips-wrs-vxworks) + tm_file="mips/elf.h libgloss.h" + tmake_file=mips/t-ecoff + gas=yes + gnu_ld=yes + extra_parts="crtbegin.o crtend.o" +# thread_file='vxworks' + ;; mips-sgi-irix5cross64) # Irix5 host, Irix 6 target, cross64 - tm_file=mips/cross64.h - xm_file=mips/xm-iris5.h - broken_install=yes + 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 ;; - mips-sgi-irix5*) # SGI System V.4., IRIX 5 + mips-sni-sysv4) if [ x$gas = xyes ] then if [ x$stabs = xyes ] then tm_file=mips/iris5gdb.h else - tm_file=mips/iris5gas.h + tm_file="mips/sni-svr4.h mips/sni-gas.h" + fi + else + tm_file=mips/sni-svr4.h + fi + xm_defines=USG + xmake_file=mips/x-sni-svr4 + tmake_file=mips/t-mips-gas + if [ x$gnu_ld != xyes ] + then + use_collect2=yes + fi + ;; + mips-sgi-irix5*) # SGI System V.4., IRIX 5 + if [ x$gas = xyes ] + then + tm_file="mips/iris5.h mips/iris5gas.h" + if [ x$stabs = xyes ] + then + tm_file="${tm_file} dbx.h" fi else tm_file=mips/iris5.h fi - xm_file=mips/xm-iris5.h - broken_install=yes - fixincludes=Makefile.in + 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 ;; 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 - tm_file=mips/iris4gl.h - else - tm_file=mips/iris4loser.h + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-iris4.h - broken_install=yes + xm_defines=USG xmake_file=mips/x-iris if [ x$gas = xyes ] then @@ -1702,15 +3887,16 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi + if [ x$enable_threads = xyes ]; then +: not ported yet 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 - tm_file=mips/iris4-gdb.h - else - tm_file=mips/iris4.h + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-iris4.h - broken_install=yes + xm_defines=USG xmake_file=mips/x-iris if [ x$gas = xyes ] then @@ -1722,15 +3908,16 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi + if [ x$enable_threads = xyes ]; then +: not ported yet thread_file='irix' + fi ;; mips-sgi-*) # Mostly like a MIPS. + tm_file="mips/iris3.h ${tm_file}" if [ x$stabs = xyes ]; then - tm_file=mips/iris3-gdb.h - else - tm_file=mips/iris3.h + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-iris3.h - broken_install=yes + xm_defines=USG xmake_file=mips/x-iris3 if [ x$gas = xyes ] then @@ -1744,17 +3931,16 @@ for machine in $canon_build $canon_host $canon_target; do fi ;; mips-dec-osfrose*) # Decstation running OSF/1 reference port with OSF/rose. - tm_file=mips/osfrose.h + tm_file="mips/osfrose.h ${tm_file}" xmake_file=mips/x-osfrose tmake_file=mips/t-osfrose extra_objs=halfpic.o use_collect2=yes ;; mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL + tm_file=mips/dec-osf1.h if [ x$stabs = xyes ]; then - tm_file=mips/dec-gosf1.h - else - tm_file=mips/dec-osf1.h + tm_file="${tm_file} dbx.h" fi xmake_file=mips/x-dec-osf1 if [ x$gas = xyes ] @@ -1771,8 +3957,6 @@ for machine in $canon_build $canon_host $canon_target; do ;; mips-dec-bsd*) # Decstation running 4.4 BSD tm_file=mips/dec-bsd.h - xmake_file= - tmake_file= fixincludes= if [ x$gas = xyes ] then @@ -1786,19 +3970,27 @@ for machine in $canon_build $canon_host $canon_target; do use_collect2=yes fi ;; - mips-dec-netbsd*) # Decstation running NetBSD + mipsel-*-netbsd* | mips-dec-netbsd*) # Decstation running NetBSD tm_file=mips/netbsd.h - xm_file=mips/xm-netbsd.h - xmake_file=x-netbsd - tmake_file=t-libc-ok - fixincludes=Makefile.in - prefix=$native_prefix + 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*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 - tm_file=mips/news4-gdb.h - else - tm_file=mips/news4.h + tm_file="${tm_file} dbx.h" fi if [ x$gas = xyes ] then @@ -1815,12 +4007,12 @@ for machine in $canon_build $canon_host $canon_target; do mips-sony-sysv*) # Sony NEWS 3800 with NEWSOS5.0. # 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 - tm_file=mips/news5-gdb.h - else - tm_file=mips/news5.h + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-news.h + xm_file="xm-siglist.h ${xm_file}" + xm_defines=USG if [ x$gas = xyes ] then tmake_file=mips/t-mips-gas @@ -1833,12 +4025,12 @@ for machine in $canon_build $canon_host $canon_target; do fi ;; mips-tandem-sysv4*) # Tandem S2 running NonStop UX + tm_file="mips/svr4-5.h mips/svr4-t.h" if [ x$stabs = xyes ]; then - tm_file=mips/svr4-t-gdb.h - else - tm_file=mips/svr4-t.h + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-sysv4.h + xm_file="xm-siglist.h ${xm_file}" + xm_defines=USG xmake_file=mips/x-sysv if [ x$gas = xyes ] then @@ -1852,13 +4044,11 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-ultrix* | mips-dec-mach3) # Decstation. + tm_file="mips/ultrix.h ${tm_file}" if [ x$stabs = xyes ]; then - tm_file=mips/ultrix-gdb.h - else - tm_file=mips/ultrix.h + tm_file="${tm_file} dbx.h" fi xmake_file=mips/x-ultrix if [ x$gas = xyes ] @@ -1874,10 +4064,9 @@ for machine in $canon_build $canon_host $canon_target; do fi ;; mips-*-riscos[56789]bsd*) - if [ x$stabs = xyes ]; then # MIPS BSD 4.3, RISC-OS 5.0 - tm_file=mips/bsd-5-gdb.h - else - tm_file=mips/bsd-5.h + tm_file=mips/bsd-5.h # MIPS BSD 4.3, RISC-OS 5.0 + if [ x$stabs = xyes ]; then + tm_file="${tm_file} dbx.h" fi if [ x$gas = xyes ] then @@ -1890,13 +4079,11 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-bsd* | mips-*-riscosbsd* | mips-*-riscos[1234]bsd*) - if [ x$stabs = xyes ]; then # MIPS BSD 4.3, RISC-OS 4.0 - tm_file=mips/bsd-4-gdb.h - else - tm_file=mips/bsd-4.h + tm_file="mips/bsd-4.h ${tm_file}" # MIPS BSD 4.3, RISC-OS 4.0 + if [ x$stabs = xyes ]; then + tm_file="${tm_file} dbx.h" fi if [ x$gas = xyes ] then @@ -1909,15 +4096,13 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-riscos[56789]sysv4*) - if [ x$stabs = xyes ]; then # MIPS System V.4., RISC-OS 5.0 - tm_file=mips/svr4-5-gdb.h - else - tm_file=mips/svr4-5.h + tm_file=mips/svr4-5.h # MIPS System V.4., RISC-OS 5.0 + if [ x$stabs = xyes ]; then + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-sysv4.h + xm_file="xm-siglist.h ${xm_file}" xmake_file=mips/x-sysv if [ x$gas = xyes ] then @@ -1930,15 +4115,13 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-sysv4* | mips-*-riscos[1234]sysv4* | mips-*-riscossysv4*) - if [ x$stabs = xyes ]; then # MIPS System V.4. RISC-OS 4.0 - tm_file=mips/svr4-4-gdb.h - else - tm_file=mips/svr4-4.h + tm_file="mips/svr4-4.h ${tm_file}" + if [ x$stabs = xyes ]; then + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-sysv.h + xm_defines=USG xmake_file=mips/x-sysv if [ x$gas = xyes ] then @@ -1951,15 +4134,13 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-riscos[56789]sysv*) - if [ x$stabs = xyes ]; then # MIPS System V.3, RISC-OS 5.0 - tm_file=mips/svr3-5-gdb.h - else - tm_file=mips/svr3-5.h + tm_file=mips/svr3-5.h # MIPS System V.3, RISC-OS 5.0 + if [ x$stabs = xyes ]; then + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-sysv.h + xm_defines=USG xmake_file=mips/x-sysv if [ x$gas = xyes ] then @@ -1972,15 +4153,13 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-sysv* | mips-*-riscos*sysv*) - if [ x$stabs = xyes ]; then # MIPS System V.3, RISC-OS 4.0 - tm_file=mips/svr3-4-gdb.h - else - tm_file=mips/svr3-4.h + tm_file="mips/svr3-4.h ${tm_file}" + if [ x$stabs = xyes ]; then + tm_file="${tm_file} dbx.h" fi - xm_file=mips/xm-sysv.h + xm_defines=USG xmake_file=mips/x-sysv if [ x$gas = xyes ] then @@ -1993,13 +4172,11 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; - mips-*-riscos[56789]*) # Default MIPS RISC-OS 5.0. + mips-*-riscos[56789]*) # Default MIPS RISC-OS 5.0. + tm_file=mips/mips-5.h if [ x$stabs = xyes ]; then - tm_file=mips/mips-5-gdb.h - else - tm_file=mips/mips-5.h + tm_file="${tm_file} dbx.h" fi if [ x$gas = xyes ] then @@ -2011,64 +4188,62 @@ for machine in $canon_build $canon_host $canon_target; do then use_collect2=yes fi - broken_install=yes ;; mips-*-gnu*) - cpu_type=mips # GNU supports this CPU; rest done below. ;; mipsel-*-ecoff*) - cpu_type=mips + tm_file=mips/ecoffl.h if [ x$stabs = xyes ]; then - tm_file=mips/ecoffl-gdb.h - else - tm_file=mips/ecoffl.h + 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 - tm_file=mips/ecoff-gdb.h - else - tm_file=mips/ecoff.h + tm_file="${tm_file} dbx.h" fi tmake_file=mips/t-ecoff - broken_install=yes ;; mipsel-*-elf*) - cpu_type=mips - tm_file=mips/elfl.h + tm_file="mips/elfl.h libgloss.h" tmake_file=mips/t-ecoff ;; mips-*-elf*) - cpu_type=mips - tm_file=mips/elf.h + tm_file="mips/elf.h libgloss.h" tmake_file=mips/t-ecoff ;; mips64el-*-elf*) - cpu_type=mips - tm_file=mips/elfl64.h + tm_file="mips/elfl64.h libgloss.h" tmake_file=mips/t-ecoff ;; mips64orionel-*-elf*) - cpu_type=mips - tm_file=mips/elflorion.h + tm_file="mips/elforion.h mips/elfl64.h libgloss.h" tmake_file=mips/t-ecoff ;; mips64-*-elf*) - cpu_type=mips - tm_file=mips/elf64.h + tm_file="mips/elf64.h libgloss.h" tmake_file=mips/t-ecoff ;; mips64orion-*-elf*) - cpu_type=mips - tm_file=mips/elforion.h + tm_file="mips/elforion.h mips/elf64.h libgloss.h" tmake_file=mips/t-ecoff ;; + 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" + tmake_file=mips/t-r3900 + ;; + mipstx39-*-elf*) + tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h" + tmake_file=mips/t-r3900 + ;; mips-*-*) # Default MIPS RISC-OS 4.0. if [ x$stabs = xyes ]; then - tm_file=mips/mips-4-gdb.h - else - tm_file=mips/mips.h + tm_file="${tm_file} dbx.h" fi if [ x$gas = xyes ] then @@ -2081,6 +4256,24 @@ for machine in $canon_build $canon_host $canon_target; do use_collect2=yes fi ;; + mn10200-*-*) + cpu_type=mn10200 + tm_file="mn10200/mn10200.h" + if [ x$stabs = xyes ] + then + tm_file="${tm_file} dbx.h" + fi + use_collect2=no + ;; + mn10300-*-*) + cpu_type=mn10300 + tm_file="mn10300/mn10300.h" + if [ x$stabs = xyes ] + then + tm_file="${tm_file} dbx.h" + fi + use_collect2=no + ;; ns32k-encore-bsd*) tm_file=ns32k/encore.h use_collect2=yes @@ -2091,20 +4284,17 @@ for machine in $canon_build $canon_host $canon_target; do ;; ns32k-tek6100-bsd*) tm_file=ns32k/tek6100.h - broken_install=yes use_collect2=yes ;; ns32k-tek6200-bsd*) tm_file=ns32k/tek6200.h - broken_install=yes use_collect2=yes ;; # This has not been updated to GCC 2. # ns32k-ns-genix*) -# xm_file=ns32k/xm-genix.h +# xm_defines=USG # xmake_file=ns32k/x-genix # tm_file=ns32k/genix.h -# broken_install=yes # use_collect2=yes # ;; ns32k-merlin-*) @@ -2117,16 +4307,24 @@ for machine in $canon_build $canon_host $canon_target; do ;; ns32k-pc532-minix*) tm_file=ns32k/pc532-min.h - xm_file=ns32k/xm-pc532-min.h + xm_file="ns32k/xm-pc532-min.h ${xm-file}" + xm_defines=USG use_collect2=yes ;; - ns32k-pc532-netbsd*) + ns32k-*-netbsd*) tm_file=ns32k/netbsd.h - xm_file=ns32k/xm-netbsd.h - tmake_file=t-libc-ok - # On NetBSD, the headers are already okay. - fixincludes=Makefile.in - xmake_file=x-netbsd + 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 + ;; + pdp11-*-bsd) + tm_file="${tm_file} pdp11/2bsd.h" + ;; + pdp11-*-*) + ;; + ns32k-*-openbsd*) + # Nothing special ;; pyramid-*-*) cpu_type=pyr @@ -2140,149 +4338,333 @@ for machine in $canon_build $canon_host $canon_target; do xmake_file=romp/x-mach use_collect2=yes ;; - powerpc-ibm-aix[456789].*) - cpu_type=rs6000 - tm_file=rs6000/aix41ppc.h - tmake_file=rs6000/t-newas - use_collect2=yes + romp-*-openbsd*) + # Nothing special ;; - powerpc-ibm-aix*) - cpu_type=rs6000 - tm_file=rs6000/powerpc.h - tmake_file=rs6000/t-rs6000 - use_collect2=yes + powerpc-*-openbsd*) + tmake_file="${tmake_file} rs6000/t-rs6000 rs6000/t-openbsd" + xmake_file=none ;; - powerpc-*-sysv4* | powerpc-*-elf*) + powerpc-*-beos*) cpu_type=rs6000 - xm_file=rs6000/xm-sysv4.h + tm_file=rs6000/beos.h + xm_file=rs6000/xm-beos.h + tmake_file=rs6000/t-beos + xmake_file=rs6000/x-beos + ;; + powerpc-*-sysv* | powerpc-*-elf*) tm_file=rs6000/sysv4.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + extra_headers=ppc-asm.h if [ x$gas = xyes ] then - tmake_file=rs6000/t-ppcgas + tmake_file="rs6000/t-ppcos rs6000/t-ppccomm" else - tmake_file=rs6000/t-ppc + tmake_file="rs6000/t-ppc rs6000/t-ppccomm" fi xmake_file=rs6000/x-sysv4 ;; powerpc-*-eabiaix*) - cpu_type=rs6000 tm_file=rs6000/eabiaix.h - tmake_file=rs6000/t-eabiaix + tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm" fixincludes=Makefile.in + extra_headers=ppc-asm.h ;; powerpc-*-eabisim*) - cpu_type=rs6000 tm_file=rs6000/eabisim.h - tmake_file=rs6000/t-eabisim + tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm" fixincludes=Makefile.in + extra_headers=ppc-asm.h ;; powerpc-*-eabi*) - cpu_type=rs6000 tm_file=rs6000/eabi.h if [ x$gas = xyes ] then - tmake_file=rs6000/t-eabigas + 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 ] + 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 ] + 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 + thread_file='posix' + fi + ;; + powerpc-*-linux-gnu*) + tm_file=rs6000/linux.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG ${xm_defines}" + out_file=rs6000/rs6000.c + if [ x$gas = xyes ] + then + tmake_file="rs6000/t-ppcos t-linux rs6000/t-ppccomm" else - tmake_file=rs6000/t-eabi + 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 + thread_file='posix' fi - fixincludes=Makefile.in ;; - powerpcle-*-sysv4* | powerpcle-*-elf*) - cpu_type=rs6000 - xm_file=rs6000/xm-sysv4.h + powerpc-wrs-vxworks*) + cpu_type=rs6000 + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + tm_file=rs6000/vxppc.h + tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm" + extra_headers=ppc-asm.h + thread_file='vxworks' + ;; + powerpcle-*-sysv* | powerpcle-*-elf*) tm_file=rs6000/sysv4le.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" if [ x$gas = xyes ] then - tmake_file=rs6000/t-ppclegas + tmake_file="rs6000/t-ppcos rs6000/t-ppccomm" else - tmake_file=rs6000/t-ppc + tmake_file="rs6000/t-ppc rs6000/t-ppccomm" fi xmake_file=rs6000/x-sysv4 + extra_headers=ppc-asm.h ;; powerpcle-*-eabisim*) - cpu_type=rs6000 tm_file=rs6000/eabilesim.h - tmake_file=rs6000/t-eabisim + tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm" fixincludes=Makefile.in + extra_headers=ppc-asm.h ;; powerpcle-*-eabi*) - cpu_type=rs6000 tm_file=rs6000/eabile.h if [ x$gas = xyes ] then - tmake_file=rs6000/t-eabilegas + tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm" else - tmake_file=rs6000/t-eabi + 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 + 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}" + tmake_file=rs6000/t-winnt + xmake_file=rs6000/x-cygwin32 +# extra_objs=pe.o fixincludes=Makefile.in + if [ x$enable_threads = xyes ]; then + thread_file='win32' + fi + exeext=.exe + extra_headers=ppc-asm.h + ;; + powerpcle-*-solaris2*) + tm_file=rs6000/sol2.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + if [ 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 - tmake_file=rs6000/t-rs6000 xmake_file=rs6000/x-aix31 use_collect2=yes ;; - rs6000-ibm-aix3.2.[456789]*) + rs6000-ibm-aix3.2.[456789]* | powerpc-ibm-aix3.2.[456789]*) tm_file=rs6000/aix3newas.h - tmake_file=rs6000/t-newas + if [ x$host != x$target ] + then + tmake_file=rs6000/t-xnewas + else + tmake_file=rs6000/t-newas + fi use_collect2=yes ;; - rs6000-ibm-aix[456789].*) + rs6000-ibm-aix4.[12]* | powerpc-ibm-aix4.[12]*) tm_file=rs6000/aix41.h - tmake_file=rs6000/t-newas - xmake_file=rs6000/x-aix31 + if [ x$host != x$target ] + then + tmake_file=rs6000/t-xnewas + else + tmake_file=rs6000/t-newas + fi + xmake_file=rs6000/x-aix41 + use_collect2=yes + ;; + rs6000-ibm-aix4.[3456789].* | powerpc-ibm-aix4.[3456789].*) + tm_file=rs6000/aix43.h + if [ x$host != x$target ] + then + tmake_file=rs6000/t-xaix43 + else + tmake_file=rs6000/t-aix43 + fi + xmake_file=rs6000/x-aix43 + use_collect2=yes + ;; + rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*) + tm_file=rs6000/aix43.h + if [ x$host != x$target ] + then + tmake_file=rs6000/t-xaix43 + else + tmake_file=rs6000/t-aix43 + fi + xmake_file=rs6000/x-aix43 use_collect2=yes ;; rs6000-ibm-aix*) use_collect2=yes - tmake_file=rs6000/t-rs6000 ;; rs6000-bull-bosx) - tmake_file=rs6000/t-rs6000 use_collect2=yes ;; rs6000-*-mach*) - xm_file=rs6000/xm-mach.h tm_file=rs6000/mach.h - tmake_file=rs6000/t-rs6000 + xm_file="${xm_file} rs6000/xm-mach.h" xmake_file=rs6000/x-mach use_collect2=yes ;; rs6000-*-lynxos*) - xmake_file=rs6000/x-lynx - xm_file=rs6000/xm-lynx.h tm_file=rs6000/lynx.h + xm_file=rs6000/xm-lynx.h tmake_file=rs6000/t-rs6000 + xmake_file=rs6000/x-lynx use_collect2=yes ;; + sh-*-elf*) + tm_file=sh/elf.h + float_format=sh + ;; + sh-*-rtemself*) + tmake_file="sh/t-sh t-rtems" + tm_file=sh/rtemself.h + float_format=sh + ;; + sh-*-rtems*) + tmake_file="sh/t-sh t-rtems" + tm_file=sh/rtems.h + float_format=sh + ;; sh-*-*) - cpu_type=sh + float_format=sh ;; sparc-tti-*) tm_file=sparc/pbd.h - xm_file=sparc/xm-pbd.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG ;; sparc-wrs-vxworks* | sparclite-wrs-vxworks*) - cpu_type=sparc tm_file=sparc/vxsparc.h tmake_file=sparc/t-vxsparc use_collect2=yes + thread_file='vxworks' ;; sparc-*-aout*) tmake_file=sparc/t-sparcbare - tm_file=sparc/sparc-aout.h + tm_file="sparc/aout.h libgloss.h" ;; sparc-*-netbsd*) tm_file=sparc/netbsd.h - xm_file=sparc/xm-netbsd.h - # On NetBSD, the headers are already okay. - fixincludes=Makefile.in - tmake_file=t-libc-ok - xmake_file=x-netbsd + 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 + ;; + sparc-*-openbsd*) + # we need collect2 until our bug is fixed... + use_collect2=yes ;; sparc-*-bsd*) tm_file=sparc/bsd.h ;; + sparc-*-elf*) + tm_file=sparc/elf.h + tmake_file=sparc/t-elf + extra_parts="crti.o crtn.o crtbegin.o crtend.o" + #float_format=i128 + float_format=i64 + ;; + sparc-*-linux-gnuaout*) # Sparc's running GNU/Linux, a.out + 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 + xm_file="${xm_file} sparc/xm-linux.h" + xmake_file=x-linux + 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 + xm_file="${xm_file} sparc/xm-linux.h" + xmake_file=x-linux + 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 + thread_file='posix' + fi + ;; sparc-*-lynxos*) if [ x$gas = xyes ] then @@ -2294,14 +4676,42 @@ for machine in $canon_build $canon_host $canon_target; do tmake_file=sparc/t-sunos41 xmake_file=x-lynx ;; - sparc-*-solaris2* | sparc-*-sunos5*) - xm_file=sparc/xm-sol2.h - tm_file=sparc/sol2.h + sparc-*-rtems*) + tmake_file="sparc/t-sparcbare t-rtems" + tm_file=sparc/rtems.h + ;; + sparc-*-solaris2*) + if [ x$gnu_ld = xyes ] + then + tm_file=sparc/sol2.h + else + tm_file=sparc/sol2-sld.h + fi + xm_file="xm-siglist.h sparc/xm-sysv4.h sparc/xm-sol2.h" + xm_defines="USG POSIX" tmake_file=sparc/t-sol2 xmake_file=sparc/x-sysv4 - extra_parts="crt1.o crti.o crtn.o gmon.o crtbegin.o crtend.o" - fixincludes=fixinc.svr4 - broken_install=yes + 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;; + *) + fixincludes=fixinc.wrap;; + esac + float_format=i128 + if [ x${enable_threads} = x ]; then + enable_threads=$have_pthread_h + if [ 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 + thread_file='posix' + else + thread_file='solaris' + fi + fi ;; sparc-*-sunos4.0*) tm_file=sparc/sunos4.h @@ -2312,86 +4722,123 @@ for machine in $canon_build $canon_host $canon_target; do tm_file=sparc/sunos4.h tmake_file=sparc/t-sunos41 use_collect2=yes + if [ x$gas = xyes ]; then + tm_file="${tm_file} sparc/sun4gas.h" + fi ;; sparc-*-sunos3*) tm_file=sparc/sun4o3.h use_collect2=yes ;; sparc-*-sysv4*) - xm_file=sparc/xm-sysv4.h tm_file=sparc/sysv4.h + xm_file="xm-siglist.h sparc/xm-sysv4.h" + xm_defines="USG POSIX" tmake_file=t-svr4 xmake_file=sparc/x-sysv4 extra_parts="crtbegin.o crtend.o" ;; + sparc-*-vxsim*) + xm_file="xm-siglist.h sparc/xm-sysv4.h sparc/xm-sol2.h" + xm_defines="USG POSIX" + tm_file=sparc/vxsim.h + tmake_file=sparc/t-vxsparc + xmake_file=sparc/x-sysv4 + ;; + sparclet-*-aout*) + tm_file="sparc/splet.h libgloss.h" + tmake_file=sparc/t-splet + ;; sparclite-*-coff*) - cpu_type=sparc - tm_file=sparc/litecoff.h + tm_file="sparc/litecoff.h libgloss.h" tmake_file=sparc/t-sparclite ;; - sparclite-*-*) - cpu_type=sparc - tm_file=sparc/lite.h + sparclite-*-aout*) + tm_file="sparc/lite.h aoutos.h libgloss.h" tmake_file=sparc/t-sparclite - use_collect2=yes ;; sparc64-*-aout*) - cpu_type=sparc tmake_file=sparc/t-sp64 tm_file=sparc/sp64-aout.h ;; sparc64-*-elf*) - cpu_type=sparc tmake_file=sparc/t-sp64 tm_file=sparc/sp64-elf.h extra_parts="crtbegin.o crtend.o" ;; + sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux + tmake_file=sparc/t-sp64 + 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. + gnu_ld=yes + ;; # This hasn't been upgraded to GCC 2. # tahoe-harris-*) # Harris tahoe, using COFF. # tm_file=tahoe/harris.h # ;; # tahoe-*-bsd*) # tahoe running BSD # ;; + thumb-*-coff* | thumbel-*-coff*) + 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 + fixincludes=Makefile.in # There is nothing to fix + ;; # This hasn't been upgraded to GCC 2. # tron-*-*) # cpu_type=gmicro # use_collect2=yes # ;; + v850-*-*) + cpu_type=v850 + tm_file="v850/v850.h" + xm_file="v850/xm-v850.h" + tmake_file=v850/t-v850 + if [ x$stabs = xyes ] + then + tm_file="${tm_file} dbx.h" + fi + use_collect2=no + ;; vax-*-bsd*) # vaxen running BSD use_collect2=yes + float_format=vax ;; vax-*-sysv*) # vaxen running system V - xm_file=vax/xm-vaxv.h - tm_file=vax/vaxv.h + tm_file="${tm_file} vax/vaxv.h" + xm_defines=USG + float_format=vax ;; vax-*-netbsd*) - tm_file=vax/netbsd.h - xm_file=vax/xm-netbsd.h - tmake_file=t-libc-ok - # On NetBSD, the headers are already okay. - fixincludes=Makefile.in - xmake_file=x-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 + ;; + vax-*-openbsd*) + tmake_file="${tm_file} vax/t-openbsd" ;; vax-*-ultrix*) # vaxen running ultrix - tm_file=vax/ultrix.h + tm_file="${tm_file} vax/ultrix.h" use_collect2=yes + float_format=vax ;; vax-*-vms*) # vaxen running VMS xm_file=vax/xm-vms.h tm_file=vax/vms.h + float_format=vax ;; - pdp11-*-bsd) - xm_file=pdp11/xm-pdp11.h - tm_file=pdp11/2bsd.h - tmake_file=pdp11/t-pdp11 - ;; - pdp11-*-*) - xm_file=pdp11/xm-pdp11.h - tm_file=pdp11/pdp11.h - tmake_file=pdp11/t-pdp11 + vax-*-*) # vax default entry + float_format=vax ;; we32k-att-sysv*) - cpu_type=we32k + xm_file="${xm_file} xm-svr3" use_collect2=yes ;; *) @@ -2402,14 +4849,14 @@ for machine in $canon_build $canon_host $canon_target; do case $machine in *-*-linux-gnu*) - ;; # Existing Linux/GNU systems do not use the GNU setup. + ;; # Existing GNU/Linux systems do not use the GNU setup. *-*-gnu*) # On the GNU system, the setup is just about the same on # each different CPU. The specific machines that GNU # supports are matched above and just set $cpu_type. - xm_file=${cpu_type}/xm-gnu.h + xm_file="xm-gnu.h ${xm_file}" tm_file=${cpu_type}/gnu.h - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" # GNU always uses ELF. elf=yes # GNU tools are the only tools. @@ -2417,161 +4864,640 @@ for machine in $canon_build $canon_host $canon_target; do gas=yes # On GNU, the headers are already okay. fixincludes=Makefile.in - # Don't build libgcc1.c, because there is no non-GNU - # compiler to build it with. The GNU system C library will - # include assembly versions of any needed functions. - tmake_file=t-libc-ok + 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 - broken_install=yes install_headers_dir=install-headers-cpio ;; *-*-sysv*) - broken_install=yes install_headers_dir=install-headers-cpio ;; esac - # Distinguish i386 from i486/i586. - # ??? For the moment we treat i586 as an i486. + # Distinguish i[34567]86 # Also, do not run mips-tfile on MIPS if using gas. + # Process --with-cpu= for PowerPC/rs6000 + target_cpu_default2= case $machine in - i[45]86-*-*) - target_cpu_default=2 + i486-*-*) + target_cpu_default2=1 ;; - mips*-*-*) + i586-*-*) + target_cpu_default2=2 + ;; + i686-*-* | i786-*-*) + target_cpu_default2=3 + ;; + alpha*-*-*) + case $machine in + alphaev6*) + target_cpu_default2="MASK_CPU_EV6|MASK_BWX|MASK_CIX|MASK_MAX" + ;; + alphapca56*) + target_cpu_default2="MASK_CPU_EV5|MASK_BWX|MASK_MAX" + ;; + alphaev56*) + target_cpu_default2="MASK_CPU_EV5|MASK_BWX" + ;; + alphaev5*) + target_cpu_default2="MASK_CPU_EV5" + ;; + esac + if [ x$gas = xyes ] then - target_cpu_default=16 + if [ "$target_cpu_default2" = "" ] + then + target_cpu_default2="MASK_GAS" + else + target_cpu_default2="${target_cpu_default2}|MASK_GAS" + fi fi ;; - alpha-*-*) + arm*-*-*) + case "x$with_cpu" in + x) + # The most generic + target_cpu_default2="TARGET_CPU_generic" + ;; + + # Distinguish cores, and major variants + # arm7m doesn't exist, but D & I don't affect code + xarm23678 | xarm250 | xarm67010 \ + | xarm7m | xarm7dm | xarm7dmi | xarm7tdmi \ + | xarm7100 | xarm7500 | xarm7500fe | xarm810 \ + | xstrongarm | xstrongarm110) + target_cpu_default2="TARGET_CPU_$with_cpu" + ;; + + xyes | xno) + echo "--with-cpu must be passed a value" 1>&2 + exit 1 + ;; + + *) + if [ x$pass2done = xyes ] + then + echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2 + exit 1 + fi + ;; + esac + ;; + + mips*-*-ecoff* | mips*-*-elf*) if [ x$gas = xyes ] then - target_cpu_default=4 + if [ x$gnu_ld = xyes ] + then + target_cpu_default2=20 + else + target_cpu_default2=16 + fi fi ;; - esac + mips*-*-*) + if [ x$gas = xyes ] + then + target_cpu_default2=16 + fi + ;; + powerpc*-*-* | rs6000-*-*) + case "x$with_cpu" in + x) + ;; - # No need for collect2 if we have the GNU linker. - case x$gnu_ld in - xyes) - use_collect2= + xcommon | xpower | xpower2 | xpowerpc | xrios \ + | xrios1 | xrios2 | xrsc | xrsc1 \ + | x601 | x602 | x603 | x603e | x604 | x604e | x620 \ + | x403 | x505 | x801 | x821 | x823 | x860) + target_cpu_default2="\"$with_cpu\"" + ;; + + xyes | xno) + echo "--with-cpu must be passed a value" 1>&2 + exit 1 + ;; + + *) + if [ x$pass2done = xyes ] + then + echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2 + exit 1 + fi + ;; + esac + ;; + sparc*-*-*) + case ".$with_cpu" in + .) + target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`" + ;; + .supersparc | .ultrasparc | .v7 | .v8 | .v9) + target_cpu_default2="TARGET_CPU_$with_cpu" + ;; + *) + if [ x$pass2done = xyes ] + then + echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2 + exit 1 + fi + ;; + esac ;; esac -# Default certain vars that apply to both host and target in turn. - if [ x$cpu_type = x ] - then cpu_type=`echo $machine | sed 's/-.*$//'` + if [ "$target_cpu_default2" != "" ] + then + if [ "$target_cpu_default" != "" ] + then + target_cpu_default="(${target_cpu_default}|${target_cpu_default2})" + else + target_cpu_default=$target_cpu_default2 + fi fi + # No need for collect2 if we have the GNU linker. + # Actually, there is now; GNU ld doesn't handle the EH info or + # collecting for shared libraries. + #case x$gnu_ld in + #xyes) + # use_collect2= + # ;; + #esac + # 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 ] then - if [ x$xm_file = x ] + if [ x"$xm_file" = x ] then build_xm_file=$cpu_type/xm-$cpu_type.h else build_xm_file=$xm_file fi + build_xm_defines=$xm_defines + build_install_headers_dir=$install_headers_dir + build_exeext=$exeext pass1done=yes else if [ x$pass2done = x ] then - if [ x$xm_file = x ] + if [ x"$xm_file" = x ] then host_xm_file=$cpu_type/xm-$cpu_type.h else host_xm_file=$xm_file fi - if [ x$xmake_file = x ] + host_xm_defines=$xm_defines + if [ x"$xmake_file" = x ] then xmake_file=$cpu_type/x-$cpu_type fi - host_xmake_file=$xmake_file - host_broken_install=$broken_install - host_install_headers_dir=$install_headers_dir + host_xmake_file="$xmake_file" host_truncate_target=$truncate_target + host_extra_gcc_objs=$extra_gcc_objs + host_extra_objs=$extra_host_objs + host_exeext=$exeext pass2done=yes fi fi done +extra_objs="${host_extra_objs} ${extra_objs}" + # Default the target-machine variables that were not explicitly set. -if [ x$tm_file = x ] +if [ x"$tm_file" = x ] then tm_file=$cpu_type/$cpu_type.h; fi if [ x$extra_headers = x ] then extra_headers=; fi -if [ x$xm_file = x ] +if [ x"$xm_file" = x ] then xm_file=$cpu_type/xm-$cpu_type.h; fi -md_file=$cpu_type/$cpu_type.md +if [ x$md_file = x ] +then md_file=$cpu_type/$cpu_type.md; fi if [ x$out_file = x ] then out_file=$cpu_type/$cpu_type.c; fi -if [ x$tmake_file = x ] +if [ x"$tmake_file" = x ] then tmake_file=$cpu_type/t-$cpu_type fi +if [ x$float_format = x ] +then float_format=i64 +fi + +if [ x$enable_haifa = x ] +then + case $target in + alpha*-* | hppa1.?-* | powerpc*-* | rs6000-* | *sparc*-* | m32r*-*) + enable_haifa=yes;; + esac +fi + +# Handle cpp installation. +if [ x$enable_cpp != x ] +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. echo "Using \`$srcdir/config/$out_file' to output insns." echo "Using \`$srcdir/config/$md_file' as machine description file." -echo "Using \`$srcdir/config/$tm_file' as target machine macro file." -echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file." -if [ $host_xm_file != $build_xm_file ]; then - echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file." + +count=a +for f in $tm_file; do + count=${count}x +done +if [ $count = ax ]; then + echo "Using \`$srcdir/config/$tm_file' as target machine macro file." +else + echo "Using the following target machine macro files:" + for f in $tm_file; do + echo " $srcdir/config/$f" + done +fi + +count=a +for f in $host_xm_file; do + count=${count}x +done +if [ $count = ax ]; then + echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file." +else + echo "Using the following host machine macro files:" + for f in $host_xm_file; do + echo " $srcdir/config/$f" + done +fi + +if [ "$host_xm_file" != "$build_xm_file" ]; then + count=a + for f in $build_xm_file; do + count=${count}x + done + if [ $count = ax ]; then + echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file." + else + echo "Using the following build machine macro files:" + for f in $build_xm_file; do + echo " $srcdir/config/$f" + done + fi +fi + +if [ x$thread_file = x ]; then + if [ x$target_thread_file != x ]; then + thread_file=$target_thread_file + else + thread_file='single' + fi +fi + +# Set up the header files. +# $links is the list of header files to create. +# $vars is the list of shell variables with file names to include. +# 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}" + +# 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 ] +then + build_xm_file="auto-host.h ${build_xm_file}" +else + # We create a subdir, then run autoconf in the subdir. + # To prevent recursion we set host and build for the new + # invocation of configure to the build for this invocation + # of configure. + tempdir=build.$$ + rm -rf $tempdir + mkdir $tempdir + cd $tempdir + case ${srcdir} in + /*) realsrcdir=${srcdir};; + *) realsrcdir=../${srcdir};; + esac + CC=${CC_FOR_BUILD} ${realsrcdir}/configure \ + --target=$target --host=$build --build=$build + + # We just finished tests for the build machine, so rename + # the file auto-build.h in the gcc directory. + mv auto-host.h ../auto-build.h + cd .. + rm -rf $tempdir + build_xm_file="auto-build.h ${build_xm_file}" fi -# Set up the list of links to be made. -# $links is the list of link names, and $files is the list of names to link to. -files="$host_xm_file $tm_file $xm_file $build_xm_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 # Make the links. -while [ -n "$files" ] +while [ -n "$vars" ] do - # set file to car of files, files to cdr of files - set $files; file=$1; shift; files=$* + set $vars; var=$1; shift; vars=$* set $links; link=$1; shift; links=$* + set $defines; define=$1; shift; defines=$* + + rm -f $link + + # Define TARGET_CPU_DEFAULT if the system wants one. + # This substitutes for lots of *.h files. + if [ "$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 + echo "#include \"$file\"" >>$link + done + + for def in `eval echo '$'$define`; do + echo "#ifndef $def" >>$link + echo "#define $def" >>$link + echo "#endif" >>$link + done +done + +# Truncate the target if necessary +if [ 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 + gcc_version_trigger=$with_gcc_version_trigger +else + gcc_version_trigger=${srcdir}/version.c +fi +gcc_version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < ${gcc_version_trigger}` + +# Get an absolute path to the GCC top-level source directory +holddir=`pwd` +cd $srcdir +topdir=`pwd` +cd $holddir + +# Conditionalize the makefile for this host machine. +# Make-host contains the concatenation of all host makefile fragments +# [there can be more than one]. This file is built by configure.frag. +host_overrides=Make-host +dep_host_xmake_file= +for f in .. ${host_xmake_file} +do + if [ -f ${srcdir}/config/$f ] + then + dep_host_xmake_file="${dep_host_xmake_file} ${srcdir}/config/$f" + fi +done + +# Conditionalize the makefile for this target machine. +# Make-target contains the concatenation of all host makefile fragments +# [there can be more than one]. This file is built by configure.frag. +target_overrides=Make-target +dep_tmake_file= +for f in .. ${tmake_file} +do + if [ -f ${srcdir}/config/$f ] + then + dep_tmake_file="${dep_tmake_file} ${srcdir}/config/$f" + fi +done + +# If the host doesn't support symlinks, modify CC in +# FLAGS_TO_PASS so CC="stage1/xgcc -Bstage1/" works. +# Otherwise, we can use "CC=$(CC)". +rm -f symtest.tem +if $symbolic_link $srcdir/gcc.c symtest.tem 2>/dev/null +then + cc_set_by_configure="\$(CC)" + stage_prefix_set_by_configure="\$(STAGE_PREFIX)" +else + rm -f symtest.tem + if cp -p $srcdir/gcc.c symtest.tem 2>/dev/null + then + symbolic_link="cp -p" + else + symbolic_link="cp" + fi + 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 + +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" +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 +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 +done + +# Define macro CROSS_COMPILE in compilation +# if this is a cross-compiler. +# Also use all.cross instead of all.internal +# and add cross-make to Makefile. +cross_overrides="/dev/null" +if [ x$host != x$target ] +then + cross_defines="CROSS=-DCROSS_COMPILE" + cross_overrides="${topdir}/cross-make" +fi + +# When building gcc with a cross-compiler, we need to fix a few things. +# This must come after cross-make as we want all.build to override +# all.cross. +build_overrides="/dev/null" +if [ x$build != x$host ] +then + build_overrides="${topdir}/build-make" +fi + +# Expand extra_headers to include complete path. +# This substitutes for lots of t-* files. +extra_headers_list= +if [ "x$extra_headers" = x ] +then true +else + # Prepend ${srcdir}/ginclude/ to every entry in extra_headers. + for file in $extra_headers; + do + extra_headers_list="${extra_headers_list} \$(srcdir)/ginclude/${file}" + done +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 ] +then + will_use_collect2= + maybe_use_collect2= +else + will_use_collect2="collect2" + maybe_use_collect2="-DUSE_COLLECT2" +fi + +# NEED TO CONVERT +# Set MD_DEPS if the real md file is in md.pre-cpp. +# Set MD_CPP to the cpp to pass the md file through. Md files use ';' +# for line oriented comments, so we must always use a GNU cpp. If +# 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 ] +then + md_file_sub=$srcdir/config/$md_file +else + md_file=md +fi + +# If we have gas in the build tree, make a link to it. +if [ -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 + 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 +# 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 +# fi +fi - rm -f $link - echo "#include \"$file\"" >$link -done +# 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 +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 + # Build using assembler in the current directory. + gcc_cv_as=./as$host_exeext +elif [ -f $gcc_cv_as_gas_srcdir/configure.in ]; 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 + 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 + # 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 + gcc_cv_as_alignment_features=".balign and .p2align" + cat >> confdefs.h <<\EOF +#define HAVE_GAS_BALIGN_AND_P2ALIGN 1 +EOF -# Truncate the target if necessary -if [ x$host_truncate_target != x ]; then - target=`echo $target | sed -e 's/\(..............\).*/\1/'` + 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 + gcc_cv_as_alignment_features=".p2align including maximum skip" + cat >> confdefs.h <<\EOF +#define HAVE_GAS_MAX_SKIP_P2ALIGN 1 +EOF + + fi + fi +elif [ x$host = x$target ]; then + # Native build. + gcc_cv_as=as$host_exeext fi +if [ x$gcc_cv_as != x ]; then + # Check if we have .balign and .p2align + echo ".balign 4" > conftest.s + echo ".p2align 2" >> conftest.s + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + gcc_cv_as_alignment_features=".balign and .p2align" + cat >> confdefs.h <<\EOF +#define HAVE_GAS_BALIGN_AND_P2ALIGN 1 +EOF -# Get the version number from the toplevel -version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < ${srcdir}/version.c` + fi + rm -f conftest.s conftest.o + # Check if specifying the maximum bytes to skip when + # using .p2align is supported. + echo ".p2align 4,,7" > conftest.s + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + gcc_cv_as_alignment_features=".p2align including maximum skip" + cat >> confdefs.h <<\EOF +#define HAVE_GAS_MAX_SKIP_P2ALIGN 1 +EOF -# For the current directory and all of the language subdirectories, -# do the rest of the script ... + fi + rm -f conftest.s conftest.o +fi +echo "$ac_t""$gcc_cv_as_alignment_features" 1>&6 +# Figure out what language subdirectories are present. subdirs= for lang in ${srcdir}/*/config-lang.in .. do case $lang in ..) ;; # The odd quoting in the next line works around - # an apparent bug in bash 1.12 on GNU/Linux. + # an apparent bug in bash 1.12 on linux. ${srcdir}/[*]/config-lang.in) ;; *) subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`" ;; esac done -# Are we using gcc as the native compiler? -case $canon_host in -*linux*) # All GNU/Linux systems use gcc as the native compiler. - prefix=$native_prefix - gxx_include_dir=$prefix/include/g++ - ;; -esac +# Make gthr-default.h if we have a thread file. +gthread_flags= +if [ $thread_file != single ]; then + rm -f gthr-default.h + echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h + gthread_flags=-DHAVE_GTHR_DEFAULT +fi + # Make empty files to contain the specs and options for each language. # Then add #include lines to for a compiler that has specs and/or options. @@ -2592,502 +5518,226 @@ do fi done -# Define SET_MAKE if this old version of `make' doesn't define $(MAKE). -rm -f Makefile.xx -(echo 'all:'; echo ' @echo maketemp=$(MAKE)') >Makefile.xx -case `${MAKE-make} -f Makefile.xx 2>/dev/null | grep maketemp=` in -'maketemp=') - SET_MAKE="MAKE = ${MAKE-make}" - ;; -*) - SET_MAKE= - ;; -esac -rm -f Makefile.xx +# These (without "all_") are set in each config-lang.in. +# `language' must be a single word so is spelled singularly. +all_languages= +all_boot_languages= +all_compilers= +all_stagestuff= +all_diff_excludes= +all_outputs=Makefile +# List of language makefile fragments. +all_lang_makefiles= +all_headers= +all_lib2funcs= -savesrcdir=$srcdir -for subdir in . $subdirs -do - oldsrcdir=$savesrcdir +# Add the language fragments. +# Languages are added via two mechanisms. Some information must be +# recorded in makefile variables, these are defined in config-lang.in. +# We accumulate them and plug them into the main Makefile. +# The other mechanism is a set of hooks for each of the main targets +# like `clean', `install', etc. - # Re-adjust the path - case $oldsrcdir in - /*) - srcdir=$oldsrcdir/$subdir - ;; - *) - case $subdir in - .) - ;; - *) - oldsrcdir=../${oldsrcdir} - srcdir=$oldsrcdir/$subdir - ;; - esac - ;; - esac - mainsrcdir=$oldsrcdir - STARTDIR=`pwd` - test -d $subdir || mkdir $subdir - cd $subdir - - # Create Makefile.tem from Makefile.in. - # Make it set VPATH if necessary so that the sources are found. - # Also change its value of srcdir. - # Also create a .gdbinit file which runs the one in srcdir - # and tells GDB to look there for source files. - case $srcdir in - . | ./$subdir | .././$subdir) - rm -f Makefile.tem - cp Makefile.in Makefile.tem - chmod +w Makefile.tem - ;; - *) - rm -f Makefile.tem - echo "VPATH = ${srcdir}" \ - | cat - ${srcdir}/Makefile.in \ - | sed "s@^srcdir = \.@srcdir = ${srcdir}@" > Makefile.tem - rm -f .gdbinit - echo "dir ." > .gdbinit - echo "dir ${srcdir}" >> .gdbinit - if [ x$gdb_needs_out_file_path = xyes ] +language_fragments="Make-lang" +language_hooks="Make-hooks" +oldstyle_subdirs= + +for s in .. $subdirs +do + if [ $s != ".." ] + then + language= + boot_language= + compilers= + stagestuff= + diff_excludes= + headers= + outputs= + lib2funcs= + . ${srcdir}/$s/config-lang.in + if [ "x$language" = x ] then - echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit + echo "${srcdir}/$s/config-lang.in doesn't set \$language." 1>&2 + exit 1 fi - if [ "x$subdirs" != x ]; then - for s in $subdirs - do - echo "dir ${srcdir}/$s" >> .gdbinit - done + 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 ] + then + all_boot_languages="$all_boot_languages $language" fi - echo "source ${srcdir}/.gdbinit" >> .gdbinit - ;; - esac - - # Conditionalize the makefile for this host machine. - if [ -f ${mainsrcdir}/config/${host_xmake_file} ] - then - rm -f Makefile.xx - sed -e "/####host/ r ${mainsrcdir}/config/${host_xmake_file}" Makefile.tem > Makefile.xx - echo "Merged ${host_xmake_file}." - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - dep_host_xmake_file=${host_xmake_file} - else - # Say in the makefile that there is no host_xmake_file, - # by using a name which (when interpreted relative to $srcdir/config) - # will duplicate another dependency: $srcdir/Makefile.in. - dep_host_xmake_file=../Makefile.in + all_compilers="$all_compilers $compilers" + all_stagestuff="$all_stagestuff $stagestuff" + all_diff_excludes="$all_diff_excludes $diff_excludes" + all_headers="$all_headers $headers" + all_outputs="$all_outputs $outputs" + if [ x$outputs = x ] + then + oldstyle_subdirs="$oldstyle_subdirs $s" + fi + all_lib2funcs="$all_lib2funcs $lib2funcs" fi +done - # Add a definition for MAKE if system wants one. - case "$SET_MAKE" in - ?*) - rm -f Makefile.xx - (echo "$SET_MAKE"; cat Makefile.tem) >Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - esac +# Since we can't use `::' targets, we link each language in +# with a set of hooks, reached indirectly via lang.${target}. - # Add a definition for INSTALL if system wants one. - # This substitutes for lots of x-* files. - if [ x$host_broken_install = x ] - then true - else - rm -f Makefile.xx - abssrcdir=`cd ${srcdir}; pwd` - sed "s|^INSTALL = .*|INSTALL = ${abssrcdir}/install.sh -c|" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi +rm -f Make-hooks +touch Make-hooks +target_list="all.build all.cross start.encap rest.encap \ + info dvi \ + install-normal install-common install-info install-man \ + uninstall distdir \ + mostlyclean clean distclean extraclean maintainer-clean \ + stage1 stage2 stage3 stage4" +for t in $target_list +do + x= + for l in .. $all_languages + do + if [ $l != ".." ]; then + x="$x $l.$t" + fi + done + echo "lang.$t: $x" >> Make-hooks +done - # Some of the following don't make sense in the language makefiles, - # but rather than introduce another level of nesting, we leave them - # as is. +# If we're not building in srcdir, create .gdbinit. - # Set EXTRA_HEADERS according to extra_headers. - # This substitutes for lots of t-* files. - if [ "x$extra_headers" = x ] - then true - else - # Prepend ${srcdir}/ginclude/ to every entry in extra_headers. - list= - for file in $extra_headers; +if [ ! -f Makefile.in ]; then + echo "dir ." > .gdbinit + echo "dir ${srcdir}" >> .gdbinit + if [ x$gdb_needs_out_file_path = xyes ] + then + echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit + fi + if [ "x$subdirs" != x ]; then + for s in $subdirs do - list="${list} ${srcdir}/ginclude/${file}" + echo "dir ${srcdir}/$s" >> .gdbinit done - rm -f Makefile.xx - sed "s|^EXTRA_HEADERS =|EXTRA_HEADERS = ${list}|" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - - # Set EXTRA_PASSES according to extra_passes. - # This substitutes for lots of t-* files. - if [ "x$extra_passes" = x ] - then true - else - rm -f Makefile.xx - sed "s/^EXTRA_PASSES =/EXTRA_PASSES = $extra_passes/" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - - # Set EXTRA_PARTS according to extra_parts. - # This substitutes for lots of t-* files. - if [ "x$extra_parts" = x ] - then true - else - rm -f Makefile.xx - sed "s/^EXTRA_PARTS =/EXTRA_PARTS = $extra_parts/" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem fi + echo "source ${srcdir}/.gdbinit" >> .gdbinit +fi - # Set EXTRA_PROGRAMS according to extra_programs. - if [ "x$extra_programs" = x ] - then true - else - rm -f Makefile.xx - sed "s/^EXTRA_PROGRAMS =/EXTRA_PROGRAMS = $extra_programs/" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi +# Define variables host_canonical and build_canonical +# because some Cygnus local changes in the Makefile depend on them. +build_canonical=${build} +host_canonical=${host} +target_subdir= +if [ "${host}" != "${target}" ] ; then + target_subdir=${target}/ +fi - # Set EXTRA_OBJS according to extra_objs. - # This substitutes for lots of t-* files. - if [ "x$extra_objs" = x ] - then true - else - rm -f Makefile.xx - sed "s|^EXTRA_OBJS =|EXTRA_OBJS = $extra_objs|" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - # Set EXTRA_GCC_OBJS according to extra_gcc_objs. - # This substitutes for lots of t-* files. - if [ "x$extra_gcc_objs" = x ] - then true - else - rm -f Makefile.xx - sed "s|^EXTRA_GCC_OBJS =|EXTRA_GCC_OBJS = $extra_gcc_objs|" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - 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 ] - then true - else - rm -f Makefile.xx - (echo "USE_COLLECT2 = ld"; echo "MAYBE_USE_COLLECT2 = -DUSE_COLLECT2")\ - | cat - Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - - # Add -DTARGET_CPU_DEFAULT for toplev.c if system wants one. - # This substitutes for lots of *.h files. - if [ x$target_cpu_default = x ] - then true - else - rm -f Makefile.xx - # This used cat, but rfg@netcom.com said that ran into NFS bugs. - sed -e "/^# Makefile for GNU C compiler./c\\ -MAYBE_TARGET_DEFAULT = -DTARGET_CPU_DEFAULT=$target_cpu_default\\ -\# Makefile for GNU C compiler." Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - - # Set MD_DEPS if the real md file is in md.pre-cpp. - # Set MD_CPP to the cpp to pass the md file through. Md files use ';' - # for line oriented comments, so we must always use a GNU cpp. If - # building gcc with a cross compiler, use the cross compiler just - # built. Otherwise, we can use the cpp just built. - if [ "x$md_cppflags" = x ] - then - md_file=$srcdir/config/$md_file - else - rm -f Makefile.xx - (if [ x$host = x$build ] ; then - echo "MD_DEPS = $(md_file) cpp" ; echo "MD_CPP = ./cpp" - else - echo "MD_DEPS = md.pre-cpp" ; echo "MD_CPP = \$(HOST_CC) -x c -E" - fi - md_file=md - echo "MD_CPPFLAGS = $md_cppflags") | \ - cat - Makefile.tem | sed -e "s|^MD_FILE[ ]*=.*|MD_FILE = md|" > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - - # If we have gas in the build tree, make a link to it. - if [ -f ../gas/Makefile ]; then - rm -f as; $symbolic_link ../gas/as.new as 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 - rm -f ld; $symbolic_link ../ld/ld.new ld 2>/dev/null - else - rm -f collect-ld; $symbolic_link ../ld/ld.new collect-ld 2>/dev/null - fi - fi - - # If using -program-transform-name, override the installation names. - if [ "x${program_transform_set}" = "xyes" ] ; then - sed -e "s/^program_transform_name[ ]*=.*$/program_transform_name = $program_transform_name/" \ - -e "s/^program_transform_cross_name[ ]*=.*$/program_transform_cross_name = $program_transform_name/" \ - Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - fi - - # Conditionalize the makefile for this target machine. - if [ -f ${mainsrcdir}/config/${tmake_file} ] - then - rm -f Makefile.xx - sed -e "/####target/ r ${mainsrcdir}/config/${tmake_file}" Makefile.tem > Makefile.xx - echo "Merged ${tmake_file}." - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - dep_tmake_file=${tmake_file} - else - # Say in the makefile that there is no tmake_file, - # by using a name which (when interpreted relative to $srcdir/config) - # will duplicate another dependency: $srcdir/Makefile.in. - dep_tmake_file=../Makefile.in - fi - # If this is the top level Makefile, add the language fragments. - # Languages are added via two mechanisms. Some information must be - # recorded in makefile variables, these are defined in config-lang.in. - # We accumulate them and plug them into the main Makefile. - # The other mechanism is a set of hooks for each of the main targets - # like `clean', `install', etc. - if [ $subdir = . ] - then - # These (without "all_") are set in each config-lang.in. - # `language' must be a single word so is spelled singularly. - all_languages= - all_compilers= - all_stagestuff= - all_diff_excludes= - # List of language makefile fragments. - all_lang_makefiles= - - rm -f Makefile.xx Makefile.ll - touch Makefile.ll - for s in .. $subdirs - do - if [ $s != ".." ] - then - language= - compilers= - stagestuff= - diff_excludes= - . ${mainsrcdir}/$s/config-lang.in - if [ "x$language" = x ] - then - echo "${mainsrcdir}/$s/config-lang.in doesn't set \$language." 1>&2 - exit 1 - fi - all_lang_makefiles="$all_lang_makefiles ${mainsrcdir}/$s/Make-lang.in ${mainsrcdir}/$s/Makefile.in" - all_languages="$all_languages $language" - all_compilers="$all_compilers $compilers" - all_stagestuff="$all_stagestuff $stagestuff" - all_diff_excludes="$all_diff_excludes $diff_excludes" +# If this is using newlib, then define inhibit_libc in +# LIBGCC2_CFLAGS. This will cause __eprintf to be left out of +# libgcc.a, but that's OK because newib should have its own version of +# assert.h. +inhibit_libc= +if [ x$with_newlib = xyes ]; then + inhibit_libc=-Dinhibit_libc +fi - cat ${mainsrcdir}/$s/Make-lang.in >> Makefile.ll - fi - done - sed -e "/####language fragments/ r Makefile.ll" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - sed -e "s|^SUBDIRS[ ]*=.*$|SUBDIRS = $subdirs|" \ - -e "s|^LANGUAGES[ ]*=[ ]*\(.*\)$|LANGUAGES = \1 $all_languages|" \ - -e "s|^COMPILERS[ ]*=[ ]*\(.*\)$|COMPILERS = \1 $all_compilers|" \ - -e "s|^LANG_MAKEFILES[ ]*=.*$|LANG_MAKEFILES = $all_lang_makefiles|" \ - -e "s|^LANG_STAGESTUFF[ ]*=.*$|LANG_STAGESTUFF = $all_stagestuff|" \ - -e "s|^LANG_DIFF_EXCLUDES[ ]*=.*$|LANG_DIFF_EXCLUDES = $all_diff_excludes|" \ - Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - - # Since we can't use `::' targets, we link each language in - # with a set of hooks, reached indirectly via lang.${target}. - - target_list="all.build all.cross start.encap rest.encap \ - info dvi \ - install-normal install-common install-info install-man \ - uninstall distdir \ - mostlyclean clean distclean extraclean maintainer-clean \ - stage1 stage2 stage3 stage4" - rm -f Makefile.ll - for t in $target_list - do - x= - for l in .. $all_languages - do - if [ $l != ".." ]; then - x="$x $l.$t" - fi - done - echo "lang.$t: $x" >> Makefile.ll - done - sed -e "/####language hooks/ r Makefile.ll" Makefile.tem > Makefile.xx - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - rm -f Makefile.ll - # If the host doesn't support symlinks, modify CC in - # FLAGS_TO_PASS so CC="stage1/xgcc -Bstage1/" works. - # Otherwise, we can use "CC=$(CC)". - rm -f symtest.tem - if $symbolic_link symtest1.tem symtest.tem 2>/dev/null - then - sed -e 's,CC=set-by-configure,CC=$(CC),' \ - Makefile.tem > Makefile.xx - else - sed -e "s,CC=set-by-configure,CC=\`case '$(CC)' in stage*) echo '$(CC)' | sed -e 's|stage|../stage|g';; *) echo '$(CC)';; esac\`," \ - Makefile.tem > Makefile.xx - fi - rm -f Makefile.tem - mv Makefile.xx Makefile.tem - rm -f symtest.tem +# Override SCHED_OBJ and SCHED_CFLAGS to enable the Haifa scheduler. +sched_prefix= +sched_cflags= +if [ x$enable_haifa = xyes ]; then + echo "Using the Haifa scheduler." + sched_prefix=haifa- + sched_cflags=-DHAIFA +fi - if [ "x$all_languages" != x ] - then - # Missing space after `Merged' is intentional. - echo "Merged$all_languages fragment(s)." - fi - # Otherwise, this is a language subdirectory. If the host supports - # symlinks, point stage[123] at ../stage[123] so bootstrapping and the - # installation procedure can still use CC="stage1/xgcc -Bstage1/". - # If the host doesn't support symlinks, FLAGS_TO_PASS has been - # modified to solve the problem there. - else - for t in stage1 stage2 stage3 stage4 include - do - rm -f $t - $symbolic_link ../$t $t 2>/dev/null - done +if [ 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 + echo "Removing $x" + rm -f $x fi + done +fi + +# Nothing to do for FLOAT_H, float_format already handled. +objdir=`pwd` + + +# Process the language and host/target makefile fragments. +${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xmake_file" "$dep_tmake_file" + +# Substitute configuration variables + + + + + + + + + + + + + + + + + + + + + + + + + + - out_object_file=`basename $out_file .c`.o - - # Remove all formfeeds, since some Makes get confused by them. - # Also arrange to give the variables `target', `host_xmake_file', - # `tmake_file', `prefix', `local_prefix', `exec_prefix', `FIXINCLUDES' - # `out_file', `out_object', `md_file', `lang_specs_files', - # `lang_options_files', and `INSTALL_HEADERS_DIR' values in the - # Makefile from the values they have in this script. - rm -f Makefile.xx - rm -f aux-output.c aux-output.o md - # Create an empty Makefile.sed first, to work around a Nextstep 3.3 bug. - echo 's| ||' > Makefile.sed - rm Makefile.sed - echo 's| ||' > Makefile.sed - echo "s|^target=.*$|target=${target}|" >> Makefile.sed - echo "s|^xmake_file=.*$|xmake_file=${dep_host_xmake_file}|" >> Makefile.sed - echo "s|^tmake_file=.*$|tmake_file=${dep_tmake_file}|" >> Makefile.sed - echo "s|^version=.*$|version=${version}|" >> Makefile.sed - echo "s|^version=.*$|version=${version}|" >> Makefile.sed - echo "s|^out_file=.*$|out_file=${srcdir}/config/${out_file}|" >> Makefile.sed - echo "s|^out_object_file=.*$|out_object_file=${out_object_file}|" >> Makefile.sed - echo "s|^md_file=.*$|md_file=${md_file}|" >> Makefile.sed - echo "s|^tm_file=.*$|tm_file=${srcdir}/config/${tm_file}|" >> Makefile.sed - echo "s|^host_xm_file=.*$|host_xm_file=${srcdir}/config/${host_xm_file}|" >> Makefile.sed - echo "s|^build_xm_file=.*$|build_xm_file=${srcdir}/config/${build_xm_file}|" >> Makefile.sed - echo "s|^lang_specs_files=.*$|lang_specs_files=${lang_specs_files}|" >> Makefile.sed - echo "s|^lang_options_files=.*$|lang_options_files=${lang_options_files}|" >> Makefile.sed - echo "s|^prefix[ ]*=.*|prefix = $prefix|" >> Makefile.sed - echo "s|^gxx_include_dir[ ]*=.*|gxx_include_dir = $gxx_include_dir|" >> Makefile.sed - echo "s|^local_prefix[ ]*=.*|local_prefix = $local_prefix|" >> Makefile.sed - echo "s|^exec_prefix[ ]*=.*|exec_prefix = $exec_prefix|" >> Makefile.sed - echo "s|^FIXINCLUDES[ ]*=.*|FIXINCLUDES = $fixincludes|" >> Makefile.sed - echo "s|^INSTALL_HEADERS_DIR[ ]*=.*$|INSTALL_HEADERS_DIR = ${host_install_headers_dir}|" >> Makefile.sed - sed -f Makefile.sed Makefile.tem > Makefile.xx - rm -f Makefile.tem Makefile.sed - mv Makefile.xx Makefile.tem - - # Install Makefile for real, after making final changes. - # Define macro CROSS_COMPILE in compilation if this is a cross-compiler. - # Also use all.cross instead of all.internal, and add cross-make to Makefile. - if [ x$canon_host = x$canon_target ] - then - rm -f Makefile - if [ x$canon_host = x$canon_build ] - then - mv Makefile.tem Makefile - else - # When building gcc with a cross-compiler, we need to fix a - # few things. - echo "build= $build" > Makefile - sed -e "s|objc-runtime$||" \ - -e "/####build/ r ${mainsrcdir}/build-make" Makefile.tem >> Makefile - rm -f Makefile.tem Makefile.xx - fi - else - rm -f Makefile - echo "CROSS=-DCROSS_COMPILE" > Makefile - sed -e "/####cross/ r ${mainsrcdir}/cross-make" Makefile.tem >> Makefile - rm -f Makefile.tem Makefile.xx - fi - echo "Created \`$subdir/Makefile'." - # If a subdirectory has a configure script, run it. - if [ x$subdir != x. ] - then - if [ -f $srcdir/configure ] - then - ${CONFIG_SHELL-sh} $srcdir/configure $arguments --srcdir=$srcdir - fi - fi - cd $STARTDIR -done # end of current-dir SUBDIRS loop - -srcdir=$savesrcdir - -# Describe the chosen configuration in config.status. -# Make that file a shellscript which will reestablish the same configuration. -echo "#!/bin/sh -# GCC was configured as follows: -${srcdir}/configure" $arguments > config.new -echo echo host=$canon_host target=$canon_target build=$canon_build >> config.new -chmod a+x config.new -if [ -f config.bak ] && cmp config.bak config.new >/dev/null 2>/dev/null; -then - mv -f config.bak config.status - rm -f config.new -else - mv -f config.new config.status - rm -f config.bak -fi -str2= -str3= -str4=. -if [ x$canon_host = x$canon_target ] + + + + + + + + + + + + + + + + + + + + + + + + +# Echo that links are built +if [ x$host = x$target ] then str1="native " else str1="cross-" - str2=" from $canon_host" + str2=" from $host" fi -if [ x$canon_host != x$canon_build ] +if [ x$host != x$build ] then - str3=" on a $canon_build system" + str3=" on a $build system" fi if [ "x$str2" != x ] || [ "x$str3" != x ] @@ -3095,11 +5745,523 @@ then str4= fi -echo "Links are now set up to build a ${str1}compiler for ${canon_target}$str4" 1>&2 +echo "Links are now set up to build a ${str1}compiler for ${target}$str4" 1>&2 if [ "x$str2" != x ] || [ "x$str3" != x ] then echo " ${str2}${str3}." 1>&2 fi +# Truncate the target if necessary +if [ x$host_truncate_target != x ]; then + target=`echo $target | sed -e 's/\(..............\).*/\1/'` +fi + +# Configure the subdirectories +# AC_CONFIG_SUBDIRS($subdirs) + +# Create the Makefile +# and configure language subdirectories +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "$all_outputs auto-host.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@SET_MAKE@%$SET_MAKE%g +s%@AWK@%$AWK%g +s%@LEX@%$LEX%g +s%@LEXLIB@%$LEXLIB%g +s%@LN@%$LN%g +s%@LN_S@%$LN_S%g +s%@RANLIB@%$RANLIB%g +s%@YACC@%$YACC%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CPP@%$CPP%g +s%@vfprintf@%$vfprintf%g +s%@doprint@%$doprint%g +s%@manext@%$manext%g +s%@objext@%$objext%g +s%@gthread_flags@%$gthread_flags%g +s%@build_canonical@%$build_canonical%g +s%@host_canonical@%$host_canonical%g +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%@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%@cpp_main@%$cpp_main%g +s%@extra_passes@%$extra_passes%g +s%@extra_programs@%$extra_programs%g +s%@extra_parts@%$extra_parts%g +s%@extra_c_objs@%$extra_c_objs%g +s%@extra_cxx_objs@%$extra_cxx_objs%g +s%@extra_c_flags@%$extra_c_flags%g +s%@extra_objs@%$extra_objs%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%@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%@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%@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 +/@target_overrides@/r $target_overrides +s%@target_overrides@%%g +/@host_overrides@/r $host_overrides +s%@host_overrides@%%g +s%@cross_defines@%$cross_defines%g +/@cross_overrides@/r $cross_overrides +s%@cross_overrides@%%g +/@build_overrides@/r $build_overrides +s%@build_overrides@%%g +/@language_fragments@/r $language_fragments +s%@language_fragments@%%g +/@language_hooks@/r $language_hooks +s%@language_hooks@%%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +. $srcdir/configure.lang +case x$CONFIG_HEADERS in +xauto-host.h:config.in) +echo > cstamp-h ;; +esac +# If the host supports symlinks, point stage[1234] at ../stage[1234] so +# bootstrapping and the installation procedure can still use +# CC="stage1/xgcc -Bstage1/". If the host doesn't support symlinks, +# 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 + for d in .. ${subdirs} ; do + if [ $d != .. ]; then + STARTDIR=`pwd` + cd $d + for t in stage1 stage2 stage3 stage4 include + do + rm -f $t + $symbolic_link ../$t $t 2>/dev/null + done + cd $STARTDIR + fi + done +else true ; fi + exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/contrib/gcc/configure.frag b/contrib/gcc/configure.frag new file mode 100644 index 0000000..4bdac94 --- /dev/null +++ b/contrib/gcc/configure.frag @@ -0,0 +1,77 @@ +# configure.frag for GNU CC +# Process the host/target/language Makefile fragments. + +# Copyright (C) 1997 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. + +# First parameter is the source directory, second is list of subdirectories, +# third is list of host makefile fragments, fourth is list of target makefile +# fragments. + +srcdir=$1 +subdirs=$2 +xmake_files=$3 +tmake_files=$4 + +# Copy all the host makefile fragments into Make-host. + +rm -f Make-host +touch Make-host +for f in .. $xmake_files +do + if [ -f $f ] + then + cat $f >> Make-host + fi +done + +# Copy all the target makefile fragments into Make-target. + +rm -f Make-target +touch Make-target +for f in .. $tmake_files +do + if [ -f $f ] + then + cat $f >> Make-target + fi +done + +# Ensure the language build subdirectories exist. + +for subdir in . $subdirs +do + if [ $subdir != . ] + then + test -d $subdir || mkdir $subdir + fi +done + +# Now copy each language's Make-lang.in file to Make-lang. + +rm -f Make-lang +touch Make-lang + +for subdir in . $subdirs +do + if [ $subdir != . ] + then + cat $srcdir/$subdir/Make-lang.in >> Make-lang + fi +done diff --git a/contrib/gcc/configure.in b/contrib/gcc/configure.in new file mode 100644 index 0000000..a943830 --- /dev/null +++ b/contrib/gcc/configure.in @@ -0,0 +1,3833 @@ +# configure.in for GNU CC +# Process this file with autoconf to generate a configuration script. + +# Copyright (C) 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 +#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. + +# Initialization and defaults +AC_INIT(tree.c) +AC_CONFIG_HEADER(auto-host.h:config.in) + +remove=rm +hard_link=ln +symbolic_link='ln -s' +copy=cp + +# Check for additional parameters + +# With GNU ld +AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld arrange to work with GNU ld.], +gnu_ld_flag="$with_gnu_ld", +gnu_ld_flag=no) + +# 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) + +# With stabs +AC_ARG_WITH(stabs, +[ --with-stabs arrange to use stabs instead of host debug format.], +stabs="$with_stabs", +stabs=no) + +# With ELF +AC_ARG_WITH(elf, +[ --with-elf arrange to use ELF instead of host debug format.], +elf="$with_elf", +elf=no) + +# Specify the local prefix +local_prefix= +AC_ARG_WITH(local-prefix, +[ --with-local-prefix=DIR specifies directory to put local include.], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for local include directory prefix) ;; +no) ;; +*) local_prefix=$with_local_prefix ;; +esac]) + +# Default local prefix if it is empty +if [[ x$local_prefix = x ]]; then + local_prefix=/usr/local +fi + +gxx_include_dir= +# Specify the g++ header file directory +AC_ARG_WITH(gxx-include-dir, +[ --with-gxx-include-dir=DIR + specifies directory to put g++ header files.], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for g++ include directory) ;; +no) ;; +*) gxx_include_dir=$with_gxx_include_dir ;; +esac]) + +if test x${gxx_include_dir} = x; then + if test x${enable_version_specific_runtime_libs} = xyes; then + gxx_include_dir='${libsubdir}/include/g++' + else + gxx_include_dir='${prefix}/include/g++' + fi +fi + +# Enable expensive internal checks +AC_ARG_ENABLE(checking, +[ --enable-checking enable expensive run-time checks.], +[case "${enableval}" in +yes) AC_DEFINE(ENABLE_CHECKING) ;; +no) ;; +*) AC_MSG_ERROR(bad value ${enableval} given for checking option) ;; +esac]) + +# Enable use of cpplib for C. +cpp_main=cccp +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 + cpp_main=cppmain +fi) + +# Enable Haifa scheduler. +AC_ARG_ENABLE(haifa, +[ --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 +# Pass with a value to specify a thread package +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 + enable_threads='' +fi, +enable_threads='') + +enable_threads_flag=$enable_threads +# Check if a valid thread package +case x${enable_threads_flag} in + x | xno) + # No threads + target_thread_file='single' + ;; + xyes) + # default + target_thread_file='' + ;; + xdecosf1 | xirix | xmach | xos2 | xposix | xpthreads | xsingle | \ + xsolaris | xwin32 | xdce | xvxworks) + target_thread_file=$enable_threads_flag + ;; + *) + echo "$enable_threads is an unknown thread package" 1>&2 + exit 1 + ;; +esac + +# Determine the host, build, and target systems +AC_CANONICAL_SYSTEM + +# Find the native compiler +AC_PROG_CC +AC_PROG_MAKE_SET + +# Find some useful tools +AC_PROG_AWK +AC_PROG_LEX +GCC_PROG_LN +GCC_PROG_LN_S +GCC_C_VOLATILE +AC_PROG_RANLIB +AC_PROG_YACC +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) + +# 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 the system preprocessor understands the ANSI C preprocessor +# stringification operator. +AC_MSG_CHECKING(whether cpp understands the stringify operator) +AC_CACHE_VAL(gcc_cv_c_have_stringify, +[AC_TRY_COMPILE(, +[#define S(x) #x +char *test = S(foo);], +gcc_cv_c_have_stringify=yes, gcc_cv_c_have_stringify=no)]) +AC_MSG_RESULT($gcc_cv_c_have_stringify) +if test $gcc_cv_c_have_stringify = yes; then + AC_DEFINE(HAVE_CPP_STRINGIFY) +fi + +# Use only if it exists, +# doesn't clash with , and declares intmax_t. +AC_MSG_CHECKING(for inttypes.h) +AC_CACHE_VAL(gcc_cv_header_inttypes_h, +[AC_TRY_COMPILE( + [#include +#include ], + [intmax_t i = -1;], + [gcc_cv_header_inttypes_h=yes], + gcc_cv_header_inttypes_h=no)]) +AC_MSG_RESULT($gcc_cv_header_inttypes_h) +if test $gcc_cv_header_inttypes_h = yes; then + AC_DEFINE(HAVE_INTTYPES_H) +fi + +AC_CHECK_FUNCS(strtoul bsearch strerror putenv popen bcopy bzero bcmp \ + index rindex strchr strrchr kill getrlimit setrlimit atoll atoq \ + sysconf isascii gettimeofday) + +GCC_FUNC_VFPRINTF_DOPRNT +GCC_FUNC_PRINTF_PTR + +GCC_NEED_DECLARATIONS(malloc realloc calloc free bcopy bzero bcmp \ + index rindex getenv atol sbrk abort atof strerror getcwd getwd) + +GCC_NEED_DECLARATIONS(getrlimit setrlimit, [ +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +]) + +AC_DECL_SYS_SIGLIST + +# File extensions +manext='.1' +objext='.o' +AC_SUBST(manext) +AC_SUBST(objext) + +build_xm_file= +build_xm_defines= +build_install_headers_dir=install-headers-tar +build_exeext= +host_xm_file= +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; +# then we decode the target machine and forget everything else +# that came from the host machine. +for machine in $build $host $target; do + + out_file= + xmake_file= + tmake_file= + extra_headers= + extra_passes= + extra_parts= + extra_programs= + extra_objs= + extra_host_objs= + extra_gcc_objs= + xm_defines= + float_format= + # Set this to force installation and use of collect2. + 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 + # wants its .md file passed through cpp. + md_cppflags= + # Set this if directory names should be truncated to 14 characters. + truncate_target= + # Set this if gdb needs a dir command with `dirname $out_file` + gdb_needs_out_file_path= + # Set this if the build machine requires executables to have a + # file name suffix. + exeext= + # Set this to control which thread package will be used. + thread_file= + # Reinitialize these from the flag values every loop pass, since some + # configure entries modify them. + gas="$gas_flag" + gnu_ld="$gnu_ld_flag" + enable_threads=$enable_threads_flag + + # Set default cpu_type, tm_file and xm_file so it can be updated in + # each machine entry. + cpu_type=`echo $machine | sed 's/-.*$//'` + case $machine in + alpha*-*-*) + cpu_type=alpha + ;; + arm*-*-*) + cpu_type=arm + ;; + c*-convex-*) + cpu_type=convex + ;; + i[[34567]]86-*-*) + cpu_type=i386 + ;; + hppa*-*-*) + cpu_type=pa + ;; + m68000-*-*) + cpu_type=m68k + ;; + mips*-*-*) + cpu_type=mips + ;; + powerpc*-*-*) + cpu_type=rs6000 + ;; + pyramid-*-*) + cpu_type=pyr + ;; + sparc*-*-*) + cpu_type=sparc + ;; + esac + + tm_file=${cpu_type}/${cpu_type}.h + xm_file=${cpu_type}/xm-${cpu_type}.h + + # Common parts for linux-gnu and openbsd systems + case $machine in + *-*-linux-gnu*) + xm_defines="HAVE_ATEXIT POSIX BSTRING" + ;; + *-*-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 + if test x$enable_threads = xyes; then + thread_file='posix' + tmake_file="${tmake_file} t-openbsd-thread" + fi + ;; + esac + + case $machine in + # Support site-specific machine types. + *local*) + cpu_type=`echo $machine | sed -e 's/-.*//'` + 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 ]] ; \ + then xmake_file=${cpu_type}/x-$rest; \ + else true; \ + fi + if [[ -f $srcdir/config/${cpu_type}/t-$rest ]] ; \ + then tmake_file=${cpu_type}/t-$rest; \ + else true; \ + fi + ;; + 1750a-*-*) + ;; + a29k-*-bsd* | a29k-*-sym1*) + tm_file="${tm_file} a29k/unix.h" + xm_defines=USG + xmake_file=a29k/x-unix + use_collect2=yes + ;; + a29k-*-udi | a29k-*-coff) + tm_file="${tm_file} dbxcoff.h a29k/udi.h" + tmake_file=a29k/t-a29kbare + ;; + a29k-wrs-vxworks*) + tm_file="${tm_file} dbxcoff.h a29k/udi.h a29k/vx29k.h" + tmake_file=a29k/t-vx29k + extra_parts="crtbegin.o crtend.o" + thread_file='vxworks' + ;; + a29k-*-*) # Default a29k environment. + use_collect2=yes + ;; + alpha*-*-linux-gnuecoff*) + tm_file="${tm_file} alpha/linux-ecoff.h alpha/linux.h" + target_cpu_default="MASK_GAS" + gas=no + xmake_file=none + gas=yes gnu_ld=yes + ;; + 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" + extra_parts="crtbegin.o crtend.o" + fixincludes=fixinc.wrap + xmake_file=none + gas=yes gnu_ld=yes + if [[ 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" + extra_parts="crtbegin.o crtend.o" + xmake_file=none + fixincludes=Makefile.in + gas=yes gnu_ld=yes + if [[ 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}" + target_cpu_default="MASK_GAS" + tmake_file="alpha/t-crtbe" + 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 + ;; + + alpha*-dec-osf*) + if [[ x$stabs = xyes ]] + then + tm_file="${tm_file} dbx.h" + fi + if [[ x$gas != xyes ]] + then + extra_passes="mips-tfile mips-tdump" + fi + use_collect2=yes + case $machine in + *-*-osf1*) + tm_file="${tm_file} alpha/osf.h alpha/osf12.h alpha/osf2or3.h" + ;; + *-*-osf[[23]]*) + tm_file="${tm_file} alpha/osf.h alpha/osf2or3.h" + ;; + *-*-osf4*) + tm_file="${tm_file} alpha/osf.h" + # Some versions of OSF4 (specifically X4.0-9 296.7) have + # a broken tar, so we use cpio instead. + install_headers_dir=install-headers-cpio + ;; + esac + case $machine in + *-*-osf4.0[[b-z]] | *-*-osf4.[[1-9]]*) + target_cpu_default=MASK_SUPPORT_ARCH + ;; + esac + ;; + alpha*-*-vxworks*) + tm_file="${tm_file} dbx.h alpha/vxworks.h" + if [ x$gas != xyes ] + then + extra_passes="mips-tfile mips-tdump" + fi + use_collect2=yes + ;; + alpha*-*-winnt*) + tm_file="${tm_file} alpha/win-nt.h" + xm_file="${xm_file} config/winnt/xm-winnt.h alpha/xm-winnt.h" + tmake_file=t-libc-ok + 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 ]] + then + extra_programs=ld.exe + fi + if [[ 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 + ;; + arc-*-elf*) + extra_parts="crtinit.o crtfini.o" + ;; + arm-*-coff* | armel-*-coff*) + tm_file=arm/coff.h + tmake_file=arm/t-bare + ;; + 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 ]] + then + tm_file=arm/rix-gas.h + else + tm_file=arm/riscix.h + fi + xmake_file=arm/x-riscix + tmake_file=arm/t-riscix + use_collect2=yes + ;; + 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}" + tmake_file="t-netbsd arm/t-netbsd" + # On NetBSD, the headers are already okay, except for math.h. + fixincludes=fixinc.wrap + ;; + arm-*-linux-gnuaout*) # ARM GNU/Linux + cpu_type=arm + xmake_file=x-linux + tm_file=arm/linux-gas.h + tmake_file=arm/t-linux + fixincludes=Makefile.in + gnu_ld=yes + ;; + arm-*-aout) + tm_file=arm/aout.h + tmake_file=arm/t-bare + ;; + 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 + ;; + clipper-intergraph-clix*) + tm_file="${tm_file} svr3.h clipper/clix.h" + xm_file=clipper/xm-clix.h + xmake_file=clipper/x-clix + extra_headers=va-clipper.h + extra_parts="crtbegin.o crtend.o" + install_headers_dir=install-headers-cpio + ;; + dsp16xx-*) + ;; + elxsi-elxsi-*) + use_collect2=yes + ;; +# This hasn't been upgraded to GCC 2. +# fx80-alliant-*) # Alliant FX/80 +# ;; + h8300-*-*) + float_format=i32 + ;; + hppa*-*-openbsd*) + target_cpu_default="MASK_SNAKE" + tmake_file=pa/t-openbsd + ;; + hppa1.1-*-pro*) + tm_file="pa/pa-pro.h ${tm_file} pa/pa-pro-end.h libgloss.h" + xm_file=pa/xm-papro.h + tmake_file=pa/t-pro + ;; + hppa1.1-*-osf*) + target_cpu_default=1 + 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" + xm_file=pa/xm-papro.h + tmake_file=pa/t-pro + ;; + hppa1.0-*-osf*) + tm_file="${tm_file} pa/pa-osf.h" + use_collect2=yes + fixincludes=Makefile.in + ;; + hppa1.1-*-bsd*) + target_cpu_default=1 + 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 ]] + then + tm_file="${tm_file} pa/gas.h" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.0-*-hpux8.0[[0-2]]*) + tm_file="${tm_file} pa/pa-hpux.h" + xm_file=pa/xm-pahpux.h + xmake_file=pa/x-pa-hpux + if [[ x$gas = xyes ]] + then + tm_file="${tm_file} pa/pa-gas.h" + else + tm_file="pa/pa-oldas.h ${tm_file}" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.1-*-hpux8.0[[0-2]]*) + target_cpu_default=1 + tm_file="${tm_file} pa/pa-hpux.h" + xm_file=pa/xm-pahpux.h + xmake_file=pa/x-pa-hpux + if [[ x$gas = xyes ]] + then + tm_file="${tm_file} pa/pa-gas.h" + else + tm_file="pa/pa-oldas.h ${tm_file}" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.1-*-hpux8*) + target_cpu_default=1 + tm_file="${tm_file} pa/pa-hpux.h" + xm_file=pa/xm-pahpux.h + xmake_file=pa/x-pa-hpux + if [[ x$gas = xyes ]] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.0-*-hpux8*) + tm_file="${tm_file} pa/pa-hpux.h" + xm_file=pa/xm-pahpux.h + xmake_file=pa/x-pa-hpux + if [[ 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 + 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 ]] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + if [[ x$enable_threads = x ]]; then + enable_threads=$have_pthread_h + fi + if [[ 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.0-*-hpux10*) + 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 ]] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + if [[ x$enable_threads = x ]]; then + enable_threads=$have_pthread_h + fi + if [[ 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 + 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 ]] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.0-*-hpux*) + 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 ]] + 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 + 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 ]] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa1.0-*-hiux*) + 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 ]] + then + tm_file="${tm_file} pa/pa-gas.h" + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + ;; + hppa*-*-lites*) + target_cpu_default=1 + use_collect2=yes + fixincludes=Makefile.in + ;; + i370-*-mvs*) + ;; + i[[34567]]86-ibm-aix*) # IBM PS/2 running AIX + if [[ x$gas = xyes ]] + then + tm_file=i386/aix386.h + extra_parts="crtbegin.o crtend.o" + tmake_file=i386/t-crtstuff + else + tm_file=i386/aix386ng.h + use_collect2=yes + fi + xm_file="xm-alloca.h i386/xm-aix.h ${xm_file}" + xm_defines=USG + xmake_file=i386/x-aix + ;; + 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 ]] + then + tm_file=i386/sysv4gdb.h + else + tm_file=i386/sysv4.h + fi + extra_parts="crtbegin.o crtend.o" + tmake_file=i386/t-crtpic + ;; + i[[34567]]86-next-*) + 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 + thread_file='mach' + fi + ;; + i[[34567]]86-sequent-bsd*) # 80386 from Sequent + use_collect2=yes + if [[ x$gas = xyes ]] + then + tm_file=i386/seq-gas.h + else + tm_file=i386/sequent.h + fi + ;; + i[[34567]]86-sequent-ptx1*) + 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*) + 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*) + 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 + xm_defines=USG + tm_file=i386/sun.h + use_collect2=yes + ;; + i[[34567]]86-wrs-vxworks*) + tm_file=i386/vxi386.h + tmake_file=i386/t-i386bare + ;; + i[[34567]]86-*-aout*) + tm_file=i386/i386-aout.h + tmake_file=i386/t-i386bare + ;; + i[[34567]]86-*-bsdi* | i[[34567]]86-*-bsd386*) + tm_file=i386/bsd386.h +# tmake_file=t-libc-ok + ;; + i[[34567]]86-*-bsd*) + 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 + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + tmake_file=i386/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 + ;; + 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 + ;; + 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 + ;; + i[[34567]]86-*-isc*) # 80386 running ISC system + xm_file="${xm_file} i386/xm-isc.h" + xm_defines="USG SVR3" + case $machine in + i[[34567]]86-*-isc[[34]]*) + xmake_file=i386/x-isc3 + ;; + *) + xmake_file=i386/x-isc + ;; + esac + if [[ x$gas = xyes -a x$stabs = xyes ]] + then + tm_file=i386/iscdbx.h + tmake_file=i386/t-svr3dbx + extra_parts="svr3.ifile svr3z.ifile" + else + tm_file=i386/isccoff.h + tmake_file=i386/t-crtstuff + extra_parts="crtbegin.o crtend.o" + fi + 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 + 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 + thread_file='posix' + fi + ;; + i[[34567]]86-*-gnu*) + 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 + ;; + i[[34567]]86-pc-msdosdjgpp*) + xm_file=i386/xm-go32.h + tm_file=i386/go32.h + tmake_file=i386/t-go32 + gnu_ld=yes + gas=yes + ;; + 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 ]] + then + tm_file=i386/lynx.h + else + tm_file=i386/lynx-ng.h + fi + xm_file=i386/xm-lynx.h + tmake_file=i386/t-i386bare + xmake_file=x-lynx + ;; + i[[34567]]86-*-mach*) + 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 ]] + then + tm_file=i386/osfelf.h + use_collect2= + else + tm_file=i386/osfrose.h + use_collect2=yes + fi + xm_file="i386/xm-osf.h ${xm_file}" + xmake_file=i386/x-osfrose + tmake_file=i386/t-osf + extra_objs=halfpic.o + ;; + i[[34567]]86-go32-rtems*) + 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*) + cpu_type=i386 + tm_file=i386/rtemself.h + tmake_file="i386/t-i386bare t-rtems" + ;; + i[[34567]]86-*-rtems*) + 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 + 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 ]] + then + tm_file="i386/sco5gas.h ${tm_file}" + tmake_file=i386/t-sco5gas + else + tmake_file=i386/t-sco5 + fi + extra_parts="crti.o crtbegin.o crtend.o crtbeginS.o crtendS.o" + ;; + i[[34567]]86-*-sco3.2v4*) # 80386 running SCO 3.2v4 system + 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 ]] + then + tm_file=i386/sco4dbx.h + tmake_file=i386/t-svr3dbx + extra_parts="svr3.ifile svr3z.rfile" + else + tm_file=i386/sco4.h + tmake_file=i386/t-crtstuff + extra_parts="crtbegin.o crtend.o" + fi + truncate_target=yes + ;; + i[[34567]]86-*-sco*) # 80386 running SCO system + xm_file=i386/xm-sco.h + xmake_file=i386/x-sco + install_headers_dir=install-headers-cpio + if [[ x$stabs = xyes ]] + then + tm_file=i386/scodbx.h + tmake_file=i386/t-svr3dbx + extra_parts="svr3.ifile svr3z.rfile" + else + tm_file=i386/sco.h + extra_parts="crtbegin.o crtend.o" + tmake_file=i386/t-crtstuff + fi + truncate_target=yes + ;; + 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 ]] + then + tm_file=i386/sol2dbg.h + else + tm_file=i386/sol2.h + fi + 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 + 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 ]] + 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 + ;; + 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 ]] + then + tm_file="${tm_file} dbx.h" + fi + tmake_file=i386/t-crtpic + xmake_file=x-svr4 + extra_parts="crtbegin.o crtend.o" + ;; + 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 ]] + then + tm_file=i386/osf1elfgdb.h + else + tm_file=i386/osf1elf.h + fi + tmake_file=i386/t-osf1elf + 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 + xm_defines="USG SVR3" + xmake_file=i386/x-sysv3 + if [[ x$gas = xyes ]] + then + if [[ x$stabs = xyes ]] + then + tm_file=i386/svr3dbx.h + tmake_file=i386/t-svr3dbx + extra_parts="svr3.ifile svr3z.rfile" + else + tm_file=i386/svr3gas.h + extra_parts="crtbegin.o crtend.o" + tmake_file=i386/t-crtstuff + fi + else + tm_file=i386/sysv3.h + extra_parts="crtbegin.o crtend.o" + tmake_file=i386/t-crtstuff + fi + ;; + i386-*-vsta) # Intel 80386's running VSTa kernel + xm_file="${xm_file} i386/xm-vsta.h" + tm_file=i386/vsta.h + 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 + extra_objs=winnt.o + fixincludes=Makefile.in + if [[ x$enable_threads = xyes ]]; then + thread_file='win32' + fi + exeext=.exe + ;; + 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" + extra_objs=winnt.o + xmake_file=i386/x-cygwin32 + fixincludes=Makefile.in + if [[ x$enable_threads = xyes ]]; then + thread_file='win32' + fi + exeext=.exe + case $machine in + *mingw32msv*) + ;; + *mingw32crt* | *mingw32*) + tm_file="${tm_file} i386/crtdll.h" + ;; + esac + ;; + i[[34567]]86-*-winnt3*) + tm_file=i386/win-nt.h + out_file=i386/i386.c + xm_file="xm-winnt.h ${xm_file}" + xmake_file=winnt/x-winnt + 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 ]] + then + extra_programs=ld.exe + fi + if [[ x$enable_threads = xyes ]]; then + thread_file='win32' + fi + ;; + i[[34567]]86-dg-dgux*) + 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 + tm_file="${tm_file} svr4.h i860/sysv4.h i860/fx2800.h" + xm_file="${xm_file}" + xmake_file=i860/x-fx2800 + tmake_file=i860/t-fx2800 + extra_parts="crtbegin.o crtend.o" + ;; + i860-*-bsd*) + tm_file="${tm_file} i860/bsd.h" + if [[ x$gas = xyes ]] + then + tm_file="${tm_file} i860/bsd-gas.h" + fi + use_collect2=yes + ;; + i860-*-mach*) + tm_file="${tm_file} i860/mach.h" + tmake_file=t-libc-ok + ;; + i860-*-osf*) # Intel Paragon XP/S, OSF/1AD + tm_file="${tm_file} svr3.h i860/paragon.h" + xm_defines="USG SVR3" + tmake_file=t-osf + ;; + i860-*-sysv3*) + tm_file="${tm_file} svr3.h i860/sysv3.h" + xm_defines="USG SVR3" + xmake_file=i860/x-sysv3 + extra_parts="crtbegin.o crtend.o" + ;; + i860-*-sysv4*) + tm_file="${tm_file} svr4.h i860/sysv4.h" + xm_defines="USG SVR3" + xmake_file=i860/x-sysv4 + tmake_file=t-svr4 + extra_parts="crtbegin.o crtend.o" + ;; + i960-wrs-vxworks5 | i960-wrs-vxworks5.0*) + tm_file="${tm_file} i960/vx960.h" + tmake_file=i960/t-vxworks960 + use_collect2=yes + thread_file='vxworks' + ;; + i960-wrs-vxworks5* | i960-wrs-vxworks) + tm_file="${tm_file} dbxcoff.h i960/i960-coff.h i960/vx960-coff.h" + tmake_file=i960/t-vxworks960 + use_collect2=yes + thread_file='vxworks' + ;; + i960-wrs-vxworks*) + tm_file="${tm_file} i960/vx960.h" + tmake_file=i960/t-vxworks960 + use_collect2=yes + thread_file='vxworks' + ;; + i960-*-coff*) + tm_file="${tm_file} dbxcoff.h i960/i960-coff.h libgloss.h" + tmake_file=i960/t-960bare + use_collect2=yes + ;; + i960-*-rtems) + tmake_file="i960/t-960bare t-rtems" + tm_file="${tm_file} dbxcoff.h i960/rtems.h" + use_collect2=yes + ;; + i960-*-*) # Default i960 environment. + use_collect2=yes + ;; + m32r-*-elf*) + extra_parts="crtinit.o crtfini.o" + ;; + m68000-convergent-sysv*) + tm_file=m68k/ctix.h + xm_file="m68k/xm-3b1.h ${xm_file}" + xm_defines=USG + use_collect2=yes + extra_headers=math-68881.h + ;; + m68000-hp-bsd*) # HP 9000/200 running BSD + tm_file=m68k/hp2bsd.h + xmake_file=m68k/x-hp2bsd + use_collect2=yes + extra_headers=math-68881.h + ;; + m68000-hp-hpux*) # HP 9000 series 300 + xm_file="xm_alloca.h ${xm_file}" + xm_defines="USG NO_SYS_SIGLIST" + if [[ x$gas = xyes ]] + then + xmake_file=m68k/x-hp320g + tm_file=m68k/hp310g.h + else + xmake_file=m68k/x-hp320 + tm_file=m68k/hp310.h + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + extra_headers=math-68881.h + ;; + m68000-sun-sunos3*) + tm_file=m68k/sun2.h + use_collect2=yes + extra_headers=math-68881.h + ;; + m68000-sun-sunos4*) + tm_file=m68k/sun2o4.h + use_collect2=yes + extra_headers=math-68881.h + ;; + m68000-att-sysv*) + xm_file="m68k/xm-3b1.h ${xm_file}" + xm_defines=USG + if [[ x$gas = xyes ]] + then + tm_file=m68k/3b1g.h + else + tm_file=m68k/3b1.h + fi + use_collect2=yes + extra_headers=math-68881.h + ;; + m68k-apple-aux*) # Apple Macintosh running A/UX + xm_defines="USG AUX" + tmake_file=m68k/t-aux + install_headers_dir=install-headers-cpio + extra_headers=math-68881.h + extra_parts="crt1.o mcrt1.o maccrt1.o crt2.o crtn.o" + tm_file= + if [[ "$gnu_ld" = yes ]] + then + tm_file="${tm_file} m68k/auxgld.h" + else + tm_file="${tm_file} m68k/auxld.h" + fi + if [[ "$gas" = yes ]] + then + tm_file="${tm_file} m68k/auxgas.h" + else + tm_file="${tm_file} m68k/auxas.h" + fi + tm_file="${tm_file} m68k/a-ux.h" + float_format=m68k + ;; + m68k-apollo-*) + tm_file=m68k/apollo68.h + xmake_file=m68k/x-apollo68 + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-altos-sysv*) # Altos 3068 + if [[ x$gas = xyes ]] + then + tm_file=m68k/altos3068.h + xm_defines=USG + else + echo "The Altos is supported only with the GNU assembler" 1>&2 + exit 1 + fi + extra_headers=math-68881.h + ;; + m68k-bull-sysv*) # Bull DPX/2 + if [[ x$gas = xyes ]] + then + if [[ x$stabs = xyes ]] + then + tm_file=m68k/dpx2cdbx.h + else + tm_file=m68k/dpx2g.h + fi + else + tm_file=m68k/dpx2.h + fi + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG + xmake_file=m68k/x-dpx2 + use_collect2=yes + extra_headers=math-68881.h + ;; + m68k-atari-sysv4*) # Atari variant of V.4. + tm_file=m68k/atari.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines="USG FULL_PROTOTYPES" + tmake_file=t-svr4 + extra_parts="crtbegin.o crtend.o" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-motorola-sysv*) + 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 ]] + then + xmake_file=m68k/x-mot3300-gas + if [[ x$gnu_ld = xyes ]] + then + tmake_file=m68k/t-mot3300-gald + else + tmake_file=m68k/t-mot3300-gas + use_collect2=yes + fi + else + xmake_file=m68k/x-mot3300 + if [[ x$gnu_ld = xyes ]] + then + tmake_file=m68k/t-mot3300-gld + else + tmake_file=m68k/t-mot3300 + use_collect2=yes + fi + fi + gdb_needs_out_file_path=yes + extra_parts="crt0.o mcrt0.o" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-ncr-sysv*) # NCR Tower 32 SVR3 + tm_file=m68k/tower-as.h + xm_defines="USG SVR3" + xmake_file=m68k/x-tower + extra_parts="crtbegin.o crtend.o" + extra_headers=math-68881.h + ;; + m68k-plexus-sysv*) + tm_file=m68k/plexus.h + xm_file="xm-alloca.h m68k/xm-plexus.h ${xm_file}" + xm_defines=USG + use_collect2=yes + extra_headers=math-68881.h + ;; + m68k-tti-*) + tm_file=m68k/pbb.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG + extra_headers=math-68881.h + ;; + m68k-crds-unos*) + xm_file="xm-alloca.h m68k/xm-crds.h ${xm_file}" + xm_defines="USG unos" + xmake_file=m68k/x-crds + tm_file=m68k/crds.h + use_collect2=yes + extra_headers=math-68881.h + ;; + m68k-cbm-sysv4*) # Commodore variant of V.4. + tm_file=m68k/amix.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines="USG FULL_PROTOTYPES" + xmake_file=m68k/x-amix + tmake_file=t-svr4 + extra_parts="crtbegin.o crtend.o" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-ccur-rtu) + tm_file=m68k/ccur-GAS.h + xmake_file=m68k/x-ccur + extra_headers=math-68881.h + use_collect2=yes + float_format=m68k + ;; + 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 + ;; + m68k-hp-bsd*) # HP 9000/3xx running Berkeley Unix + tm_file=m68k/hp3bsd.h + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-isi-bsd*) + if [[ x$with_fp = xno ]] + then + tm_file=m68k/isi-nfp.h + else + tm_file=m68k/isi.h + float_format=m68k + fi + use_collect2=yes + extra_headers=math-68881.h + ;; + 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 ]] + then + xmake_file=m68k/x-hp320g + tm_file=m68k/hp320g.h + else + xmake_file=m68k/x-hp320 + tm_file=m68k/hpux7.h + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-hp-hpux*) # HP 9000 series 300 + xm_file="xm_alloca.h ${xm_file}" + xm_defines="USG NO_SYS_SIGLIST" + if [[ x$gas = xyes ]] + then + xmake_file=m68k/x-hp320g + tm_file=m68k/hp320g.h + else + xmake_file=m68k/x-hp320 + tm_file=m68k/hp320.h + fi + install_headers_dir=install-headers-cpio + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-sun-mach*) + tm_file=m68k/sun3mach.h + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-sony-newsos3*) + if [[ x$gas = xyes ]] + then + tm_file=m68k/news3gas.h + else + tm_file=m68k/news3.h + fi + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-sony-bsd* | m68k-sony-newsos*) + if [[ x$gas = xyes ]] + then + tm_file=m68k/newsgas.h + else + tm_file=m68k/news.h + fi + use_collect2=yes + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-next-nextstep2*) + tm_file=m68k/next21.h + xm_file="m68k/xm-next.h ${xm_file}" + tmake_file=m68k/t-next + xmake_file=m68k/x-next + extra_objs=nextstep.o + extra_headers=math-68881.h + use_collect2=yes + float_format=m68k + ;; + m68k-next-nextstep3*) + tm_file=m68k/next.h + xm_file="m68k/xm-next.h ${xm_file}" + tmake_file=m68k/t-next + xmake_file=m68k/x-next + extra_objs=nextstep.o + extra_headers=math-68881.h + float_format=m68k + if [[ x$enable_threads = xyes ]]; then + thread_file='mach' + fi + ;; + m68k-sun-sunos3*) + if [[ x$with_fp = xno ]] + then + tm_file=m68k/sun3n3.h + else + tm_file=m68k/sun3o3.h + float_format=m68k + fi + use_collect2=yes + extra_headers=math-68881.h + ;; + m68k-sun-sunos*) # For SunOS 4 (the default). + if [[ x$with_fp = xno ]] + then + tm_file=m68k/sun3n.h + else + tm_file=m68k/sun3.h + float_format=m68k + fi + use_collect2=yes + extra_headers=math-68881.h + ;; + m68k-wrs-vxworks*) + tm_file=m68k/vxm68k.h + tmake_file=m68k/t-vxworks68 + extra_headers=math-68881.h + thread_file='vxworks' + float_format=m68k + ;; + m68k-*-aout*) + tmake_file=m68k/t-m68kbare + tm_file="m68k/m68k-aout.h libgloss.h" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-*-coff*) + tmake_file=m68k/t-m68kbare + tm_file="m68k/m68k-coff.h dbx.h libgloss.h" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-*-lynxos*) + if [[ x$gas = xyes ]] + then + tm_file=m68k/lynx.h + else + tm_file=m68k/lynx-ng.h + fi + xm_file=m68k/xm-lynx.h + xmake_file=x-lynx + tmake_file=m68k/t-lynx + extra_headers=math-68881.h + float_format=m68k + ;; + 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 + ;; + m68k*-*-openbsd*) + float_format=m68k + # we need collect2 until our bug is fixed... + use_collect2=yes + ;; + m68k-*-sysv3*) # Motorola m68k's running system V.3 + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG + xmake_file=m68k/x-m68kv + extra_parts="crtbegin.o crtend.o" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-*-sysv4*) # Motorola m68k's running system V.4 + tm_file=m68k/m68kv4.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG + tmake_file=t-svr4 + extra_parts="crtbegin.o crtend.o" + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-*-linux-gnuaout*) # Motorola m68k's running GNU/Linux + # with a.out format + 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 + ;; + m68k-*-linux-gnulibc1) # Motorola m68k's running GNU/Linux + # with ELF format using the + # GNU/Linux C library 5 + xmake_file=x-linux + 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 + ;; + m68k-*-linux-gnu*) # Motorola m68k's running GNU/Linux + # with ELF format using glibc 2 + # aka the GNU/Linux C library 6. + xmake_file=x-linux + 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 + thread_file='posix' + fi + ;; + m68k-*-psos*) + tmake_file=m68k/t-m68kbare + tm_file=m68k/m68k-psos.h + extra_headers=math-68881.h + float_format=m68k + ;; + m68k-*-rtems*) + tmake_file="m68k/t-m68kbare t-rtems" + tm_file=m68k/rtems.h + extra_headers=math-68881.h + float_format=m68k + ;; + + m88k-dg-dgux*) + case $machine in + m88k-dg-dguxbcs*) + tm_file=m88k/dguxbcs.h + tmake_file=m88k/t-dguxbcs + ;; + *) + tm_file=m88k/dgux.h + tmake_file=m88k/t-dgux + ;; + esac + extra_parts="crtbegin.o bcscrtbegin.o crtend.o m88kdgux.ld" + xmake_file=m88k/x-dgux + if [[ 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 ]] + then + tmake_file=m88k/t-m88k-gas + fi + ;; + m88k-tektronix-sysv3) + tm_file=m88k/tekXD88.h + extra_parts="crtbegin.o crtend.o" + xm_file="m88k/xm-sysv3.h ${xm_file}" + xmake_file=m88k/x-tekXD88 + if [[ x$gas = xyes ]] + then + tmake_file=m88k/t-m88k-gas + fi + ;; + m88k-*-aout*) + tm_file=m88k/m88k-aout.h + ;; + m88k-*-coff*) + tm_file=m88k/m88k-coff.h + tmake_file=m88k/t-bug + ;; + m88k-*-luna*) + tm_file=m88k/luna.h + extra_parts="crtbegin.o crtend.o" + if [[ x$gas = xyes ]] + then + tmake_file=m88k/t-luna-gas + else + tmake_file=m88k/t-luna + fi + ;; + m88k-*-openbsd*) + tmake_file="${tmake_file} m88k/t-luna-gas" + ;; + m88k-*-sysv3*) + tm_file=m88k/sysv3.h + extra_parts="crtbegin.o crtend.o" + xm_file="m88k/xm-sysv3.h ${xm_file}" + xmake_file=m88k/x-sysv3 + if [[ x$gas = xyes ]] + then + tmake_file=m88k/t-m88k-gas + fi + ;; + m88k-*-sysv4*) + tm_file=m88k/sysv4.h + extra_parts="crtbegin.o crtend.o" + xmake_file=m88k/x-sysv4 + tmake_file=m88k/t-sysv4 + ;; + 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 + ;; + mips-wrs-vxworks) + tm_file="mips/elf.h libgloss.h" + tmake_file=mips/t-ecoff + gas=yes + gnu_ld=yes + extra_parts="crtbegin.o crtend.o" +# 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 + ;; + mips-sni-sysv4) + if [[ x$gas = xyes ]] + then + if [[ x$stabs = xyes ]] + then + tm_file=mips/iris5gdb.h + else + tm_file="mips/sni-svr4.h mips/sni-gas.h" + fi + else + tm_file=mips/sni-svr4.h + fi + xm_defines=USG + xmake_file=mips/x-sni-svr4 + tmake_file=mips/t-mips-gas + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + ;; + mips-sgi-irix5*) # SGI System V.4., IRIX 5 + if [[ x$gas = xyes ]] + then + tm_file="mips/iris5.h mips/iris5gas.h" + if [[ x$stabs = xyes ]] + then + tm_file="${tm_file} dbx.h" + fi + else + tm_file=mips/iris5.h + 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 + ;; + 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 + tm_file="${tm_file} dbx.h" + fi + xm_defines=USG + xmake_file=mips/x-iris + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + if [[ x$enable_threads = xyes ]]; then +: not ported yet 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 + tm_file="${tm_file} dbx.h" + fi + xm_defines=USG + xmake_file=mips/x-iris + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + if [[ x$enable_threads = xyes ]]; then +: not ported yet thread_file='irix' + fi + ;; + mips-sgi-*) # Mostly like a MIPS. + tm_file="mips/iris3.h ${tm_file}" + if [[ x$stabs = xyes ]]; then + tm_file="${tm_file} dbx.h" + fi + xm_defines=USG + xmake_file=mips/x-iris3 + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + ;; + mips-dec-osfrose*) # Decstation running OSF/1 reference port with OSF/rose. + tm_file="mips/osfrose.h ${tm_file}" + xmake_file=mips/x-osfrose + tmake_file=mips/t-osfrose + extra_objs=halfpic.o + use_collect2=yes + ;; + mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL + tm_file=mips/dec-osf1.h + if [[ x$stabs = xyes ]]; then + tm_file="${tm_file} dbx.h" + fi + xmake_file=mips/x-dec-osf1 + if [[ 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 ]] + then + use_collect2=yes + fi + ;; + mips-dec-bsd*) # Decstation running 4.4 BSD + tm_file=mips/dec-bsd.h + fixincludes= + if [[ 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 ]] + 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*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 + tm_file="${tm_file} dbx.h" + fi + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + xmake_file=mips/x-sony + ;; + mips-sony-sysv*) # Sony NEWS 3800 with NEWSOS5.0. + # 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 + tm_file="${tm_file} dbx.h" + fi + xm_file="xm-siglist.h ${xm_file}" + xm_defines=USG + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ 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 + 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 ]] + then + tmake_file=mips/t-mips-gas + extra_parts="crtbegin.o crtend.o" + else + tmake_file=mips/t-mips + extra_passes="mips-tfile mips-tdump" + fi + if [[ 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 + tm_file="${tm_file} dbx.h" + fi + xmake_file=mips/x-ultrix + if [[ 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 ]] + 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 + tm_file="${tm_file} dbx.h" + fi + if [[ 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 ]] + 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 + tm_file="${tm_file} dbx.h" + fi + if [[ 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 ]] + 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 + tm_file="${tm_file} dbx.h" + fi + xm_file="xm-siglist.h ${xm_file}" + xmake_file=mips/x-sysv + if [[ 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 ]] + 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 + tm_file="${tm_file} dbx.h" + fi + xm_defines=USG + xmake_file=mips/x-sysv + if [[ 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 ]] + 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 + tm_file="${tm_file} dbx.h" + fi + xm_defines=USG + xmake_file=mips/x-sysv + if [[ 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 ]] + then + use_collect2=yes + fi + ;; + mips-*-sysv* | mips-*-riscos*sysv*) + tm_file="mips/svr3-4.h ${tm_file}" + if [[ x$stabs = xyes ]]; then + tm_file="${tm_file} dbx.h" + fi + xm_defines=USG + xmake_file=mips/x-sysv + if [[ 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 ]] + 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 + tm_file="${tm_file} dbx.h" + fi + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + ;; + mips-*-gnu*) + ;; + mipsel-*-ecoff*) + tm_file=mips/ecoffl.h + if [[ 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 + 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 + ;; + mips-*-elf*) + tm_file="mips/elf.h libgloss.h" + tmake_file=mips/t-ecoff + ;; + mips64el-*-elf*) + tm_file="mips/elfl64.h libgloss.h" + tmake_file=mips/t-ecoff + ;; + mips64orionel-*-elf*) + tm_file="mips/elforion.h mips/elfl64.h libgloss.h" + tmake_file=mips/t-ecoff + ;; + mips64-*-elf*) + tm_file="mips/elf64.h libgloss.h" + tmake_file=mips/t-ecoff + ;; + mips64orion-*-elf*) + tm_file="mips/elforion.h mips/elf64.h libgloss.h" + tmake_file=mips/t-ecoff + ;; + 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" + tmake_file=mips/t-r3900 + ;; + mipstx39-*-elf*) + tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h" + tmake_file=mips/t-r3900 + ;; + mips-*-*) # Default MIPS RISC-OS 4.0. + if [[ x$stabs = xyes ]]; then + tm_file="${tm_file} dbx.h" + fi + if [[ x$gas = xyes ]] + then + tmake_file=mips/t-mips-gas + else + extra_passes="mips-tfile mips-tdump" + fi + if [[ x$gnu_ld != xyes ]] + then + use_collect2=yes + fi + ;; + mn10200-*-*) + cpu_type=mn10200 + tm_file="mn10200/mn10200.h" + if [[ x$stabs = xyes ]] + then + tm_file="${tm_file} dbx.h" + fi + use_collect2=no + ;; + mn10300-*-*) + cpu_type=mn10300 + tm_file="mn10300/mn10300.h" + if [[ x$stabs = xyes ]] + then + tm_file="${tm_file} dbx.h" + fi + use_collect2=no + ;; + ns32k-encore-bsd*) + tm_file=ns32k/encore.h + use_collect2=yes + ;; + ns32k-sequent-bsd*) + tm_file=ns32k/sequent.h + use_collect2=yes + ;; + ns32k-tek6100-bsd*) + tm_file=ns32k/tek6100.h + use_collect2=yes + ;; + ns32k-tek6200-bsd*) + tm_file=ns32k/tek6200.h + use_collect2=yes + ;; +# This has not been updated to GCC 2. +# ns32k-ns-genix*) +# xm_defines=USG +# xmake_file=ns32k/x-genix +# tm_file=ns32k/genix.h +# use_collect2=yes +# ;; + ns32k-merlin-*) + tm_file=ns32k/merlin.h + use_collect2=yes + ;; + ns32k-pc532-mach*) + tm_file=ns32k/pc532-mach.h + use_collect2=yes + ;; + ns32k-pc532-minix*) + tm_file=ns32k/pc532-min.h + xm_file="ns32k/xm-pc532-min.h ${xm-file}" + xm_defines=USG + use_collect2=yes + ;; + ns32k-*-netbsd*) + tm_file=ns32k/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 + ;; + pdp11-*-bsd) + tm_file="${tm_file} pdp11/2bsd.h" + ;; + pdp11-*-*) + ;; + ns32k-*-openbsd*) + # Nothing special + ;; + pyramid-*-*) + cpu_type=pyr + xmake_file=pyr/x-pyr + use_collect2=yes + ;; + romp-*-aos*) + use_collect2=yes + ;; + romp-*-mach*) + xmake_file=romp/x-mach + use_collect2=yes + ;; + romp-*-openbsd*) + # Nothing special + ;; + powerpc-*-openbsd*) + tmake_file="${tmake_file} rs6000/t-rs6000 rs6000/t-openbsd" + xmake_file=none + ;; + powerpc-*-beos*) + cpu_type=rs6000 + tm_file=rs6000/beos.h + xm_file=rs6000/xm-beos.h + tmake_file=rs6000/t-beos + xmake_file=rs6000/x-beos + ;; + powerpc-*-sysv* | powerpc-*-elf*) + tm_file=rs6000/sysv4.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + extra_headers=ppc-asm.h + if [[ 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 + ;; + 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 ]] + 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 ]] + 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 ]] + 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 + thread_file='posix' + fi + ;; + powerpc-*-linux-gnu*) + tm_file=rs6000/linux.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG ${xm_defines}" + out_file=rs6000/rs6000.c + if [[ 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 + thread_file='posix' + fi + ;; + powerpc-wrs-vxworks*) + cpu_type=rs6000 + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + tm_file=rs6000/vxppc.h + tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm" + extra_headers=ppc-asm.h + thread_file='vxworks' + ;; + powerpcle-*-sysv* | powerpcle-*-elf*) + tm_file=rs6000/sysv4le.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + if [[ 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 + extra_headers=ppc-asm.h + ;; + 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 ]] + 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 + 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}" + tmake_file=rs6000/t-winnt + xmake_file=rs6000/x-cygwin32 +# extra_objs=pe.o + fixincludes=Makefile.in + if [[ x$enable_threads = xyes ]]; then + thread_file='win32' + fi + exeext=.exe + extra_headers=ppc-asm.h + ;; + powerpcle-*-solaris2*) + tm_file=rs6000/sol2.h + xm_file="xm-siglist.h rs6000/xm-sysv4.h" + xm_defines="USG POSIX" + if [[ 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 + use_collect2=yes + ;; + rs6000-ibm-aix3.2.[[456789]]* | powerpc-ibm-aix3.2.[[456789]]*) + tm_file=rs6000/aix3newas.h + if [[ x$host != x$target ]] + then + tmake_file=rs6000/t-xnewas + else + tmake_file=rs6000/t-newas + fi + use_collect2=yes + ;; + rs6000-ibm-aix4.[[12]]* | powerpc-ibm-aix4.[[12]]*) + tm_file=rs6000/aix41.h + if [[ x$host != x$target ]] + then + tmake_file=rs6000/t-xnewas + else + tmake_file=rs6000/t-newas + fi + xmake_file=rs6000/x-aix41 + use_collect2=yes + ;; + rs6000-ibm-aix4.[[3456789]].* | powerpc-ibm-aix4.[[3456789]].*) + tm_file=rs6000/aix43.h + if [[ x$host != x$target ]] + then + tmake_file=rs6000/t-xaix43 + else + tmake_file=rs6000/t-aix43 + fi + xmake_file=rs6000/x-aix43 + use_collect2=yes + ;; + rs6000-ibm-aix[[56789]].* | powerpc-ibm-aix[[56789]].*) + tm_file=rs6000/aix43.h + if [[ x$host != x$target ]] + then + tmake_file=rs6000/t-xaix43 + else + tmake_file=rs6000/t-aix43 + fi + xmake_file=rs6000/x-aix43 + use_collect2=yes + ;; + rs6000-ibm-aix*) + use_collect2=yes + ;; + rs6000-bull-bosx) + use_collect2=yes + ;; + rs6000-*-mach*) + tm_file=rs6000/mach.h + xm_file="${xm_file} rs6000/xm-mach.h" + xmake_file=rs6000/x-mach + use_collect2=yes + ;; + rs6000-*-lynxos*) + tm_file=rs6000/lynx.h + xm_file=rs6000/xm-lynx.h + tmake_file=rs6000/t-rs6000 + xmake_file=rs6000/x-lynx + use_collect2=yes + ;; + sh-*-elf*) + tm_file=sh/elf.h + float_format=sh + ;; + sh-*-rtemself*) + tmake_file="sh/t-sh t-rtems" + tm_file=sh/rtemself.h + float_format=sh + ;; + sh-*-rtems*) + tmake_file="sh/t-sh t-rtems" + tm_file=sh/rtems.h + float_format=sh + ;; + sh-*-*) + float_format=sh + ;; + sparc-tti-*) + tm_file=sparc/pbd.h + xm_file="xm-alloca.h ${xm_file}" + xm_defines=USG + ;; + sparc-wrs-vxworks* | sparclite-wrs-vxworks*) + tm_file=sparc/vxsparc.h + tmake_file=sparc/t-vxsparc + use_collect2=yes + thread_file='vxworks' + ;; + sparc-*-aout*) + tmake_file=sparc/t-sparcbare + tm_file="sparc/aout.h libgloss.h" + ;; + 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 + ;; + sparc-*-openbsd*) + # we need collect2 until our bug is fixed... + use_collect2=yes + ;; + sparc-*-bsd*) + tm_file=sparc/bsd.h + ;; + sparc-*-elf*) + tm_file=sparc/elf.h + tmake_file=sparc/t-elf + extra_parts="crti.o crtn.o crtbegin.o crtend.o" + #float_format=i128 + float_format=i64 + ;; + sparc-*-linux-gnuaout*) # Sparc's running GNU/Linux, a.out + 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 + xm_file="${xm_file} sparc/xm-linux.h" + xmake_file=x-linux + 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 + xm_file="${xm_file} sparc/xm-linux.h" + xmake_file=x-linux + 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 + thread_file='posix' + fi + ;; + sparc-*-lynxos*) + if [[ x$gas = xyes ]] + then + tm_file=sparc/lynx.h + else + tm_file=sparc/lynx-ng.h + fi + xm_file=sparc/xm-lynx.h + tmake_file=sparc/t-sunos41 + xmake_file=x-lynx + ;; + sparc-*-rtems*) + tmake_file="sparc/t-sparcbare t-rtems" + tm_file=sparc/rtems.h + ;; + sparc-*-solaris2*) + if [[ x$gnu_ld = xyes ]] + then + tm_file=sparc/sol2.h + else + tm_file=sparc/sol2-sld.h + fi + xm_file="xm-siglist.h sparc/xm-sysv4.h sparc/xm-sol2.h" + xm_defines="USG POSIX" + tmake_file=sparc/t-sol2 + 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;; + *) + fixincludes=fixinc.wrap;; + esac + float_format=i128 + if [[ x${enable_threads} = x ]]; then + enable_threads=$have_pthread_h + if [[ 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 + thread_file='posix' + else + thread_file='solaris' + fi + fi + ;; + sparc-*-sunos4.0*) + tm_file=sparc/sunos4.h + tmake_file=sparc/t-sunos40 + use_collect2=yes + ;; + sparc-*-sunos4*) + tm_file=sparc/sunos4.h + tmake_file=sparc/t-sunos41 + use_collect2=yes + if [[ x$gas = xyes ]]; then + tm_file="${tm_file} sparc/sun4gas.h" + fi + ;; + sparc-*-sunos3*) + tm_file=sparc/sun4o3.h + use_collect2=yes + ;; + sparc-*-sysv4*) + tm_file=sparc/sysv4.h + xm_file="xm-siglist.h sparc/xm-sysv4.h" + xm_defines="USG POSIX" + tmake_file=t-svr4 + xmake_file=sparc/x-sysv4 + extra_parts="crtbegin.o crtend.o" + ;; + sparc-*-vxsim*) + xm_file="xm-siglist.h sparc/xm-sysv4.h sparc/xm-sol2.h" + xm_defines="USG POSIX" + tm_file=sparc/vxsim.h + tmake_file=sparc/t-vxsparc + xmake_file=sparc/x-sysv4 + ;; + sparclet-*-aout*) + tm_file="sparc/splet.h libgloss.h" + tmake_file=sparc/t-splet + ;; + sparclite-*-coff*) + tm_file="sparc/litecoff.h libgloss.h" + tmake_file=sparc/t-sparclite + ;; + sparclite-*-aout*) + tm_file="sparc/lite.h aoutos.h libgloss.h" + tmake_file=sparc/t-sparclite + ;; + sparc64-*-aout*) + tmake_file=sparc/t-sp64 + tm_file=sparc/sp64-aout.h + ;; + sparc64-*-elf*) + tmake_file=sparc/t-sp64 + tm_file=sparc/sp64-elf.h + extra_parts="crtbegin.o crtend.o" + ;; + sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux + tmake_file=sparc/t-sp64 + 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. + gnu_ld=yes + ;; +# This hasn't been upgraded to GCC 2. +# tahoe-harris-*) # Harris tahoe, using COFF. +# tm_file=tahoe/harris.h +# ;; +# tahoe-*-bsd*) # tahoe running BSD +# ;; + thumb-*-coff* | thumbel-*-coff*) + 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 + fixincludes=Makefile.in # There is nothing to fix + ;; +# This hasn't been upgraded to GCC 2. +# tron-*-*) +# cpu_type=gmicro +# use_collect2=yes +# ;; + v850-*-*) + cpu_type=v850 + tm_file="v850/v850.h" + xm_file="v850/xm-v850.h" + tmake_file=v850/t-v850 + if [[ x$stabs = xyes ]] + then + tm_file="${tm_file} dbx.h" + fi + use_collect2=no + ;; + vax-*-bsd*) # vaxen running BSD + use_collect2=yes + float_format=vax + ;; + vax-*-sysv*) # vaxen running system V + tm_file="${tm_file} vax/vaxv.h" + xm_defines=USG + float_format=vax + ;; + 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 + ;; + vax-*-openbsd*) + tmake_file="${tm_file} vax/t-openbsd" + ;; + vax-*-ultrix*) # vaxen running ultrix + tm_file="${tm_file} vax/ultrix.h" + use_collect2=yes + float_format=vax + ;; + vax-*-vms*) # vaxen running VMS + xm_file=vax/xm-vms.h + tm_file=vax/vms.h + float_format=vax + ;; + vax-*-*) # vax default entry + float_format=vax + ;; + we32k-att-sysv*) + xm_file="${xm_file} xm-svr3" + use_collect2=yes + ;; + *) + echo "Configuration $machine not supported" 1>&2 + exit 1 + ;; + esac + + case $machine in + *-*-linux-gnu*) + ;; # Existing GNU/Linux systems do not use the GNU setup. + *-*-gnu*) + # On the GNU system, the setup is just about the same on + # each different CPU. The specific machines that GNU + # supports are matched above and just set $cpu_type. + xm_file="xm-gnu.h ${xm_file}" + tm_file=${cpu_type}/gnu.h + extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" + # GNU always uses ELF. + elf=yes + # 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 + ;; + *-*-sysv*) + install_headers_dir=install-headers-cpio + ;; + esac + + # Distinguish i[34567]86 + # Also, do not run mips-tfile on MIPS if using gas. + # Process --with-cpu= for PowerPC/rs6000 + target_cpu_default2= + case $machine in + i486-*-*) + target_cpu_default2=1 + ;; + i586-*-*) + target_cpu_default2=2 + ;; + i686-*-* | i786-*-*) + target_cpu_default2=3 + ;; + alpha*-*-*) + case $machine in + alphaev6*) + target_cpu_default2="MASK_CPU_EV6|MASK_BWX|MASK_CIX|MASK_MAX" + ;; + alphapca56*) + target_cpu_default2="MASK_CPU_EV5|MASK_BWX|MASK_MAX" + ;; + alphaev56*) + target_cpu_default2="MASK_CPU_EV5|MASK_BWX" + ;; + alphaev5*) + target_cpu_default2="MASK_CPU_EV5" + ;; + esac + + if [[ x$gas = xyes ]] + then + if [[ "$target_cpu_default2" = "" ]] + then + target_cpu_default2="MASK_GAS" + else + target_cpu_default2="${target_cpu_default2}|MASK_GAS" + fi + fi + ;; + arm*-*-*) + case "x$with_cpu" in + x) + # The most generic + target_cpu_default2="TARGET_CPU_generic" + ;; + + # Distinguish cores, and major variants + # arm7m doesn't exist, but D & I don't affect code + xarm[23678] | xarm250 | xarm[67][01]0 \ + | xarm7m | xarm7dm | xarm7dmi | xarm7tdmi \ + | xarm7100 | xarm7500 | xarm7500fe | xarm810 \ + | xstrongarm | xstrongarm110) + target_cpu_default2="TARGET_CPU_$with_cpu" + ;; + + xyes | xno) + echo "--with-cpu must be passed a value" 1>&2 + exit 1 + ;; + + *) + if [[ x$pass2done = xyes ]] + then + echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2 + exit 1 + fi + ;; + esac + ;; + + mips*-*-ecoff* | mips*-*-elf*) + if [[ x$gas = xyes ]] + then + if [[ x$gnu_ld = xyes ]] + then + target_cpu_default2=20 + else + target_cpu_default2=16 + fi + fi + ;; + mips*-*-*) + if [[ x$gas = xyes ]] + then + target_cpu_default2=16 + fi + ;; + powerpc*-*-* | rs6000-*-*) + case "x$with_cpu" in + x) + ;; + + xcommon | xpower | xpower2 | xpowerpc | xrios \ + | xrios1 | xrios2 | xrsc | xrsc1 \ + | x601 | x602 | x603 | x603e | x604 | x604e | x620 \ + | x403 | x505 | x801 | x821 | x823 | x860) + target_cpu_default2="\"$with_cpu\"" + ;; + + xyes | xno) + echo "--with-cpu must be passed a value" 1>&2 + exit 1 + ;; + + *) + if [[ x$pass2done = xyes ]] + then + echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2 + exit 1 + fi + ;; + esac + ;; + sparc*-*-*) + case ".$with_cpu" in + .) + target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`" + ;; + .supersparc | .ultrasparc | .v7 | .v8 | .v9) + target_cpu_default2="TARGET_CPU_$with_cpu" + ;; + *) + if [[ x$pass2done = xyes ]] + then + echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2 + exit 1 + fi + ;; + esac + ;; + esac + + if [[ "$target_cpu_default2" != "" ]] + then + if [[ "$target_cpu_default" != "" ]] + then + target_cpu_default="(${target_cpu_default}|${target_cpu_default2})" + else + target_cpu_default=$target_cpu_default2 + fi + fi + + # No need for collect2 if we have the GNU linker. + # Actually, there is now; GNU ld doesn't handle the EH info or + # collecting for shared libraries. + #case x$gnu_ld in + #xyes) + # use_collect2= + # ;; + #esac + +# 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 ]] + then + if [[ x"$xm_file" = x ]] + then build_xm_file=$cpu_type/xm-$cpu_type.h + else build_xm_file=$xm_file + fi + build_xm_defines=$xm_defines + build_install_headers_dir=$install_headers_dir + build_exeext=$exeext + pass1done=yes + else + if [[ x$pass2done = x ]] + then + if [[ 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 ]] + then xmake_file=$cpu_type/x-$cpu_type + fi + host_xmake_file="$xmake_file" + host_truncate_target=$truncate_target + host_extra_gcc_objs=$extra_gcc_objs + host_extra_objs=$extra_host_objs + host_exeext=$exeext + pass2done=yes + fi + fi +done + +extra_objs="${host_extra_objs} ${extra_objs}" + +# Default the target-machine variables that were not explicitly set. +if [[ x"$tm_file" = x ]] +then tm_file=$cpu_type/$cpu_type.h; fi + +if [[ x$extra_headers = x ]] +then extra_headers=; fi + +if [[ x"$xm_file" = x ]] +then xm_file=$cpu_type/xm-$cpu_type.h; fi + +if [[ x$md_file = x ]] +then md_file=$cpu_type/$cpu_type.md; fi + +if [[ x$out_file = x ]] +then out_file=$cpu_type/$cpu_type.c; fi + +if [[ x"$tmake_file" = x ]] +then tmake_file=$cpu_type/t-$cpu_type +fi + +if [[ x$float_format = x ]] +then float_format=i64 +fi + +if [[ x$enable_haifa = x ]] +then + case $target in + alpha*-* | hppa1.?-* | powerpc*-* | rs6000-* | *sparc*-* | m32r*-*) + enable_haifa=yes;; + esac +fi + +# Handle cpp installation. +if [[ x$enable_cpp != x ]] +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. +echo "Using \`$srcdir/config/$out_file' to output insns." +echo "Using \`$srcdir/config/$md_file' as machine description file." + +count=a +for f in $tm_file; do + count=${count}x +done +if [[ $count = ax ]]; then + echo "Using \`$srcdir/config/$tm_file' as target machine macro file." +else + echo "Using the following target machine macro files:" + for f in $tm_file; do + echo " $srcdir/config/$f" + done +fi + +count=a +for f in $host_xm_file; do + count=${count}x +done +if [[ $count = ax ]]; then + echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file." +else + echo "Using the following host machine macro files:" + for f in $host_xm_file; do + echo " $srcdir/config/$f" + done +fi + +if [[ "$host_xm_file" != "$build_xm_file" ]]; then + count=a + for f in $build_xm_file; do + count=${count}x + done + if [[ $count = ax ]]; then + echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file." + else + echo "Using the following build machine macro files:" + for f in $build_xm_file; do + echo " $srcdir/config/$f" + done + fi +fi + +if [[ x$thread_file = x ]]; then + if [[ x$target_thread_file != x ]]; then + thread_file=$target_thread_file + else + thread_file='single' + fi +fi + +# Set up the header files. +# $links is the list of header files to create. +# $vars is the list of shell variables with file names to include. +# 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}" + +# 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 ]] +then + build_xm_file="auto-host.h ${build_xm_file}" +else + # We create a subdir, then run autoconf in the subdir. + # To prevent recursion we set host and build for the new + # invocation of configure to the build for this invocation + # of configure. + tempdir=build.$$ + rm -rf $tempdir + mkdir $tempdir + cd $tempdir + case ${srcdir} in + /*) realsrcdir=${srcdir};; + *) realsrcdir=../${srcdir};; + esac + CC=${CC_FOR_BUILD} ${realsrcdir}/configure \ + --target=$target --host=$build --build=$build + + # We just finished tests for the build machine, so rename + # the file auto-build.h in the gcc directory. + mv auto-host.h ../auto-build.h + cd .. + rm -rf $tempdir + build_xm_file="auto-build.h ${build_xm_file}" +fi + +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 + +# Make the links. +while [[ -n "$vars" ]] +do + set $vars; var=$1; shift; vars=$* + set $links; link=$1; shift; links=$* + set $defines; define=$1; shift; defines=$* + + rm -f $link + + # Define TARGET_CPU_DEFAULT if the system wants one. + # This substitutes for lots of *.h files. + if [[ "$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 + echo "#include \"$file\"" >>$link + done + + for def in `eval echo '$'$define`; do + echo "#ifndef $def" >>$link + echo "#define $def" >>$link + echo "#endif" >>$link + done +done + +# Truncate the target if necessary +if [[ 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 + gcc_version_trigger=$with_gcc_version_trigger +else + gcc_version_trigger=${srcdir}/version.c +fi +gcc_version=`sed -e 's/.*\"\([[^ \"]]*\)[[ \"]].*/\1/' < ${gcc_version_trigger}` + +# Get an absolute path to the GCC top-level source directory +holddir=`pwd` +cd $srcdir +topdir=`pwd` +cd $holddir + +# Conditionalize the makefile for this host machine. +# Make-host contains the concatenation of all host makefile fragments +# [there can be more than one]. This file is built by configure.frag. +host_overrides=Make-host +dep_host_xmake_file= +for f in .. ${host_xmake_file} +do + if [[ -f ${srcdir}/config/$f ]] + then + dep_host_xmake_file="${dep_host_xmake_file} ${srcdir}/config/$f" + fi +done + +# Conditionalize the makefile for this target machine. +# Make-target contains the concatenation of all host makefile fragments +# [there can be more than one]. This file is built by configure.frag. +target_overrides=Make-target +dep_tmake_file= +for f in .. ${tmake_file} +do + if [[ -f ${srcdir}/config/$f ]] + then + dep_tmake_file="${dep_tmake_file} ${srcdir}/config/$f" + fi +done + +# If the host doesn't support symlinks, modify CC in +# FLAGS_TO_PASS so CC="stage1/xgcc -Bstage1/" works. +# Otherwise, we can use "CC=$(CC)". +rm -f symtest.tem +if $symbolic_link $srcdir/gcc.c symtest.tem 2>/dev/null +then + cc_set_by_configure="\$(CC)" + stage_prefix_set_by_configure="\$(STAGE_PREFIX)" +else + rm -f symtest.tem + if cp -p $srcdir/gcc.c symtest.tem 2>/dev/null + then + symbolic_link="cp -p" + else + symbolic_link="cp" + fi + 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 + +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" +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 +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 +done + +# Define macro CROSS_COMPILE in compilation +# if this is a cross-compiler. +# Also use all.cross instead of all.internal +# and add cross-make to Makefile. +cross_overrides="/dev/null" +if [[ x$host != x$target ]] +then + cross_defines="CROSS=-DCROSS_COMPILE" + cross_overrides="${topdir}/cross-make" +fi + +# When building gcc with a cross-compiler, we need to fix a few things. +# This must come after cross-make as we want all.build to override +# all.cross. +build_overrides="/dev/null" +if [[ x$build != x$host ]] +then + build_overrides="${topdir}/build-make" +fi + +# Expand extra_headers to include complete path. +# This substitutes for lots of t-* files. +extra_headers_list= +if [[ "x$extra_headers" = x ]] +then true +else + # Prepend ${srcdir}/ginclude/ to every entry in extra_headers. + for file in $extra_headers; + do + extra_headers_list="${extra_headers_list} \$(srcdir)/ginclude/${file}" + done +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 ]] +then + will_use_collect2= + maybe_use_collect2= +else + will_use_collect2="collect2" + maybe_use_collect2="-DUSE_COLLECT2" +fi + +# NEED TO CONVERT +# Set MD_DEPS if the real md file is in md.pre-cpp. +# Set MD_CPP to the cpp to pass the md file through. Md files use ';' +# for line oriented comments, so we must always use a GNU cpp. If +# 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 ]] +then + md_file_sub=$srcdir/config/$md_file +else + md_file=md +fi + +# If we have gas in the build tree, make a link to it. +if [[ -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 + 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 +# 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 +# fi +fi + +# Figure out what assembler alignment features are present. +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 + # Build using assembler in the current directory. + gcc_cv_as=./as$host_exeext +elif [[ -f $gcc_cv_as_gas_srcdir/configure.in ]]; 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 + 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 + # 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 + 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 + gcc_cv_as_alignment_features=".p2align including maximum skip" + AC_DEFINE(HAVE_GAS_MAX_SKIP_P2ALIGN) + fi + fi +elif [[ x$host = x$target ]]; then + # Native build. + gcc_cv_as=as$host_exeext +fi +if [[ x$gcc_cv_as != x ]]; then + # Check if we have .balign and .p2align + echo ".balign 4" > conftest.s + echo ".p2align 2" >> conftest.s + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + gcc_cv_as_alignment_features=".balign and .p2align" + AC_DEFINE(HAVE_GAS_BALIGN_AND_P2ALIGN) + fi + rm -f conftest.s conftest.o + # Check if specifying the maximum bytes to skip when + # using .p2align is supported. + echo ".p2align 4,,7" > conftest.s + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + gcc_cv_as_alignment_features=".p2align including maximum skip" + AC_DEFINE(HAVE_GAS_MAX_SKIP_P2ALIGN) + fi + rm -f conftest.s conftest.o +fi +AC_MSG_RESULT($gcc_cv_as_alignment_features) + +# Figure out what language subdirectories are present. +subdirs= +for lang in ${srcdir}/*/config-lang.in .. +do + case $lang in + ..) ;; + # 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,'`" ;; + esac +done + +# Make gthr-default.h if we have a thread file. +gthread_flags= +if [[ $thread_file != single ]]; then + rm -f gthr-default.h + echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h + gthread_flags=-DHAVE_GTHR_DEFAULT +fi +AC_SUBST(gthread_flags) + +# Make empty files to contain the specs and options for each language. +# Then add #include lines to for a compiler that has specs and/or options. + +lang_specs_files= +lang_options_files= +rm -f specs.h options.h +touch specs.h options.h +for subdir in . $subdirs +do + if [[ -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 + echo "#include \"$subdir/lang-options.h\"" >>options.h + lang_options_files="$lang_options_files $srcdir/$subdir/lang-options.h" + fi +done + +# These (without "all_") are set in each config-lang.in. +# `language' must be a single word so is spelled singularly. +all_languages= +all_boot_languages= +all_compilers= +all_stagestuff= +all_diff_excludes= +all_outputs=Makefile +# List of language makefile fragments. +all_lang_makefiles= +all_headers= +all_lib2funcs= + +# Add the language fragments. +# Languages are added via two mechanisms. Some information must be +# recorded in makefile variables, these are defined in config-lang.in. +# We accumulate them and plug them into the main Makefile. +# The other mechanism is a set of hooks for each of the main targets +# like `clean', `install', etc. + +language_fragments="Make-lang" +language_hooks="Make-hooks" +oldstyle_subdirs= + +for s in .. $subdirs +do + if [[ $s != ".." ]] + then + language= + boot_language= + compilers= + stagestuff= + diff_excludes= + headers= + outputs= + lib2funcs= + . ${srcdir}/$s/config-lang.in + if [[ "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 ]] + then + all_boot_languages="$all_boot_languages $language" + fi + all_compilers="$all_compilers $compilers" + all_stagestuff="$all_stagestuff $stagestuff" + all_diff_excludes="$all_diff_excludes $diff_excludes" + all_headers="$all_headers $headers" + all_outputs="$all_outputs $outputs" + if [[ x$outputs = x ]] + then + oldstyle_subdirs="$oldstyle_subdirs $s" + fi + all_lib2funcs="$all_lib2funcs $lib2funcs" + fi +done + +# Since we can't use `::' targets, we link each language in +# with a set of hooks, reached indirectly via lang.${target}. + +rm -f Make-hooks +touch Make-hooks +target_list="all.build all.cross start.encap rest.encap \ + info dvi \ + install-normal install-common install-info install-man \ + uninstall distdir \ + mostlyclean clean distclean extraclean maintainer-clean \ + stage1 stage2 stage3 stage4" +for t in $target_list +do + x= + for l in .. $all_languages + do + if [[ $l != ".." ]]; then + x="$x $l.$t" + fi + done + echo "lang.$t: $x" >> Make-hooks +done + +# If we're not building in srcdir, create .gdbinit. + +if [[ ! -f Makefile.in ]]; then + echo "dir ." > .gdbinit + echo "dir ${srcdir}" >> .gdbinit + if [[ x$gdb_needs_out_file_path = xyes ]] + then + echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit + fi + if [[ "x$subdirs" != x ]]; then + for s in $subdirs + do + echo "dir ${srcdir}/$s" >> .gdbinit + done + fi + echo "source ${srcdir}/.gdbinit" >> .gdbinit +fi + +# Define variables host_canonical and build_canonical +# because some Cygnus local changes in the Makefile depend on them. +build_canonical=${build} +host_canonical=${host} +target_subdir= +if [[ "${host}" != "${target}" ]] ; then + target_subdir=${target}/ +fi +AC_SUBST(build_canonical) +AC_SUBST(host_canonical) +AC_SUBST(target_subdir) + +# If this is using newlib, then define inhibit_libc in +# LIBGCC2_CFLAGS. This will cause __eprintf to be left out of +# libgcc.a, but that's OK because newib should have its own version of +# assert.h. +inhibit_libc= +if [[ x$with_newlib = xyes ]]; then + inhibit_libc=-Dinhibit_libc +fi +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 + 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 + # 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 + echo "Removing $x" + rm -f $x + fi + done +fi + +# Nothing to do for FLOAT_H, float_format already handled. +objdir=`pwd` +AC_SUBST(objdir) + +# Process the language and host/target makefile fragments. +${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xmake_file" "$dep_tmake_file" + +# 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(cpp_main) +AC_SUBST(extra_passes) +AC_SUBST(extra_programs) +AC_SUBST(extra_parts) +AC_SUBST(extra_c_objs) +AC_SUBST(extra_cxx_objs) +AC_SUBST(extra_c_flags) +AC_SUBST(extra_objs) +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(lang_options_files) +AC_SUBST(thread_file) +AC_SUBST(gcc_version) +AC_SUBST(gcc_version_trigger) +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(stage_prefix_set_by_configure) +AC_SUBST(install) +AC_SUBST(symbolic_link) +AC_SUBST(cpp_install_dir) + + +AC_SUBST_FILE(target_overrides) +AC_SUBST_FILE(host_overrides) +AC_SUBST(cross_defines) +AC_SUBST_FILE(cross_overrides) +AC_SUBST_FILE(build_overrides) +AC_SUBST_FILE(language_fragments) +AC_SUBST_FILE(language_hooks) + +# Echo that links are built +if [[ x$host = x$target ]] +then + str1="native " +else + str1="cross-" + str2=" from $host" +fi + +if [[ x$host != x$build ]] +then + str3=" on a $build system" +fi + +if [[ "x$str2" != x ]] || [[ "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 ]] +then + echo " ${str2}${str3}." 1>&2 +fi + +# Truncate the target if necessary +if [[ x$host_truncate_target != x ]]; then + target=`echo $target | sed -e 's/\(..............\).*/\1/'` +fi + +# Configure the subdirectories +# AC_CONFIG_SUBDIRS($subdirs) + +# Create the Makefile +# and configure language subdirectories +AC_OUTPUT($all_outputs, +[ +. $srcdir/configure.lang +case x$CONFIG_HEADERS in +xauto-host.h:config.in) +echo > cstamp-h ;; +esac +# If the host supports symlinks, point stage[1234] at ../stage[1234] so +# bootstrapping and the installation procedure can still use +# CC="stage1/xgcc -Bstage1/". If the host doesn't support symlinks, +# 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 + for d in .. ${subdirs} ; do + if [[ $d != .. ]]; then + STARTDIR=`pwd` + cd $d + for t in stage1 stage2 stage3 stage4 include + do + rm -f $t + $symbolic_link ../$t $t 2>/dev/null + done + cd $STARTDIR + fi + done +else true ; fi +], +[ +host='${host}' +build='${build}' +target='${target}' +target_alias='${target_alias}' +srcdir='${srcdir}' +subdirs='${subdirs}' +oldstyle_subdirs='${oldstyle_subdirs}' +symbolic_link='${symbolic_link}' +program_transform_set='${program_transform_set}' +program_transform_name='${program_transform_name}' +dep_host_xmake_file='${dep_host_xmake_file}' +host_xmake_file='${host_xmake_file}' +dep_tmake_file='${dep_tmake_file}' +tmake_file='${tmake_file}' +thread_file='${thread_file}' +gcc_version='${gcc_version}' +gcc_version_trigger='${gcc_version_trigger}' +local_prefix='${local_prefix}' +build_install_headers_dir='${build_install_headers_dir}' +build_exeext='${build_exeext}' +host_exeext='${host_exeext}' +out_file='${out_file}' +gdb_needs_out_file_path='${gdb_needs_out_file_path}' +SET_MAKE='${SET_MAKE}' +target_list='${target_list}' +target_overrides='${target_overrides}' +host_overrides='${host_overrides}' +cross_defines='${cross_defines}' +cross_overrides='${cross_overrides}' +build_overrides='${build_overrides}' +cpp_install_dir='${cpp_install_dir}' +]) diff --git a/contrib/gcc/configure.lang b/contrib/gcc/configure.lang new file mode 100644 index 0000000..d96b6d8 --- /dev/null +++ b/contrib/gcc/configure.lang @@ -0,0 +1,233 @@ +# configure.lang for GNU CC +# This script is run by configure for configuration of language +# subdirectories which conform to the old GCC configure mechanism +# for such subdirectories. + +# Copyright (C) 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 +#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. + +savesrcdir=$srcdir + +for subdir in . $oldstyle_subdirs +do + # We only want to do this in language subdirs, but we have to handle + # the case of $oldstyle_subdirs = "". + if [ $subdir = . ] + then + continue + fi + + oldsrcdir=$savesrcdir + + # Re-adjust the path + case $oldsrcdir in + /*) + srcdir=$oldsrcdir/$subdir + ;; + *) + oldsrcdir=../${oldsrcdir} + srcdir=$oldsrcdir/$subdir + ;; + esac + mainsrcdir=$oldsrcdir + STARTDIR=`pwd` + test -d $subdir || mkdir $subdir + cd $subdir + + # Create Makefile.tem from Makefile.in. + # Make it set VPATH if necessary so that the sources are found. + # Also change its value of srcdir. + # Also create a .gdbinit file which runs the one in srcdir + # and tells GDB to look there for source files. + case $srcdir in + . | ./$subdir | .././$subdir) + rm -f Makefile.tem + cp Makefile.in Makefile.tem + chmod +w Makefile.tem + ;; + *) + rm -f Makefile.tem + echo "VPATH = ${srcdir}" \ + | cat - ${srcdir}/Makefile.in \ + | sed "s@^srcdir = \.@srcdir = ${srcdir}@" > Makefile.tem + rm -f .gdbinit + echo "dir ." > .gdbinit + echo "dir ${srcdir}" >> .gdbinit + echo "dir ${mainsrcdir}" >> .gdbinit + if [ x$gdb_needs_out_file_path = xyes ] + then + echo "dir ${mainsrcdir}/config/"`dirname ${out_file}` >> .gdbinit + fi + echo "source ${mainsrcdir}/.gdbinit" >> .gdbinit + ;; + esac + + # Conditionalize the makefile for this host machine. + rm -f Makefile.xx Makefile.ll + merged_frags= + for f in .. ${host_xmake_file} + do + if [ -f ${mainsrcdir}/config/$f ] + then + cat ${mainsrcdir}/config/$f >> Makefile.ll + if [ x"${merged_frags}" != x ] + then + merged_frags="${merged_frags} and " + fi + merged_frags="${merged_frags}${f}" + fi + done + if [ x"${merged_frags}" != x ] + then + sed -e "/####host/ r Makefile.ll" Makefile.tem > Makefile.xx + echo "Merged ${merged_frags}." + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + rm -f Makefile.ll + fi + + # Add a definition for MAKE if system wants one. + case "$SET_MAKE" in + ?*) + rm -f Makefile.xx + (echo "$SET_MAKE"; cat Makefile.tem) >Makefile.xx + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + esac + + # Add a definition for INSTALL if system wants one. + # This substitutes for lots of x-* files. + if [ x$build_broken_install = x ] + then true + else + rm -f Makefile.xx + abssrcdir=`cd ${srcdir}; pwd` + sed "s|^INSTALL = .*|${INSTALL}|" Makefile.tem > Makefile.xx + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + fi + + # If using -program-transform-name, override the installation names. + if [ "x${program_transform_set}" = "xyes" ] ; then + sed -e "s/^program_transform_name[ ]*=.*$/program_transform_name = +$program_transform_name/" \ + -e "s/^program_transform_cross_name[ +]*=.*$/program_transform_cross_name = $program_transform_name/" \ + Makefile.tem > Makefile.xx + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + fi + + # Conditionalize the makefile for this target machine. + rm -f Makefile.xx Makefile.ll + merged_frags= + for f in .. ${tmake_file} + do + if [ -f ${mainsrcdir}/config/$f ] + then + cat ${mainsrcdir}/config/$f >> Makefile.ll + if [ x"${merged_frags}" != x ] + then + merged_frags="${merged_frags} and " + fi + merged_frags="${merged_frags}$f" + fi + done + if [ x"${merged_frags}" != x ] + then + sed -e "/####target/ r Makefile.ll" Makefile.tem > Makefile.xx + echo "Merged ${merged_frags}." + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + rm -f Makefile.ll + fi + + # If the host supports + # symlinks, point stage[123] at ../stage[123] so bootstrapping and the + # installation procedure can still use CC="stage1/xgcc -Bstage1/". + # If the host doesn't support symlinks, FLAGS_TO_PASS has been + # modified to solve the problem there. + for t in stage1 stage2 stage3 stage4 include + do + rm -f $t + $symbolic_link ../$t $t 2>/dev/null + done + + # Remove all formfeeds, since some Makes get confused by them. + # Also arrange to give the variables `target', `target_alias', + # `host_xmake_file', `tmake_file', `prefix', `local_prefix', + # `exec_prefix', `INSTALL_HEADERS_DIR', `exeext' + # values in the Makefile from the values they have in this script. + rm -f Makefile.xx + # Create an empty Makefile.sed first, to work around a Nextstep 3.3 bug. + echo 's| ||' > Makefile.sed + rm Makefile.sed + echo 's| ||' > Makefile.sed + echo "s|^target=.*$|target=${target}|" >> Makefile.sed + echo "s|^target_alias=.*$|target_alias=${target_alias}|" >> Makefile.sed + echo "s|^xmake_file=.*$|xmake_file=${dep_host_xmake_file}|" >> Makefile.sed + echo "s|^tmake_file=.*$|tmake_file=${dep_tmake_file}|" >> Makefile.sed + echo "s|^version=.*$|version=${version}|" >> Makefile.sed + echo "s|^GCC_THREAD_FILE=.*$|GCC_THREAD_FILE=${thread_file}|" >> Makefile.sed + echo "s|^prefix[ ]*=.*|prefix = $prefix|" >> Makefile.sed + echo "s|^local_prefix[ ]*=.*|local_prefix = $local_prefix|" >> Makefile.sed + echo "s|^exec_prefix[ ]*=.*|exec_prefix = $exec_prefix|" >> Makefile.sed + echo "s|^INSTALL_HEADERS_DIR[ ]*=.*$|INSTALL_HEADERS_DIR = ${build_install_headers_dir}|" >> Makefile.sed + echo "s|^exeext[ ]*=.*$|exeext = ${build_exeext}|" >> Makefile.sed + sed -f Makefile.sed Makefile.tem > Makefile.xx + rm -f Makefile.tem Makefile.sed + mv Makefile.xx Makefile.tem + + # Install Makefile for real, after making final changes. + # Define macro CROSS_COMPILE in compilation + # if this is a cross-compiler. + # Also use all.cross instead of all.internal + # and add cross-make to Makefile. + if [ x$host != x$target ] + then + rm -f Makefile.xx + echo "CROSS=-DCROSS_COMPILE" > Makefile.xx + sed -e "/####cross/ r ${mainsrcdir}/cross-make" Makefile.tem >> Makefile.xx + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + fi + + # When building gcc with a cross-compiler, we need to fix a few things. + # This must come after cross-make as we want all.build to override + # all.cross. + if [ x$build != x$host ] + then + rm -f Makefile.xx + echo "build= $build" > Makefile.xx + echo "host= $host" >> Makefile.xx + sed -e "s|objc-runtime$||" \ + -e "/####build/ r ${mainsrcdir}/build-make" Makefile.tem >> Makefile.xx + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + fi + + rm -f Makefile + mv Makefile.tem Makefile + echo "Created \`$subdir/Makefile'." + + cd $STARTDIR +done # end of current-dir SUBDIRS loop + +# Restore this, remember we're invoked with `.'. +srcdir=$savesrcdir diff --git a/contrib/gcc/convert.c b/contrib/gcc/convert.c index 17e7552..e03d39b 100644 --- a/contrib/gcc/convert.c +++ b/contrib/gcc/convert.c @@ -1,5 +1,5 @@ /* Utility routines for data type conversion for GNU C. - Copyright (C) 1987, 88, 91, 92, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 91-95, 97, 1998 Free Software Foundation, Inc. This file is part of GNU C. @@ -20,25 +20,23 @@ Boston, MA 02111-1307, USA. */ /* These routines are somewhat language-independent utility function - intended to be called by the language-specific convert () functions. */ + intended to be called by the language-specific convert () functions. */ #include "config.h" #include "tree.h" #include "flags.h" #include "convert.h" +#include "toplev.h" /* Convert EXPR to some pointer or reference type TYPE. EXPR must be pointer, reference, integer, enumeral, or literal zero; - in other cases error is called. */ + in other cases error is called. */ tree convert_to_pointer (type, expr) tree type, expr; { - register tree intype = TREE_TYPE (expr); - register enum tree_code form = TREE_CODE (intype); - if (integer_zerop (expr)) { expr = build_int_2 (0, 0); @@ -46,64 +44,64 @@ convert_to_pointer (type, expr) return expr; } - if (form == POINTER_TYPE || form == REFERENCE_TYPE) - return build1 (NOP_EXPR, type, expr); - - - if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) + switch (TREE_CODE (TREE_TYPE (expr))) { - if (type_precision (intype) == POINTER_SIZE) + case POINTER_TYPE: + case REFERENCE_TYPE: + return build1 (NOP_EXPR, type, expr); + + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + if (TYPE_PRECISION (TREE_TYPE (expr)) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = convert (type_for_size (POINTER_SIZE, 0), expr); - /* Modes may be different but sizes should be the same. */ - if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))) - != GET_MODE_SIZE (TYPE_MODE (type))) - /* There is supposed to be some integral type - that is the same width as a pointer. */ - abort (); - return convert_to_pointer (type, expr); - } - error ("cannot convert to a pointer type"); + return + convert_to_pointer (type, + convert (type_for_size (POINTER_SIZE, 0), expr)); - expr = build_int_2 (0, 0); - TREE_TYPE (expr) = type; - return expr; + default: + error ("cannot convert to a pointer type"); + return convert_to_pointer (type, integer_zero_node); + } } /* Convert EXPR to some floating-point type TYPE. EXPR must be float, integer, or enumeral; - in other cases error is called. */ + in other cases error is called. */ tree convert_to_real (type, expr) tree type, expr; { - register enum tree_code form = TREE_CODE (TREE_TYPE (expr)); - - if (form == REAL_TYPE) - return build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR, - type, expr); - - if (INTEGRAL_TYPE_P (TREE_TYPE (expr))) - return build1 (FLOAT_EXPR, type, expr); - - if (form == COMPLEX_TYPE) - return convert (type, fold (build1 (REALPART_EXPR, - TREE_TYPE (TREE_TYPE (expr)), expr))); - - if (form == POINTER_TYPE || form == REFERENCE_TYPE) - error ("pointer value used where a floating point value was expected"); - else - error ("aggregate value used where a float was expected"); - - { - register tree tem = make_node (REAL_CST); - TREE_TYPE (tem) = type; - TREE_REAL_CST (tem) = REAL_VALUE_ATOF ("0.0", TYPE_MODE (type)); - return tem; - } + switch (TREE_CODE (TREE_TYPE (expr))) + { + case REAL_TYPE: + return build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR, + type, expr); + + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + return build1 (FLOAT_EXPR, type, expr); + + case COMPLEX_TYPE: + return convert (type, + fold (build1 (REALPART_EXPR, + TREE_TYPE (TREE_TYPE (expr)), expr))); + + case POINTER_TYPE: + case REFERENCE_TYPE: + error ("pointer value used where a floating point value was expected"); + return convert_to_real (type, integer_zero_node); + + default: + error ("aggregate value used where a float was expected"); + return convert_to_real (type, integer_zero_node); + } } /* Convert EXPR to some integer (or enum) type TYPE. @@ -118,34 +116,30 @@ tree convert_to_integer (type, expr) tree type, expr; { - register tree intype = TREE_TYPE (expr); - register enum tree_code form = TREE_CODE (intype); + enum tree_code ex_form = TREE_CODE (expr); + tree intype = TREE_TYPE (expr); + int inprec = TYPE_PRECISION (intype); + int outprec = TYPE_PRECISION (type); - if (form == POINTER_TYPE || form == REFERENCE_TYPE) + switch (TREE_CODE (intype)) { + case POINTER_TYPE: + case REFERENCE_TYPE: if (integer_zerop (expr)) expr = integer_zero_node; else expr = fold (build1 (CONVERT_EXPR, type_for_size (POINTER_SIZE, 0), expr)); - intype = TREE_TYPE (expr); - form = TREE_CODE (intype); - if (intype == type) - return expr; - } - if (form == INTEGER_TYPE || form == ENUMERAL_TYPE - || form == BOOLEAN_TYPE || form == CHAR_TYPE) - { - register unsigned outprec = TYPE_PRECISION (type); - register unsigned inprec = TYPE_PRECISION (intype); - register enum tree_code ex_form = TREE_CODE (expr); + return convert_to_integer (type, expr); - /* If we are widening the type, put in an explicit conversion. - Similarly if we are not changing the width. However, if this is - a logical operation that just returns 0 or 1, we can change the - type of the expression. For logical operations, we must - also change the types of the operands to maintain type + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + /* If this is a logical operation, which just returns 0 or 1, we can + change the type of the expression. For some logical operations, + we must also change the types of the operands to maintain type correctness. */ if (TREE_CODE_CLASS (ex_form) == '<') @@ -153,6 +147,7 @@ convert_to_integer (type, expr) TREE_TYPE (expr) = type; return expr; } + else if (ex_form == TRUTH_AND_EXPR || ex_form == TRUTH_ANDIF_EXPR || ex_form == TRUTH_OR_EXPR || ex_form == TRUTH_ORIF_EXPR || ex_form == TRUTH_XOR_EXPR) @@ -162,12 +157,18 @@ convert_to_integer (type, expr) TREE_TYPE (expr) = type; return expr; } + else if (ex_form == TRUTH_NOT_EXPR) { TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0)); TREE_TYPE (expr) = type; return expr; } + + /* If we are widening the type, put in an explicit conversion. + Similarly if we are not changing the width. After this, we know + we are truncating EXPR. */ + else if (outprec >= inprec) return build1 (NOP_EXPR, type, expr); @@ -352,71 +353,30 @@ convert_to_integer (type, expr) return convert (type, get_unwidened (TREE_OPERAND (expr, 0), type)); case COND_EXPR: - /* Can treat the two alternative values like the operands - of an arithmetic expression. */ - { - tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type); - tree arg2 = get_unwidened (TREE_OPERAND (expr, 2), type); - - if (outprec >= BITS_PER_WORD - || TRULY_NOOP_TRUNCATION (outprec, inprec) - || inprec > TYPE_PRECISION (TREE_TYPE (arg1)) - || inprec > TYPE_PRECISION (TREE_TYPE (arg2))) - { - /* Do the arithmetic in type TYPEX, - then convert result to TYPE. */ - register tree typex = type; - - /* Can't do arithmetic in enumeral types - so use an integer type that will hold the values. */ - if (TREE_CODE (typex) == ENUMERAL_TYPE) - typex = type_for_size (TYPE_PRECISION (typex), - TREE_UNSIGNED (typex)); - - /* But now perhaps TYPEX is as wide as INPREC. - In that case, do nothing special here. - (Otherwise would recurse infinitely in convert. */ - if (TYPE_PRECISION (typex) != inprec) - { - /* Don't do unsigned arithmetic where signed was wanted, - or vice versa. */ - typex = (TREE_UNSIGNED (TREE_TYPE (expr)) - ? unsigned_type (typex) : signed_type (typex)); - return convert (type, - fold (build (COND_EXPR, typex, - TREE_OPERAND (expr, 0), - convert (typex, arg1), - convert (typex, arg2)))); - } - else - /* It is sometimes worthwhile - to push the narrowing down through the conditional. */ - return fold (build (COND_EXPR, type, - TREE_OPERAND (expr, 0), - convert (type, TREE_OPERAND (expr, 1)), - convert (type, TREE_OPERAND (expr, 2)))); - } - } + /* It is sometimes worthwhile to push the narrowing down through + the conditional and never loses. */ + return fold (build (COND_EXPR, type, TREE_OPERAND (expr, 0), + convert (type, TREE_OPERAND (expr, 1)), + convert (type, TREE_OPERAND (expr, 2)))); + default: + break; } return build1 (NOP_EXPR, type, expr); - } - if (form == REAL_TYPE) - return build1 (FIX_TRUNC_EXPR, type, expr); + case REAL_TYPE: + return build1 (FIX_TRUNC_EXPR, type, expr); - if (form == COMPLEX_TYPE) - return convert (type, fold (build1 (REALPART_EXPR, - TREE_TYPE (TREE_TYPE (expr)), expr))); + case COMPLEX_TYPE: + return convert (type, + fold (build1 (REALPART_EXPR, + TREE_TYPE (TREE_TYPE (expr)), expr))); - error ("aggregate value used where an integer was expected"); - - { - register tree tem = build_int_2 (0, 0); - TREE_TYPE (tem) = type; - return tem; - } + default: + error ("aggregate value used where an integer was expected"); + return convert (type, integer_zero_node); + } } /* Convert EXPR to the complex type TYPE in the usual ways. */ @@ -425,48 +385,52 @@ tree convert_to_complex (type, expr) tree type, expr; { - register enum tree_code form = TREE_CODE (TREE_TYPE (expr)); tree subtype = TREE_TYPE (type); - if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE) + switch (TREE_CODE (TREE_TYPE (expr))) { - expr = convert (subtype, expr); - return build (COMPLEX_EXPR, type, expr, + case REAL_TYPE: + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + return build (COMPLEX_EXPR, type, convert (subtype, expr), convert (subtype, integer_zero_node)); - } - if (form == COMPLEX_TYPE) - { - tree elt_type = TREE_TYPE (TREE_TYPE (expr)); - if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype)) - return expr; - else if (TREE_CODE (expr) == COMPLEX_EXPR) - return fold (build (COMPLEX_EXPR, - type, - convert (subtype, TREE_OPERAND (expr, 0)), - convert (subtype, TREE_OPERAND (expr, 1)))); - else - { - expr = save_expr (expr); + case COMPLEX_TYPE: + { + tree elt_type = TREE_TYPE (TREE_TYPE (expr)); + + if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype)) + return expr; + else if (TREE_CODE (expr) == COMPLEX_EXPR) return fold (build (COMPLEX_EXPR, type, - convert (subtype, - fold (build1 (REALPART_EXPR, - TREE_TYPE (TREE_TYPE (expr)), - expr))), - convert (subtype, - fold (build1 (IMAGPART_EXPR, - TREE_TYPE (TREE_TYPE (expr)), - expr))))); - } - } + convert (subtype, TREE_OPERAND (expr, 0)), + convert (subtype, TREE_OPERAND (expr, 1)))); + else + { + expr = save_expr (expr); + return + fold (build (COMPLEX_EXPR, + type, convert (subtype, + fold (build1 (REALPART_EXPR, + TREE_TYPE (TREE_TYPE (expr)), + expr))), + convert (subtype, + fold (build1 (IMAGPART_EXPR, + TREE_TYPE (TREE_TYPE (expr)), + expr))))); + } + } - if (form == POINTER_TYPE || form == REFERENCE_TYPE) - error ("pointer value used where a complex was expected"); - else - error ("aggregate value used where a complex was expected"); - - return build (COMPLEX_EXPR, type, - convert (subtype, integer_zero_node), - convert (subtype, integer_zero_node)); + case POINTER_TYPE: + case REFERENCE_TYPE: + error ("pointer value used where a complex was expected"); + return convert_to_complex (type, integer_zero_node); + + default: + error ("aggregate value used where a complex was expected"); + return convert_to_complex (type, integer_zero_node); + } } diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog index 420e25d..5102e32 100644 --- a/contrib/gcc/cp/ChangeLog +++ b/contrib/gcc/cp/ChangeLog @@ -1,9473 +1,11057 @@ -Thu Aug 22 23:47:38 1997 H.J. Lu (hjl@gnu.ai.mit.edu) +Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com) - * Version 2.7.2.3 released. + * egcs-1.1.2 Released. -Mon Apr 29 00:27:53 1996 Jason Merrill - - * lex.c (real_yylex): Fix handling of __PRETTY_FUNCTION__ like C - frontend. - -Thu Oct 26 16:45:58 1995 Brendan Kehoe - - * errfn.c: Include stdio.h. - (cp_sprintf): Take out decl of sprintf, and cast sprintf to errorfn*. - -Mon Nov 20 14:06:28 1995 Mike Stump - - * Version 2.7.2 released. - -Mon Nov 20 14:05:00 1995 Mike Stump - - * g++.c (pfatal_with_name): Add missing third argument to concat. - -Thu Oct 26 13:59:54 1995 Mike Stump - - * init.c (expand_aggr_init): Handle cv qualifiers on the object's - type. - -Sun Nov 12 18:09:35 1995 Mike Stump - - * Version 2.7.1 released. - -Thu Nov 2 17:02:47 1995 Jason Merrill - - * call.c (convert_harshness): Handle references to arrays. - -Fri Oct 27 14:20:21 1995 Jason Merrill - - * typeck.c (comp_target_types): Check multi-level pointer - conversions in both directions. - -Tue Oct 17 21:39:05 1995 Jason Merrill - - * parse.y (explicit_instantiation): Fix 'extern template' with no - return type. - -Mon Oct 16 14:35:20 1995 Jason Merrill +Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org) - * parse.y (explicit_instantiation): Support automatic instantiation - of constructors. - (named_class_head_*): Support out-of-class definition of nested - types. - -Wed Oct 11 12:20:56 1995 Mike Stump - - * search.c (envelope_add_decl): New routine. Fix so that - methods are hidden in the same way that other members are. - (dfs_pushdecls): Cleanup and move functionality out of line, - into envelope_add_decl. - -Tue Oct 10 15:46:01 1995 Mike Stump - - * typeck.c (mark_addressable): Only call assemble_external if we - have started the output file. - -Tue Oct 10 11:27:18 1995 Jason Merrill - - * decl.c (start_function): Fix earlier cv-quals change. - -Mon Oct 9 23:53:05 1995 Mike Stump - - * parse.y (complex_direct_notype_declarator): Only push the class if - we are not already in the class. - -Mon Oct 9 11:22:03 1995 Doug Evans - - * decl.c (duplicate_decls): Call merge_machine_decl_attributes. - Update olddecl's attributes too. - (grokdeclarator): #if 0 out call to build_decl_attribute_variant. - * typeck.c (common_type): Call merge_machine_type_attributes. - -Fri Oct 6 14:44:27 1995 Mike Stump - - * typeck.c (mark_addressable): Add missing call to - assemble_external. + * decl2.c (start_objects): Make file scope constructors and + destructors local to the file if ASM_OUTPUT_CONSTRUCTOR and + ASM_OUTPUT_DESTRUCTOR are defined. -Wed Oct 4 22:05:23 1995 Jeff Law (law@hurl.cygnus.com +Sat Feb 20 15:08:42 1999 Jeffrey A Law (law@cygnus.com) - * cp/decl.c (deplicate_decls): Merge in deferred output - status for variables. - * cp/tree.c (tree_copy_lang_decl_for_deferred_output): New - function to copy the g++ specific parts of a DECL node. - (tree_copy_lang_type_for_deferred_output): Similarly for - TYPE nodes. + 1999-01-25 Martin von Löwis + * tree.c (equal_functions): New function. + (ovl_member): Call it. -Wed Oct 4 15:06:39 1995 Mike Stump +Sat Feb 6 17:00:48 1999 Jeffrey A Law (law@cygnus.com) - * decl.c (store_parm_decls): Make sure the unwinder start comes - before the exception specification start. - * except.c (expand_exception_blocks): Make sure the unwinder end - comes after the terminate protected catch clause region and after - the end of the exception specification region. + * typeck2.c: Update email addresses. -Wed Oct 4 12:47:02 1995 Jason Merrill +1998-11-16 Jason Merrill - * lex.c (real_yylex): Fix identifier case for linemode. - (handle_sysv_pragma): Don't abort when we see a pragma we don't - recognize. - -Tue Oct 3 14:09:46 1995 Mike Stump - - * decl.c (store_parm_decls): Add a call to start_eh_unwinder. - * except.c (init_exception_processing): __throw doesn't take any - arguments. - (expand_builtin_throw): Ditto. Always use Pmode, instead of SImode - for all pointers. Use expand_builtin_return_addr to unwind the - first level off the stack. - (do_unwind): Always use Pmode, instead of SImode for all pointers. - (expand_exception_blocks): Add a call to end_eh_unwinder. - (start_eh_unwinder, end_eh_unwinder): New routines to build machine - independent stack unwinders for function/method calls. - -Mon Oct 2 17:20:42 1995 Mike Stump + * typeck2.c (my_friendly_abort): Don't fatal twice in a row. - * tree.c (unsave_expr_now): Make sure we process the argument list - of any called functions. Fixes incorrect code generation for - cleanups. +1998-11-15 Jason Merrill -Mon Oct 2 13:04:16 1995 Mike Stump + * typeck2.c (my_friendly_abort): Add URL in the other case, too. - * typeck.c (get_member_function_from_ptrfunc): Save function if it - needs it. Cures core dump on things like (this->*(f()))(). +1998-11-13 Jason Merrill -Sat Sep 23 22:51:25 1995 Jason Merrill - - * decl.c (start_function): Conform to gcc cv-quals convention (no - expression has a cv-qualified type) in RESULT_DECLs. - * method.c (make_thunk): Ditto. - -Fri Sep 22 10:21:13 1995 Mike Stump - - * decl.c (pushtag): Add in the namespace name for the tag. - -Thu Sep 21 13:11:13 1995 Mike Stump - - * parse.y (maybe_base_class_list, base_class_list, base_class, - base_class_access_list): Make sure we see the typenames for base - classes. - * lex.c (see_typename): Instead of failing to see a typename when - there is no next token, perfer a typename, and get the next token. + * rtti.c (synthesize_tinfo_fn): Call import_export_decl here. + (get_tinfo_fn): Not here. -Wed Sep 20 12:35:27 1995 Michael Meissner +1998-11-08 Mark Mitchell - * decl.c (init_decl_processing): Add __builtin_expect. + * 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. -Tue Sep 19 16:48:11 1995 Mike Stump +1998-11-02 Jason Merrill - * cvt.c (cp_convert_to_pointer): Don't allow leftover conversions to - or from pointer to member functions, they must all be handled before - this point. + * decl2.c (import_export_decl): Call import_export_class. -Fri Sep 15 17:14:47 1995 Brendan Kehoe +1998-10-28 Jason Merrill - * init.c (resolve_offset_ref): Fix wording of non-static member - being referenced as a static. + * class.c (finish_struct_1): Don't complain about non-copy + assignment ops in union members. -Fri Sep 15 12:39:11 1995 Jason Merrill + * class.c (build_vtable): Don't pass at_eof to import_export_vtable. + (prepare_fresh_vtable): Likewise. + (finish_struct_1): Don't call import_export_class. + * decl2.c (finish_vtable_vardecl): Do import/export stuff. + (finish_prevtable_vardecl): Lose. + (finish_file): Don't call it. + * pt.c (instantiate_class_template): Likewise. - * typeck.c (build_indirect_ref): Only bash pointer if we actually - call build_expr_type_conversion. +1998-10-23 Martin von Löwis -Thu Sep 14 18:24:56 1995 Jason Merrill - - * cvt.c (build_expr_type_conversion): Handle conversion from + * parse.y (condition): Convert VAR_DECL from reference to indirect reference. - * typeck.c (build_indirect_ref): Avoid infinite recursion. - -Thu Sep 14 17:23:28 1995 Mike Stump - - * decl.c (expand_start_early_try_stmts): New routine to start a try - block at the start of the function, for function-try-blocks. - * cp-tree.h (expand_start_early_try_stmts): Declare it. - * parse.y (function_try_block): Use it, instead of doing it here, as - we don't want to include rtl.h here, as that conflicts with RETURN - in the parser. - -Wed Sep 13 18:32:24 1995 Mike Stump - - * lex.c (reinit_parse_for_block): Support saving inline - function-try-blocks, uses peekyylex. - * parse.y (eat_saved_input): New rule, permit the parser to see that - END_OF_SAVED_INPUT is ok, as it can see this when parsing the - handlers of a function-try-block. - (fndef): Use it. - (component_decl): Make sure TRY and RETURN can come after fn.def2. - * spew.c (peekyylex): New routine to peek at what will come next. - -Wed Sep 13 16:52:06 1995 Jason Merrill - - * typeck.c (comptypes): Tighten up comparisons of template type - parms. - - * decl.c (duplicate_decls): Turn off whining about virtual functions - redeclared inline for now. - -Wed Sep 13 11:13:40 1995 Mike Stump - - * decl.c (store_in_parms): New routine to put things before we - put base inits. - * cp-tree.h (store_in_parms): Declare it. - * decl.c (store_parm_decls): Use it to makr sure the starting of the - eh spec comes before base inits. - (finish_function): Use sequences instead of the obsolete - reorder_insns. - * parse.y (fndef): Enhance readability and maintainability. Update - to include function_try_block syntax. - (function_try_block): Add. - -Tue Sep 12 17:43:07 1995 Brendan Kehoe - - * call.c (convert_harshness): Use comptypes, not ==, to check if - TYPE and PARMTYPE are equivalent on a function type. - -Tue Sep 12 17:31:33 1995 Douglas Rupp (drupp@cs.washington.edu) - * Make-lang.in (cc1plus) : Removed unnecessary $(exeext). +1998-10-18 Jason Merrill -Mon Sep 11 23:24:07 1995 Mike Stump + * method.c (hack_identifier): Just return a member function. - * except.c (expand_throw): Never allocate storage for thrown pointer - to objects. +1998-10-18 Martin von Löwis -Mon Sep 11 19:36:45 1995 Mike Stump + * decl2.c (validate_nonmember_using_decl): Fix using-directives of + std if std is ignored. - * except.c (expand_start_catch_block): Pointers to objects come - back from catch matching already dereferenced, don't dereference - again. +1998-10-14 Jason Merrill -Mon Sep 11 15:46:28 1995 Mike Stump + * spew.c (yylex): Clear looking_for_typename if we got + 'enum { ... };'. - * except.c (expand_throw): Only decay the throw expression, don't do - any default conversions. This is so that one can throw and catch - characters, and not have them match integers. +1998-10-13 Jason Merrill -Mon Sep 11 13:46:45 1995 Mike Stump + * tinfo2.cc (fast_compare): Remove. + (before): Just use strcmp. + * tinfo.cc (operator==): Just use strcmp. - * error.c (dump_aggr_type): Deal with anonymous unions that don't - have a TYPE_NAME. +1998-10-12 Jason Merrill -Fri Sep 8 20:40:27 1995 Brendan Kehoe + * tinfo.cc (operator==): Always compare names. - * lex.c (handle_sysv_pragma): Deal with getting a comma from yylex. +1998-10-12 Jason Merrill -Fri Sep 8 15:51:41 1995 Mike Stump + * inc/typeinfo: Add #pragma interface. + (operator!=): Just call operator==. + * tinfo.cc: Add #pragma implementation. + (operator==): Move from inc/typeinfo and tinfo2.cc. - * except.c (expand_end_eh_spec): Handle empty EH specifications. + * typeck2.c (my_friendly_abort): Add URL. -Fri Sep 8 15:27:22 1995 Mike Stump +1998-10-05 Martin von Löwis - * cp-tree.h (expand_start_eh_spec): Declare new routine. - (expand_end_eh_spec): Ditto. - * decl.c (store_parm_decls): Call expand_start_eh_spec to process - exception specifications. - * except.c (expand_leftover_cleanups): Remove unused parameter. - (expand_end_catch_block): Ditto. - (expand_exception_blocks): Ditto. - (expand_start_eh_spec): New routine to mark the start of an - exception specification region. - (expand_end_eh_spec): New routine to mark the end of an exception - specification region. - (expand_exception_blocks): Call expand_end_eh_spec to process - exception specifications. + * method.c (build_decl_overload_real): Clear + numeric_output_need_bar after __. -Fri Sep 8 14:40:48 1995 Per Bothner +1998-10-04 Jason Merrill - * lex.c (do_identifier): Use global binding in preference of - dead for local variable. + * decl.c (cp_finish_decl): Make statics in extern inlines and + templates common, if possible and the target doesn't support weak + symbols. -Wed Sep 6 19:32:59 1995 Mike Stump +1998-10-03 Jason Merrill - * cp-tree.h (build_exception_variant): Remove used first argument. - * decl.c (duplicate_decls): Ditto. - (grokfndecl): Ditto. - (revert_static_member_fn): Ditto. - * decl2.c (grok_method_quals): Ditto. - * tree.c (build_exception_variant): Ditto. - * typeck.c (common_type): Ditto. - * decl2.c (grokclassfn): After changing the type, call - build_exception_variant, if necessary. + * decl2.c (merge_functions): Remove duplicates. -Tue Sep 5 15:56:27 1995 Mike Stump + * typeck.c (build_conditional_expr): Only fold if ifexp is an + INTEGER_CST. - * except.c (expand_throw): Run cleanups for the throw expression. +Fri Oct 2 02:07:26 1998 Mumit Khan -Wed Aug 30 15:24:38 1995 Stephen L. Favor (sfavor@tigger.intecom.com) + * parse.y (nomods_initdcl0): Set up the parser stack correctly. - * except.c (expand_builtin_throw): Moved gen_label_rtx calls beyond - the store_parm_decls call which does initialization in the emit_* - code concerning label numbering. - -Thu Aug 31 09:01:07 1995 Mike Stump - - * except.c (expand_internal_throw): Let the frontend be responsible - for managing all frontend EH parameters, the backend routine only - needs to deal with backend values. type and value are no longer - passed to __throw. - (init_exception_processing): Ditto. - (expand_start_all_catch): Ditto. - (expand_end_all_catch): Ditto. - (expand_leftover_cleanups): Ditto. - (expand_end_catch_block): Ditto. - (expand_builtin_throw): Ditto. - (expand_throw): Ditto. - -Tue Aug 29 15:04:36 1995 Jason Merrill - - * cp-tree.h (DECL_REAL_CONTEXT): Give the real declaration context - for a decl. - * decl.c (cp_finish_decl): Use it. - -Tue Aug 29 10:30:27 1995 Mike Stump - - * except.c (expand_internal_throw): Oops, almost forgot type and - value are now trees. - -Mon Aug 28 17:57:45 1995 Brendan Kehoe - - Fix the attribute handling to make sure they get noted before we - create the function's RTL, in case they can affect that. - * decl.c (grokfndecl): New arg ATTRLIST. Run - cplus_decl_attributes before creating the decl's rtl. - (grokdeclarator): New arg ATTRLIST, passed down into grokfndecl. - (shadow_tag, groktypename, start_decl, start_method): Pass a - NULL_TREE to grokdeclarator's new last arg. - * decl2.c (grokfield): New arg ATTRLIST, passed into grokdeclarator. - (grokbitfield, grokoptypename): Pass a NULL_TREE to - grokdeclarator's new last arg. - * except.c (expand_start_catch_block): Likewise. - * pt.c (process_template_parm, end_template_decl, - do_function_instantiation): Likewise. - * cp-tree.h (grokfield): Add arg. - (grokdeclarator): Move the prototype from here... - * decl.h: ...to here. - * lex.c (cons_up_default_function): Pass NULL_TREE to grokfield - ATTRLIST argument. - * parse.y: Create a list for the grokfield arg where appropriate, - and pass it down instead of calling cplus_decl_attributes. - -Mon Aug 28 15:07:24 1995 Mike Stump - - * except.c: Always allow turning on exception handling. Allow cross - compilations to use EH. - -Thu Aug 24 17:39:24 1995 Mike Stump - - * except.c (saved_pc, saved_throw_type, saved_throw_value): Use - trees, instead of rtxs, and don't depend on using special machine - dependent registers. - (expand_internal_throw): Ditto. - (init_exception_processing): Ditto. - (expand_start_all_catch): Ditto. - (expand_end_all_catch): Ditto. - (expand_start_catch_block): Ditto. - (expand_leftover_cleanups): Ditto. - (expand_end_catch_block): Ditto. - (expand_builtin_throw): Ditto. - (expand_throw): Ditto. - -Wed Aug 23 17:25:51 1995 Jason Merrill - - * cvt.c (build_expr_type_conversion): Handle conversions to - reference types. - -Wed Aug 23 15:33:59 1995 Mike Stump - - * except.c (do_unwind): Work around backend bug with -fpic. - -Tue Aug 22 17:20:07 1995 Per Bothner - - * decl2.c (flag_new_for_scope): Add a new mode that follows ANSI - for-scoping, but supports (and warns about) old programs. - Make the new mode (with value 1) the default. - (lang_f_options): The on-value for flag_new_for_scope is now 2. - * cp-tree.h (DECL_DEAD_FOR_LOCAL, DECL_ERROR_REPORTED): New macros - (DECL_SHADOWED_FOR_VAR): Likewise. - * decl.c (struct binding_level): New fields dead_vars_from_for - and is_for_scope. - (note_level_for_for): New function. - (poplevel): Special processing if is_for_scope. - (pushdecl): Warn if for-scope variable shadows local. - * lex.c (do_identifier): Handle old (non-ANSI) for scoping, - and warn if conflicts. - * parse.y (FOR): Call note_level_for_for. - -Mon Aug 21 10:28:31 1995 Jason Merrill - - * decl2.c (import_export_inline): Class interface hackery does not - apply to synthesized methods. +1998-08-25 Jason Merrill -Sun Aug 20 16:29:00 1995 Mike Stump - - * search.c (virtual_context): Find the right context more often. - Solves a `recoverable compiler error, fixups for virtual function' - problem. - -Sun Aug 20 13:53:24 1995 Mike Stump - - * except.c (expand_start_all_catch): Ensure that we always transfer - control to the right EH handler, by rethrowing the end label on the - region, instead of hoping we are nested and falling through. - (expand_leftover_cleanups): Ditto. - (end_protect): Since we now rethrow the end label, put a - nop after it, so that outer regions are recognized. - * init.c (build_vec_delete_1): New routine to handle most of vector - deleting, all code moved here from build_vec_delete. - (build_array_eh_cleanup): Use build_vec_delete_1 to do all the real - work. - (expand_vec_init): If the array needs partial destructing, setup an - EH region to handle it. - (build_vec_delete): Move lots of code to build_vec_delete_1, use - build_vec_delete_1 to do the grunt work. - -Sat Aug 19 14:25:33 1995 Brendan Kehoe - - Handle decl attributes properly for function definitions without - previous attribute-loaded declarations. - * decl.c (start_function): New arg ATTRS. Add a call to - cplus_decl_attributes with it before we create the RTL. - * cp-tree.h (start_function): Update prototype. - * parse.y (fn.def1): Pass ATTRS into start_function instead of - trying to call cplus_decl_attributes too late. Pass a NULL_TREE - for other use. - * decl2.c (finish_file): Pass NULL_TREE as fourth arg to - start_function. - * method.c (synthesize_method): Likewise. - * except.c (expand_builtin_throw): Likewise for start on __throw. - -Sat Aug 19 13:36:08 1995 Mike Stump - - * class.c (set_rtti_entry): Turn on -fvtable-thunk -frtti support. - This changes -fvtable-thunks vtable layout, so a recompile will be - necessary, if you use -fvtable-thunks. - (get_vtable_entry): Use n, instead of i to be consistent with the - rest of the compiler. - (get_vtable_entry_n): Ditto. - (add_virtual_function): Add a slot for the tdesc, if -fvtable-thunks - are being used. - (finish_struct_1): Ditto. - (skip_rtti_stuff): New routine to collapse similar code from many - different parts of the compiler. I think I got them all. - (modify_one_vtable): Use it. - (fixup_vtable_deltas1): Ditto. - (override_one_vtable): Ditto. - * decl2.c (mark_vtable_entries): Ditto. - * tree.c (debug_binfo): Ditto. - * search.c (expand_upcast_fixups): Ditto. - (get_abstract_virtuals_1): Ditto. Use virtuals, instead of tmp to - consistent with the rest of the compiler. - (get_abstract_virtuals): Ditto. - * cp-tree.h (skip_rtti_stuff): New routine, declare it. - * gc.c (build_headof): Support -fvtable-thunk and -frtti together. - (build_typeid): Ditto. - (build_classof): Remove old style way of doing rtti. Remove support - for `classof' and `headof'. - * gxx.gperf: Ditto. - * hash.h: Ditto. - * parse.y: Ditto. - -Fri Aug 18 17:31:58 1995 Jason Merrill - - * decl.c (start_function): Clear ctor_label and dtor_label. - - * class.c (finish_struct_1): Fix handling of access decls. - -Tue Aug 15 19:21:54 1995 Jason Merrill - - * class.c (finish_struct): Only do minimal processing here, so it - can be used for class template definitions, as well. - (finish_struct_1): New function with the rest of the code. - -Tue Aug 15 09:46:16 1995 Mike Stump - - * class.c (prepare_fresh_vtable): On second though, always build the - offset (see Aug 10 change), unless -fvtable-thunks is given. It - does this by calling the new routine set_rtti_entry. - (finish_struct): Ditto. - (set_rtti_entry): New routine to update the rtti information at the - start of the vtable. - -Mon Aug 14 12:21:22 1995 Brendan Kehoe - - * error.c (dump_decl, case IDENTIFIER_NODE): Only work on a dtor - if it's declared in the C++ language spec. - (dump_function_decl): Likewise. - (dump_function_name): Likewise. - (ident_fndecl): Make sure we got something back from lookup_name. - * decl.c (start_function): Likewise. - -Fri Aug 11 16:52:15 1995 Jason Merrill - - * call.c (build_method_call): Don't call build_new when calling a - constructor without an instance. - -Thu Aug 10 20:00:17 1995 Mike Stump - - * class.c (prepare_fresh_vtable): Always build the offset to the - complete object, as it doesn't cost much. This allows dynamic_cast - to void * to work when -frtti isn't given. - (finish_struct): Ditto. - -Thu Aug 10 16:31:28 1995 Mike Stump - - * except.c (build_eh_type): Split out some functionality to new - routine named build_eh_type_type. - (build_eh_type_type): New routine. - (expand_start_catch_block): Use build_eh_type_type, as we never want - the dynamic type of the catch parameter, just the static type. - Fixes core dumps when -frtti is used and one catchs pointers to - classes. - -Thu Aug 10 14:55:29 1995 Mike Stump + * decl.c (duplicate_decls): Don't complain about different + exceptions from an internal decl even if pedantic. - * except.c (expand_builtin_throw): Since we now use normal calling - conventions for __throw, we have to remove the first layer off the - stack, so that the next context we search for handlers is the outer - context instead of the context that had the call to __throw, if we - don't immediately find the desired context. - -Tue Aug 8 17:44:23 1995 Jason Merrill - - * tree.c (cp_expand_decl_cleanup): Returns int, not tree. - * cp-tree.h: Update. +1998-08-24 Gavin Romig-Koch - * parse.y (template_type_parm): Add support for `typename'. - -Tue Aug 8 12:06:31 1995 Mike Stump - - * except.c (expand_internal_throw): New internal routine to throw a - value. - (expand_end_all_catch, expand_leftover_cleanups): All throwers - changed to use `expand_internal_throw' instead of jumping to throw - label. - (expand_end_catch_block, expand_throw): Ditto. - (throw_label): Removed. - (expand_builtin_throw): Changed so that EH parameters are passed by - normal function call conventions. Completes Aug 4th work. + * typeck.c (c_expand_return): Handle the case that valtype + is wider than the functions return type. -Fri Aug 4 17:17:08 1995 Mike Stump +1998-08-24 Martin von Löwis - * cp-tree.h (expand_builtin_throw): Declare it. - * decl2.c (finish_file): Call expand_builtin_throw. - * except.c (make_first_label): Remove. - (init_exception_processing): Don't use a LABEL_REF for throw_label, - instead use a SYMBOL_REF, this is so that we don't use LABEL_REFs in - other functions that don't really appear in those functions. This - solves a problem where cc1plus consumed exponential amounts of - memory when -Wall was used. - (expand_end_all_catch, expand_leftover_cleanups, - expand_end_catch_block, expand_throw): Change all uses of - throw_label to match new style. - (do_unwind): Rename parameter to inner_throw_label, as it is now - different from throw_label. Also, assume that our caller will wrap - the passed label with a LABEL_REF, if needed. - (expand_builtin_throw): Make external, change so that the generated - throw is now a real function. - (expand_exception_blocks): Never generate throw code inside another - function. - -Fri Aug 4 12:20:02 1995 Mike Stump - - * decl.c (grokdeclarator): Move checking of mutable const objects - and mutable static objects down, as we might decide during parsing - to unset staticp or constp (for example, when const is part of the - object being pointed to). - -Thu Aug 3 17:13:43 1995 Mike Stump - - * except.c (output_exception_table_entry): Enhance portability to - weird machines. - (emit_exception_table): Ditto. - -Thu Aug 3 16:41:38 1995 Mike Stump - - * typeck.c (build_ptrmemfunc): Handle casting of pointer to - non-virtual member functions. - -Wed Aug 2 11:58:25 1995 Mike Stump - - * gc.c (build_typeid): Strip cv qualifiers so that const T&, T&, T - and const T all match. - -Wed Aug 2 11:25:33 1995 Mike Stump - - * except.c (build_eh_type): Strip cv qualifiers so that const T&, - T&, T and const T all match. - -Tue Aug 1 14:20:16 1995 Mike Stump - - * except.c: Fix up comments, cleanup code and eliminate exceptNode, - exceptStack, exceptstack, push_except_stmts, pop_except_stmts, - new_except_stack, push_last_insn, pop_last_insn, insn_save_node and - InsnSave. Also, numerous speed improvements, and correctness - improvements. Double faulting in all situations should now be - handled correctly. - (expand_start_all_catch): Instead of having many terminate protected - regions, just have one. - (expand_start_catch_block): No longer have to protect - false_label_rtx, as it isn't used for EH region marking. - (expand_end_catch_block): Expand out EH cleanups here by using - expand_leftover_cleanups. - (expand_end_all_catch): Use sequences instead of playing with insn - links directly. - (expand_exception_blocks): Ditto. Also protect all catch clauses - with one terminate region. + * search.c (my_tree_cons): Reimplement. -Mon Jul 31 13:24:30 1995 Jason Merrill +1998-08-17 Jason Merrill - * method.c (report_type_mismatch): Don't talk about an object - parameter for non-methods. + * decl.c (finish_enum): Also set TYPE_SIZE_UNIT. + * class.c (finish_struct_bits): Likewise. -Sun Jul 30 13:13:02 1995 Jason Merrill +1998-08-17 Mark Mitchell - * class.c (finish_struct): Catch private and protected members of - anonymous unions here. - * decl2.c (finish_anon_union): And here. - * parse.y: Instead of here. + * pt.c (check_explicit_specialization): Don't abort on bogus + explicit instantiations. - * errfn.c (ARGSLIST): Support passing four args. - * error.c (cv_as_string): New function. - (cp_printers): Add it. - * call.c (build_method_call): Report 'const' at end of pseudo-decl. +1998-08-14 Jason Merrill - * method.c (report_type_mismatch): Deal with a bad_arg of 0. + * rtti.c (get_tinfo_fn): Don't mess with the context for now. - * init.c (expand_aggr_init): Handle volatile objects, too. +1998-08-13 Mumit Khan -Sat Jul 29 13:42:03 1995 Jason Merrill + * decl2.c (import_export_class): Don't use dllexport + attribute as a heuristic. - * decl.c (struct binding_level): Keep list of incomplete decls. - (print_binding_level): Use list_length to count them. - (pushdecl): Build up the list. - (hack_incomplete_structures): Walk it and prune completed decls. +1998-07-29 Jason Merrill -Fri Jul 28 15:26:44 1995 Jason Merrill + * decl.c (push_overloaded_decl): Use current_namespace instead of + DECL_CONTEXT (decl) to determine where we go. - * typeck.c (comp_target_types): Don't check const and volatile for - function types. - (comp_ptr_ttypes_real): Ditto. + * decl.c (lookup_name_real): Fix typo. -Thu Jul 27 15:40:48 1995 Jason Merrill +1998-07-28 Jason Merrill - * typeck.c (comp_target_types): Fix. + * class.c (finish_struct_1): Convert integer_zero_node to + ssizetype before passing it to set_rtti_entry. + * typeck2.c (initializer_constant_valid_p): Allow conversion of 0 + of any size to a pointer. -Thu Jul 27 15:10:48 1995 Mike Stump +1998-07-27 Jason Merrill - * cp-tree.h (unsave_expr_now, build_unsave_expr, - cp_expand_decl_cleanup): Declare new routines. - * decl.c (cp_finish_decl, store_parm_decls, - hack_incomplete_structures): Change all cals from - expand_decl_cleanup to cp_expand_decl_cleanup. - * gc.c (protect_value_from_gc): Ditto. - * expr.c (cplus_expand_expr): Handle UNSAVE_EXPRs. - * tree.c (unsave_expr): New routine to build an UNSAVE_EXPR. - (unsave_expr_now): Backend routine used by tree expander. - (cp_expand_decl_cleanup): Wrap second argument in an UNSAVE_EXPR to - work around a limitation in the backend. The backend uses the - cleanups multiple times, on disjoint control flows, so we cannot - pass unsaved SAVE_EXPRs to the backend. - * tree.def (UNSAVE_EXPR): New tree code. - * typeck.c (c_expand_return): Move goto/return code up inside - conditional, as we don't always want to do this, we only want to do - this when we don't otherwise finish with this control flow. + * typeck2.c (build_functional_cast): Handle default-initialization. -Thu Jul 27 10:38:43 1995 Brendan Kehoe + * call.c (build_over_call): Pass 1 to popclass. - * parse.y (typespec): Only complain about typeof if we're not - getting it from a system header. + * parse.y (direct_notype_declarator): Add precedence declaration + to notype_unqualified_id case. + * Makefile.in (EXPECT): Adjust. -Thu Jul 27 10:26:23 1995 Doug Evans + * tree.c (ovl_member): Fix for single function in OVL. - Clean up prefix attribute handling. - * parse.y (reserved_declspecs): Link prefix attributes with declspecs. - (declmods): Likewise. - (all rules that reference typed_declspecs and declmods): Call - split_specs_attrs or strip_attrs to separate declspecs and attrs. - (lang_extdef): Delete resetting of prefix_attributes. - (template_def, notype_declarator rule): Use NULL_TREE for - prefix_attributes. - (condition): Use NULL_TREE for prefix_attributes. - (setattrs): Deleted. - (nomods_initdcl0): Set prefix_attributes to NULL_TREE. - (component_decl): Delete resetting of prefix_attributes. - (component_decl_1, notype_components rule): Use NULL_TREE for - prefix_attributes. - (simple_stmt): Delete resetting of prefix_attributes. +1998-07-24 Jason Merrill -Mon Jul 24 13:37:53 1995 Jason Merrill + * decl.c (lookup_name_real): OK, do return the from_obj value + unless got_object depends on template parms. - * call.c (convert_harshness): Deal with reference conversions before - others. Actually do array->pointer decay. Call comp_target_types - with pointer types rather than their targets. + * parse.y (nested_name_specifier_1): Pull out the TYPE_MAIN_VARIANT. - * typeck.c (comp_target_types): Avoid assigning D const * to B *. + * pt.c (coerce_template_parms): Also complain about local enums. -Mon Jul 24 08:54:46 1995 Brendan Kehoe + * cp-tree.h: Add prototype for set_identifier_local_value. + * decl.c (set_identifier_local_value_with_scope): Make static, + prototype. + * search.c (covariant_return_p): Likewise. + * except.c (build_terminate_handler, alloc_eh_object): Likewise. - * pt.c (to_be_restored): Move decl to global scope. + * call.c (build_method_call): Only pull out the type of a destructor + if it's a template type parm. + * decl.c (lookup_name_real): Never return the from_obj value. -Sat Jul 22 12:22:11 1995 Jason Merrill +1998-07-23 Jason Merrill - * decl.c (start_decl): Put back clearing of DECL_IN_AGGR_P. + * except.c (process_start_catch_block_old): Call start_decl_1 for + catch parm. + * decl.c (start_decl_1): Avoid duplicate error. -Fri Jul 21 17:09:02 1995 Jason Merrill + * init.c (expand_default_init): Only perform the initialization if + it will do something. - * decl.c (grokdeclarator): Downgrade error about 'extern int A::i' - to pedwarn. +1998-07-23 H.J. Lu (hjl@gnu.org) - * pt.c (instantiate_template): Also avoid instantiation if the - function has already been declared to be a specialization. + * parse.y (base_class): Check for invalid base class. - * decl2.c (check_classfn): Ignore cname argument, and return the - matching function. +1998-07-23 Jason Merrill - * decl.c (start_decl): Handle declarations of member functions - outside of the class (i.e. specialization declarations). + * decl2.c (import_export_template): Fold in... + (import_export_class): ...to here. Handle dllimport/export. -Thu Jul 20 10:34:48 1995 Jason Merrill + * class.c (build_vtable): Pass at_eof to import_export_vtable. + (prepare_fresh_vtable): Likewise. + * decl2.c (import_export_class): Split out... + (finish_prevtable_vardecl): From here. + * class.c (finish_struct_1): Call import_export_class if at_eof. - * class.c (finish_struct): Don't mess with the type of bitfields. + * 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. - * various.c: s/TYPE_POINTER_TO/build_pointer_type/. +1998-07-22 Jason Merrill -Thu Jul 20 01:43:10 1995 Mike Stump + * inc/exception: Change terminate and unexpected to (). - * init.c (expand_aggr_init): Assume LOOKUP_ONLYCONVERTING if init - is not a parameter list (TREE_LIST). - (expand_default_init): If LOOKUP_ONLYCONVERTING is set, then set - LOOKUP_NO_CONVERSION so that we don't allow two-level conversions, - but don't set it otherwise. + * parse.y (named_class_head_sans_basetype_defn): A + named_class_head_sans_basetype followed by '{' or ':' is a defn. -Wed Jul 19 20:32:01 1995 Mike Stump +1998-07-21 Jason Merrill - * init.c (expand_default_init): Don't allow two-level conversions - during construction. + * tree.c (canonical_type_variant): New fn to handle arrays. + * cp-tree.h (CANONICAL_TYPE_VARIANT): Remove. + * pt.c (unify, default case): Also fold arg. Fix array bounds case. + * method.c (process_overload_item): Use build_overload_value for + arrays. -Wed Jul 19 18:06:37 1995 Mike Stump +1998-07-19 Jason Merrill - * gc.c (build_headof): The type of dyncasting to a pointer to cv - void, should be pointer to cv void. + * lex.c (do_identifier): Look for class value even if we don't + have a global value. Do implicit declaration if parsing is 2. + * semantics.c (finish_call_expr): Pass 2 if we're doing Koenig + lookup. -Wed Jul 19 17:25:43 1995 Mike Stump +1998-07-19 Mark Mitchell - * gc.c (build_dynamic_cast): Allow casting in const. + * decl.c (pushtag): Revert previous change. + * pt.c (lookup_template_class): Don't put out debugging + information for types that use template parameters. -Wed Jul 19 16:34:27 1995 Mike Stump - - * typeck.c (build_const_cast): If we are passed error_mark_node, - return it. - -Wed Jul 19 15:24:48 1995 Brendan Kehoe - - * class.c (push_nested_class): Make sure TYPE is non-nil. - - * cvt.c (type_promotes_to): Watch for error_mark_node on the - incoming TYPE. - -Wed Jul 19 13:23:12 1995 Gerald Baumgartner - - * cp-tree.h (SIGTABLE_VT_OFF_NAME): Renamed from SIGTABLE_OFFSET_NAME. - (SIGTABLE_VB_OFF_NAME): New macro. - (vt_off_identifier): Renamed from offset_identifier. - (vb_off_identifier): Added extern declaration. - - * decl.c (vt_off_identifier): Renamed from offset identifier. - (vb_off_identifier): New variable to hold the identifier for the - sigtable field vb_off. - (init_decl_processing): Initialize vb_off_identifier. - Renamed vt_off_identifier from offset_identifier. - * sig.c (build_signature_method_call): Renamed offset_identifier and - local variable offset to vt_off_identifer and vt_off, respecitively. - * sig.c (build_signature_table_constructor): Renamed offset to vt_off. - - * decl.c (init_decl_processing): Add vb_off field to - sigtable_entry_type. Reorder fields so that pfn gets properly - aligned at a 64 bit boundary on the Alpha. - * sig.c (build_signature_table_constructor): Build the constructor - according to the new layout. Set the vb_off field to -1 for now. - - * decl.c (init_decl_processing): Align sigtable_entry_type on word - boundaries instead of double word boundaries to save space. - -Tue Jul 18 16:58:37 1995 Mike Stump - - * cvt.c (cp_convert): Always call build_cplus_new for a ctor. - -Tue Jul 18 14:24:53 1995 Brendan Kehoe - - * parse.y (opt.component_decl_list): Only forbid private/protected - in anonymous unions. We need to make this know when the type is - defined for an object, to not give the error. - -Mon Jul 17 14:22:44 1995 Brendan Kehoe - - * parse.y (opt.component_decl_list): Don't allow access control - as private or protected for union members. - -Sun Jul 16 14:01:00 1995 Jim Wilson - - * lex.c (check_newline): For 'p' case, move goto skipline line to - before end brace for 'pragma'. - -Fri Jul 7 13:55:58 1995 Mike Stump - - * g++.1: Tiny updates. - -Fri Jul 7 13:05:20 1995 Mike Stump - - * decl.c (cp_finish_decl): Only destruct local static variables if - they are constructed, and only construct the first time control - passes completely through its declaration (if not initialized with a - constant-expression). - (expand_static_init): Ditto. - -Wed Jul 5 14:05:04 1995 Brendan Kehoe + * 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. - * typeck.c (comptypes, case OFFSET_REF): If either offset basetype - is a TEMPLATE_TYPE_PARM, give a match. + * semantics.c (finish_translation_unit): Fix spelling error in + comment. -Mon Jul 3 15:17:20 1995 Steve Chamberlain +1998-07-17 Jason Merrill - * g++.c (sys/file.h): Remove change of Jun 28. + * decl.c (lookup_name_real): Pull out single function here. + (select_decl): Not here. + (unqualified_namespace_lookup): Use CP_DECL_CONTEXT. -Fri Jun 30 15:42:57 1995 Mike Stump + * decl.c (qualify_lookup): Tweak again. - * method.c (build_overload_value): Handle encoding of null pointer - constants (or any pointer with a constant numeric value) for + * pt.c (lookup_template_class): Don't mess with the context of the + instantiation. + * decl2.c (current_decl_namespace): Remove special handling for templates. -Fri Jun 30 13:45:51 1995 Brendan Kehoe + * pt.c (tsubst, case FUNCTION_DECL): Fix getting complete args for + a member template specialization. - * call.c (convert_harshness): Add QUAL_CODE when we're faced with - const vs non-const for void conversions. + * tree.c (ovl_member): Use decls_match to compare functions. + * decl.c (decls_match): Check the context of a function. -Fri Jun 30 10:19:52 1995 Mike Stump + * parse.y (primary): Use notype_unqualified_id instead of IDENTIFIER + in Koenig lookup support rules. + * semantics.c (finish_call_expr): Handle the new cases. - * except.c (expand_start_all_catch): Fix problem with finding an - outer nested try block when there is no code to separate it from an - inner try block. + * typeck.c (build_x_function_call): Handle overloaded methods. -Fri Jun 30 02:22:26 1995 Mike Stump + * decl.c (grokvardecl): Don't call build_static_name for extern "C". - * search.c (dfs_pushdecls): Consume 2 or 3 orders of magnitude less - memory please when virtual bases are used. +1998-07-16 Mark Mitchell -Thu Jun 29 19:03:47 1995 Mike Stump + * semantics.c (finish_object_call_expr): Revert previous change. + * call.c (build_new_method_call): Likewise. Instead, convert + TYPE_DECLs to IDENTIFIERs here, in the presence of templates. - * class.c (build_vbase_path): Avoid testing things that cannot be - null to see if they are null. - * cvt.c (convert_pointer_to_vbase): Remove code that doesn't work. - * decl.c (finish_function): Pass a type into the new - convert_pointer_to_vbase instead of a binfo. - * search.c (convert_pointer_to_vbase): Rewritten to use get_vbase - and convert_pointer_to_real. - (expand_indirect_vtbls_init): Use convert_pointer_to_vbase instead - of the more cryptic call to get_vbase. +1998-07-16 Jason Merrill -Thu Jun 29 09:35:05 1995 Mike Stump + * decl.c (qualify_lookup): Handle templates. - * decl.c (BOOL_TYPE_SIZE): Fix broken SLOW_BYTE_ACCESS check. + * decl2.c (do_using_directive): Don't pass ancestor. + * decl.c (push_using_directive): Calculate ancestor. -Thu Jun 29 03:43:55 1995 Jason Merrill + * decl2.c (do_nonmember_using_decl): Allow for type shadowing. + * decl.c (pushdecl): Move type shadowing handling from here... + (duplicate_decls): ...to here. + * decl.c (set_identifier_local_value_with_scope): New fn. + (pushdecl): Use it. + (set_identifier_local_value, lookup_type_current_level): New fns. + * decl2.c (do_local_using_decl): Handle types and binding level + stuff properly. - * pt.c (instantiate_template): Don't strip 'this' twice. + * init.c (build_offset_ref): Don't call mark_used on an OVERLOAD. + * decl.c (select_decl): Extract a lone function from an OVERLOAD. + (lookup_namespace_name): Likewise. + * typeck.c (build_unary_op): Not here anymore. - * pt.c (coerce_template_parms): Allow null pointer constants. + * decl2.c (do_class_using_decl): Make sure we get an identifier. + * class.c (handle_using_decl): Ignore TYPE_DECLs. - * decl.c (revert_static_member_fn): But only if DECL_ARGUMENTS is - set. + * decl.c (qualify_lookup): New fn. + (lookup_name_real): Use it. -Wed Jun 28 23:34:58 1995 Steve Chamberlain +1998-07-16 Martin v. Loewis - * g++.c (pfatal_with_name): Use my_strerror to get error - string. - (sys/file.h): Include if HAVE_FILE_H defined. + * decl2.c (add_using_namespace): When directly using a namespace + that was indirect before, promote it. -Wed Jun 28 18:39:03 1995 Jason Merrill + * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES, + LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY, + LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros. + * decl.c (select_decl): Replace two flag parameters by one. + (unqualified_namespace_lookup): Likewise, pass flag. + (lookup_flags): New function. + (lookup_name_real): Compute flags, pass them. + (lookup_namespace_name): Call with zero-flag. + * decl2.c (ambiguous_decl): Add flag parameter, complain only + according to flags. + (lookup_using_namespace, qualified_lookup_using_namespace): + Add flag parameter, pass them through. + * lex.c (do_scoped_id): Call with zero-flag. - * decl.c (revert_static_member_fn): Also remove 'this' from - DECL_ARGUMENTS. - * decl2.c (check_classfn): Don't revert this function until we get a - match. +1998-07-16 Jason Merrill -Wed Jun 28 14:07:27 1995 Brendan Kehoe + * typeck.c (convert_for_assignment): Use comptypes. - * parse.y (component_decl): Clear PREFIX_ATTRIBUTES here. +1998-07-16 Mark Mitchell -Wed Jun 28 11:05:13 1995 Mike Stump + * semantics.c (finish_object_call_expr): Move test for the + function called being a TYPE_DECL to ... + * call.c (build_new_method_call): Here. - * decl2.c (finish_file): Handle global vector news. - * init.c (build_new): Encode vector news so that later we will know - how many elements there are. +1998-07-15 Jason Merrill -Mon Jun 26 13:38:06 1995 Jason Merrill + * decl2.c (arg_assoc_class): Also look at template arguments, if any. + (arg_assoc): Handle error_mark_node and multiple levels of TREE_LIST. - * expr.c (cplus_expand_expr): Don't mess with temp slots. + * lex.c (looking_for_typename): Don't initialize. - * decl2.c (warn_if_unknown_interface): Don't crash if tinst_for_decl - returns null. + * decl2.c (ambiguous_decl): Clarify error message. - * decl2.c (check_classfn): Use revert_static_member_fn. - * decl.c (revert_static_member_fn): Diagnose static member functions - declared const or volatile. + * decl.c (push_using_directive): Iterate over namespaces used + indirectly. - * decl2.c (grokfield): Check for missing default args here, too. - (check_default_args): Function to do the checking. - * decl.c (pushdecl): Use it. +1998-07-15 Martin v. Löwis - * decl.c (pushdecl): Don't warn about shadowing a member of `this' - if there is no `this'. + * decl2.c (add_using_namespace): Iterate over namespaces used + indirectly. -Sun Jun 25 11:34:25 1995 Jason Merrill + * decl.c (lookup_name_real): Accept namespace aliases as locals. + (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. + * parse.y (namespace_alias): New non-terminal. + (extdef): Use it. - * call.c (build_method_call): Downgrade 'called before definition' - to a warning, as it ought to go away after Monterey. +1998-07-15 Jason Merrill -Sat Jun 24 14:18:42 1995 Jason Merrill + * decl2.c (arg_assoc_type): Handle METHOD_TYPE like FUNCTION_TYPE. + Handle TEMPLATE_TYPE_PARM. + (arg_assoc): Rewrite. - * pt.c (coerce_template_parms): Don't do extra checking on pointer - to member arguments. + * pt.c (complete_template_args): Don't look at the context unless + we have to. - * class.c (finish_struct): const and reference members don't prevent - a class from being an aggregate. + * method.c (build_decl_overload_real): Fix namespace handling. - * class.c (finish_struct): Signatures are always aggregates. + * typeck.c (build_unary_op): Extract a lone function from an + OVERLOAD. -Fri Jun 23 17:20:29 1995 Jason Merrill + * call.c (build_scoped_method_call): Handle getting a namespace + for basetype in a destructor call. + (check_dtor_name): Handle enums. - * decl2.c (check_classfn): Improve error message. + * parse.y (using_directive): New nonterminal. + (extdef, simple_stmt): Use it. - * pt.c (tsubst): Handle PROMOTE_PROTOTYPES. +1998-07-14 Martin von Löwis -Thu Jun 22 01:50:42 1995 Jason Merrill + * decl2.c (add_function): Move error message ... + (arg_assoc_namespace): ... from here. - * typeck.c (comptypes): Don't ignore method quals. +1998-07-14 Jason Merrill - * class.c (finish_struct): Non-abstract virtuals are always USED. + * parse.y (namespace_qualifier): Fix multiple level handling. + * decl2.c (namespace_ancestor): Use CP_DECL_CONTEXT. + (arg_assoc): Don't skip the first argument of a function. - * decl.c (build_ptrmemfunc_type): The underlying union type isn't - IS_AGGR_TYPE, either. - * class.c (finish_struct): Use CLASSTYPE_NON_AGGREGATE instead. - * cp-tree.h: Ditto. + * call.c (joust): Don't warn about "confusing" conversions to the + same type. - * cp-tree.h (lang_type): Add aggregate. - (CLASSTYPE_AGGREGATE): New macro. - (TYPE_NON_AGGREGATE_CLASS): Ditto. - * class.c (finish_struct): Determine whether a class is an - aggregate. - * decl.c (cp_finish_decl): Check TYPE_NON_AGGREGATE_CLASS instead of - TYPE_NEEDS_CONSTRUCTING. - * typeck2.c (digest_init): Check TYPE_NON_AGGREGATE_CLASS for - subobjects, too. +1998-07-14 Martin von Löwis - * pt.c (tsubst, PARM_TYPE): Propagate DECL_ARTIFICIAL. - - * decl.c (start_function): For pre-parsed functions, layout all of - the parm decls again. - (grokvardecl): TREE_PUBLIC depends on DECL_THIS_EXTERN, not - DECL_EXTERNAL. - - * pt.c (coerce_template_parms): Improve checking for invalid - template parms. - -Wed Jun 21 12:01:16 1995 Brendan Kehoe - - * decl.c (grokdeclarator): Forbid declaration of a static member - with the same name as its enclosing class. - -Mon Jun 19 10:28:14 1995 Jason Merrill - - * decl.c (finish_function): Clear current_class_decl. + * class.c (push_nested_class): Complain about namespaces. + * decl.c (start_decl): Enter the object's namespace. + (cp_finish_decl): Leave it. + (grokdeclarator): Likewise. + * decl2.c (check_decl_namespace): New function. + (finish_file): Call it. + * parse.y (complex_direct_notype_declarator): Set complexity + of namespace-qualified ids to -1, enter the namespace. - * typeck.c (build_conditional_expr): Use convert (boolean_type_node - instead of truthvalue_conversion. + * method.c (build_template_decl_overload): Expect _DECL as first + parameter. Put context temporarily into current_namespace. + * pt.c (check_explicit_specialization): Change caller. + (tsubst): Likewise. - * class.c (finish_struct): A data member with the same name as the - class doesn't suppress constructors. + * init.c (build_offset_ref): Call mark_used and + convert_from_reference for namespace members. -Fri Jun 16 18:11:39 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu) +Mon Jul 13 23:25:28 1998 Martin von Lvwis - * decl.c (start_function): If current_class_decl is a signature - pointer, don't dereference it but set C_C_D to current_class_decl. + * search.c (my_tree_cons): The bitfield is at index 2. -Fri Jun 16 17:06:28 1995 Jason Merrill +Mon Jul 13 17:21:01 1998 Nick Clifton - * decl.c (duplicate_decls): Complain about virtual functions - redeclared to be inline. + * lang-options.h: Format changed to work with new --help support + in gcc/toplev.c + +1998-07-12 Martin von Löwis + + * decl2.c (build_expr_from_tree): Change calls of do_identifier. + Do Koenig lookup in CALL_EXPR. + (arg_assoc): Handle error_mark. + * lex.c (is_global): New function. + (do_identifier): Expect arguments for Koenig lookup. + * parse.y (primary): Add rules for calls of unqualified function calls. + (do_id): Change call of do_identifier. + * pt.c (finish_stmt_expr): Likewise. + * semantics.c (finish_id_expr): Likewise. + (finish_call_expr): Add integer parameter to indicate + argument-dependent lookup. + + * decl.c (struct binding_level): New field using_directives. + (push_using_decl): Not sorry anymore. + (push_using_directive): New function. + (lookup_tag): Use CP_DECL_CONTEXT to iterate. + (unqualified_namespace_lookup): New function, code from ... + (lookup_name_real): ... here. + * decl2.c (lookup_using_namespace): Pass using list instead of + initial scope. + (validate_nonmember_using_decl): New function. + (do_nonmember_using_decl): New function. + (do_toplevel_using_decl): Use them. + (do_local_using_decl): New function. + (do_using_directive): Support block-level directives. + * parse.y (simple_stmt): Support using declarations and + directives. + (namespace_qualifier, namespace_using_decl): New non-terminals. + + * xref.c (classname): New function. + (GNU_xref_hier): Change class and base parameters to tree. + * decl.c (xref_baseypes): Change caller. + * friend.c (make_friend_class): Likewise. + +1998-07-12 Kriang Lerdsuwanakij + + * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter + comparison. + + * 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 + its template arguments if exists. + + * pt.c (coerce_template_template_parms): New function equivalent + to coerce_template_parms when IS_TMPL_PARM is true. + (coerce_template_parms): Use it. Remove the IS_TMPL_PARM parameter, + all callers changed. + + (coerce_template_parms): Access ARGLIST properly when creating a + new vector. Only accept implicit TYPE_DECL as valid argument for + a template template parameter when it is a base class of + current_class_type. Don't display error message when COMPLAIN is + false. + +1998-07-12 Klaus Kaempf (kkaempf@progis.de) + + * repo.c (get_base_filename): Use file_name_nondirectory. + (open_repo_file): Ditto. + * cp-tree.h (file_name_nondirectory): Add prototype. + +1998-07-12 Jason Merrill + + * friend.c (do_friend): Pull the identifier out of declarator. + Use cp_error and friends. + * 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. + * cvt.c (convert_pointer_to_real): Check for error_mark_node sooner. + * 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. + +Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com) + + * g++.1 (-traditional): Remove duplicated documentation. + +1998-07-11 Mark Mitchell + + * method.c (flush_repeats): Add nrepeats parameter. + (issue_nrepeats): Likewise. + (is_back_referenceable_type): New function. Don't back-reference + TEMPLATE_TYPE_PARMs as well as simple types like integers. + (build_mangled_name_for_type): Likewise. + (build_mangled_name_for_type_with_Gcode): Likewise. + (lasttype): Remove. + (nrepeats): Likewise. + (Nrepeats): Likewise. + (start_squangling): Don't clear the variables removed above. + (end_squangling): Likewise. + (flush_repeats): Tidy. Use nrepeats parameter rather than + Nrepeats global. + (issue_nrepeats): Likewise, but with nrepeats global. Use + is_backreferenceable_type. + (build_overload_nested_name): Tidy. Add comment. Use + build_mangled_name_for_type. + (build_underscore_int): Comment. + (build_overload_scope_ref): Use build_mangled_name_for_type. + (build_overload_int): Likewise. + (build_template_template_parm_names): Tidy. + (build_template_parm_names): Use build_mangled_name_for_type. + (build_overload_identifier): Add comments. + (build_mangled_name_for_type_with_Gcode): Split out from + build_mangled_name. + (build_mangled_name_for_type): Use it. + (build_mangled_name): Rework to use build_mangled_name_for_type + and to not use global nrepeats/Nrepeats. Tidy. + (process_modifiers): Tidy. + (check_btype): Use is_backreferenceable_type. Add comment. + Rename `node' to `type'. + (process_overload_item): Set numeric_output_need_bar here. + Use build_mangled_name_for_type. Tidy. + (build_decl_overload_real): Tidy. Don't use Nrepeats. Use + build_mangled_name_for_type. + + * pt.c (push_template_decl_real): Don't look at DECL_TEMPLATE_INFO + for TYPE_DECLs. + +1998-07-08 Vladimir N. Makarov + + * cp-tree.h (warn_long_long): Define. + * decl.c (grokdeclarator): Add flag `warn_long_long' as guard for + warning "ANSI C++ does not support `long long'". + * decl2.c (warn_long_long): Define. + (lang_decode_option): Parse -Wlong-long, -Wno-long-long options. + +1998-07-07 Jason Merrill + + * decl.c (xref_tag): Handle attributes between 'class' and name. + * parse.y (aggr): Likewise. + * semantics.c (finish_class_definition): Likewise. + * Makefile.in (EXPECTED): Adjust. + + * cp-tree.h: Declare flag_optional_diags and warn_multichar. + * 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 + name if -fno-optional-diags. + * decl.c (pushdecl_class_level): Likewise. + * lex.c (real_yylex): Check warn_multichar. + +1998-07-06 Jason Merrill + + * decl.c (lookup_tag): Use CP_DECL_CONTEXT. + + * tree.c (make_binfo): Fix length. + +1998-06-30 Benjamin Kosnik + + * decl2.c (lang_decode_option): Remove warn_template_debugging. + * lang-options.h: Ditto. -Fri Jun 16 13:20:38 1995 Mike Stump +Mon Jun 29 20:17:40 1998 Kaveh R. Ghazi + + * except.c (build_eh_type_type_ref): Remove unused variable `susp'. + (process_start_catch_block): Likewise for variables + `false_label_rtx', `call_rtx' and `return_value_rtx'. + +1998-06-29 Brendan Kehoe + + * tree.c (build_srcloc): Make sure we allocate this node on the + permanent obstack. + +Sat Jun 27 23:34:18 1998 Fred Fish + + * g++spec.c (NEED_MATH_LIBRARY): Define to 1 if not already defined. + (lang_specific_driver): Initialize need_math with NEED_MATH_LIBRARY. + (lang_specific_driver): Only add -lm automatically if need_math is + nonzero. - * decl.c (get_unique_name): New routine to name unnamed namespaces. - (push_namespace): Use get_unique_name for naming unnamed namespaces. +Sat Jun 27 12:22:56 1998 Jeffrey A Law (law@cygnus.com) -Fri Jun 16 15:07:29 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o - * Make-lang.in (DEMANGLER_PROG): Add LIBS. +Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi -Thu Jun 15 15:00:41 1995 Jason Merrill + * Makefile.in (EXPR_H): New dependency variable. + (decl2.o): Depend on $(EXPR_H). + (typeck.o): Likewise. + (init.o): Likewise. + (expr.o): Likewise. + +1998-06-25 Benjamin Kosnik - * decl.c (define_function): Don't set DECL_INTERFACE_KNOWN. + * decl.c (start_enum): Put local enums on permanent_obstack. - * parse.y: Call cplus_decl_attributes with prefix_attributes where - appropriate. +1998-06-25 Mark Mitchell -Wed Jun 14 19:24:49 1995 Mike Stump + * cp-tree.h (c_get_alias_set): Declare. + * decl.c (init_decl_processing): Set lang_get_alias_set. - * search.c (get_vbase): New routine to switch hierarchies from the - CLASSTYPE_VBASECLASSES to the normal one. - (expand_indirect_vtbls_init): Use get_vbase to figure out how we - want to convert to a vbase pointer. +1998-06-25 Andrew MacLeod -Mon Jun 12 17:50:30 1995 Jason Merrill + * 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. + * 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. - * pt.c (instantiate_class_template): Add the new instantiation to - template_classes. - (do_pending_expansions): Call instantiate_member_templates on all of - the classes in template_classes. +1998-06-25 Dave Brolley -Mon Jun 12 12:36:59 1995 Mike Stump + * lang-specs.h: Use new | syntax to eliminate + string concatenation. - * decl.c (complete_array_type): Fill in the TYPE_DOMAIN of our - TYPE_MAIN_VARIANT if it is not filled in. - * init.c (build_delete): If the TYPE_DOMAIN is not set, give an - error instead of core dumping. +1998-06-25 Jason Merrill -Mon Jun 12 10:41:40 1995 Jason Merrill + * cp-tree.h (CP_DECL_CONTEXT): New macro. + * decl2.c (is_namespace_ancestor, lookup_using_namespace): Use it. + * method.c (build_overload_nested_name): Likewise. + * sig.c (build_signature_pointer_or_reference_type): Don't set + DECL_CONTEXT. - * call.c (can_convert): Also check for distance > 0. - (can_convert_arg): Ditto. - (user_harshness): Ditto. +1998-06-24 Martin v. Löwis -Fri Jun 9 19:17:21 1995 Jason Merrill + Set DECL_CONTEXT for globals to NULL_TREE instead of global_namespace. + * cp-tree.h (FROB_CONTEXT): New macro. + (DECL_MAIN_P): ::main should have a DECL_CONTEXT of NULL_TREE. + * decl.c (namespace_binding): Replace NULL_TREE with + global_namespace. + (set_namespace_binding, pop_namespace, lookup_name_real): Likewise. + * decl2.c (is_namespace_ancestor, lookup_using_namespace): + Likewise. + * decl.c (pushtag): Use FROB_CONTEXT. + (pushdecl, make_typename_type, define_function, grokdeclarator): + Likewise. + * decl2.c (set_decl_namespace, do_namespace_alias): Likewise. + * pt.c (push_template_decl_real, lookup_template_class, tsubst): + Likewise. + * decl2.c (decl_namespace): Return global_namespace if no context. + * method.c (build_overload_nested_name): Expect null as context. + * pt.c (mangle_class_name_for_template): Do nothing for null + contexts. + (lookup_template_class): Allow for null id_context. - * g++.c (MATH_LIBRARY): Provide default. - (main): Always link with the math library if we link with libstdc++. +1998-06-25 Richard Henderson - * decl.c (start_function): Complain about redefinition of a function - even when the pending_inline version is compiled after the other - version. + * method.c (emit_thunk): Set current_function_is_thunk for the + ASM_OUTPUT_MI_THUNK case as well. -Thu Jun 8 15:44:38 1995 Jason Merrill +1998-06-23 Andrew MacLeod - * gc.c (build_dynamic_cast): Build up a reference to a parameter of - aggregate type. + * exception.cc (__cplus_type_matcher): Get a match_info pointer + instead of an exception table entry as a parameter. -Wed Jun 7 20:00:31 1995 Mike Stump +1998-06-23 Andrew MacLeod - * *.[chy]: Change all callers of finish_decl to cp_finish_decl. - * decl.c (finish_decl): New routine to handle call backs from the - mid end (declare_hidden_char_array). + * parse.y (function_try_block): Don't call start_catch_handler. + * except.c (call_eh_info): Remove coerced field from declaration. + (build_eh_type_type_ref): New function to create an address of a + rtti function for the new style exception tables. + (expand_start_catch_block): Split function, this contains the + common part. + (process_start_catch_block_old): New function to perform the rest + of expand_start_catch_block under old style exceptions. + (process_start_catch_block_old): New function to perform the rest + of expand_start_catch_block under new style exceptions. + (expand_end_catch_block): Only pop the false label off the stack under + the old style of exceptions. + * semantics.c (finish_try_block): Don't call start_catch_handler. + * 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. -Wed Jun 7 19:02:50 1995 Jason Merrill +1998-06-23 Jason Merrill - * decl.c (start_function): Handle setting C_C_D here. - (set_C_C_D): Removed. - (struct saved_scope): Remove class_decl. - (push_to_top_level): Don't save current_class_decl. - (pop_from_top_level): Don't restore current_class_decl or C_C_D. - (struct cp_function): Add C_C_D. - (push_cp_function_context): Save C_C_D. - (pop_cp_function_context): Restore C_C_D. + * call.c (joust): Fix confusing conversion warning. -Wed Jun 7 15:31:57 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * call.c (build_op_delete_call): Add placement parm. Check + LOOKUP_SPECULATIVELY. + * cp-tree.h, decl2.c, init.c: Adjust. + * decl.c (finish_function): Use it. - * init.c (build_vec_delete): Resolve an offset ref before we try to - use it. + * pt.c (tsubst): Diagnose creating void fields or variables. -Wed Jun 7 14:19:32 1995 Jason Merrill +Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi - * typeck.c (build_modify_expr): If the class lacks a constructor or - assignment operator, return error_mark_node. - (common_type): Use build_cplus_array_type. + * call.c (build_scoped_method_call): Remove unused variable `tmp'. -Tue Jun 6 09:41:27 1995 Mike Stump + * cp-tree.h (check_dtor_name): Add prototype. - * class.c (dont_allow_type_definitions): New variable set when types - cannot be defined. - (finish_struct): Use it. - * cp-tree.h (dont_allow_type_definitions): Define it. - * parse.y (primary, handler_seq): Set it. + * init.c (expand_member_init): Remove unused variables + `ptr_type_node', `parm' and `rval'. -Mon Jun 5 18:49:38 1995 Mike Stump + * ptree.c (print_lang_type): Use HOST_WIDE_INT_PRINT_DEC specifier + in call to fprintf. + (lang_print_xnode): Likewise. - * method.c (build_opfncall): Use DECL_CHAIN, not TREE_CHAIN for - results from lookup_fnfields. Always give warning/error on bad - code. + * typeck2.c (enum_name_string): Cast argument to sprintf to long + and use %ld specifier. -Mon Jun 5 11:39:37 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * init.c (member_init_ok_or_else): Don't allow initialization of - an ancestor's member from within a constructor. - -Mon Jun 5 11:20:34 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu) - - * sig.c (build_signature_table_constructor): Use DECL_CONTEXT - instead of DECL_CLASS_CONTEXT for calculating the vfield offset so - abstract virtual functions are handled correctly. - - * sig.c (build_signature_table_constructor): Store the correct - delta in signature table entries. It does not yet work for - classes with virtual base classes as implementations of signatures. - (build_signature_method_call): Add the delta to the object_ptr - before generating the function call. - - * call.c (build_method_call): Make instance_ptr the signature - pointer itself instead of dereferencing the optr. - * sig.c (build_signature_method_call): Dereference the optr for the - direct and virtual calls. - - * sig.c (build_signature_table_constructor): Make the tag for - default implementations -1 instead of 2. - (build_signature_method_call): Change the generated conditional - expression correspondingly. - - * sig.c (build_signature_pointer_constructor): Deleted the sorry - message that said we can't handle multiple inheritance for - implementations of signatures - (build_signature_method_call): Use the offset from the sigtable - entry instead of the vptr field from the signature pointer for - building a virtual function call. - - * class.c (build_vfn_ref): Deleted signature specific code, we don't - call this function anymore from build_signature_method_call. - - * cp-tree.h (SIGNATURE_VPTR_NAME): Deleted. We use the right vptr - field in the object now instead of in the signature pointer/ref. - (build_vptr_ref): Deleted extern declaration. - * sig.c (build_vptr_ref): Deleted. - (build_signature_pointer_or_reference_type): Deleted construction of - the vptr field. - (build_signature_pointer_constructor): Deleted initialization of/ - assignment to the vptr field. - - * sig.c (build_signature_table_constructor): Convert the signature - table entry fields to their correct types. - - * sig.c (build_signature_table_constructor): Don't call digest_init - for the fields of a sigtable entry, it's wasted time. - - * sig.c (build_signature_table_constructor): Correctly set the - offset and index fields of a sigtable entry. Build the constructor - the way digest_init does, digest_init can't handle initializing an - anonymous union inside a struct. - (build_signature_method_call): Use the index field instead of the - delta field to get the vtable index. - - * decl.c (init_decl_processing): Fix number of fields for building - sigtable_entry_type. - - * cp-tree.h (tag_identifier, offset_identifier): Added extern decls. - (SIGTABLE_CODE_NAME): Renamed to SIGTABLE_TAG_NAME. - (SIGTABLE_PFN_NAME): Deleted, we'll use VTABLE_PFN_NAME instead. - * decl.c (tag_identifier, offset_identifier): New variables to - hold the identifiers for the sigtable fields tag and offset. - (init_decl_processing): Initialize these variables. - (init_decl_processing): Use these variables to build the - sigtable_entry_type structure. Rename the code and offset fields - to tag and delta, respectively; add offset and index fields. Changed - types of fields from short_integer_type_node to delta_type_node. - * sig.c (build_signature_table_constructor): Rename code and offset - to tag and delta, respectively. - (build_signature_method_call): Ditto. Use above variables. - -Fri Jun 2 11:05:58 1995 Jason Merrill - - * decl.c (set_C_C_D): New function. suspend_momentary before - building C_C_D. - (pop_from_top_level): Call it. - (start_function): Ditto. - (pop_cp_function_context): Ditto. + * xref.c (GNU_xref_end_scope): Use HOST_WIDE_INT_PRINT_DEC + specifier in call to fprintf. + (GNU_xref_member): Cast argument to sprintf to int. - * class.c, cp-tree.h, decl.c, decl2.c, parse.y: Lose all references - to current_vtable_decl, CLASSTYPE_INST_VAR and CLASSTYPE_VTBL_PTR. +Fri Jun 19 23:22:42 1998 Bruno Haible - * decl.c (push_cp_function_context): Save current_class_decl. - (pop_cp_function_context): Restore current_class_decl and set C_C_D. - (pop_from_top_level): Don't use CLASSTYPE_INST_VAR to set C_C_D. - (start_function): Ditto. + * typeck2.c (pop_init_level): Warn about implicit zero initialization + of struct members. - * class.c (popclass): Don't mess with current_class_decl, - current_vtable_decl, or C_C_D. +Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi -Mon May 29 12:45:10 1995 Paul Eggert + * cp-tree.h: Prototype function `check_java_method'. - * Make-lang.in (c++.mostlyclean): Remove $(DEMANGLER_PROG). +1998-06-17 Jason Merrill -Thu Jun 1 17:03:51 1995 Jason Merrill + * class.c (finish_struct): Make conflicting use of id a pedwarn. + * decl.c (pushdecl_class_level): Likewise. - * decl.c (lookup_name_real): Don't try to look anything up in an - erroneous object. +1998-06-17 Mark Mitchell -Fri Jun 2 10:30:14 1995 Mike Stump + * pt.c (convert_nontype_argument): Issue an error when presented + with an integer (real) constant that cannot be simplified to an + INT_CST (REAL_CST). - * method.c (build_overload_int): New routine. Break out - functionality from build_overload_value so we can reuse it. - (build_overload_value): Handle pointer to member functions as value - parameters for templates. - (build_overload_identifier): Since template parameters are shared - among all instantiations, we have to substitute in the real types - in TREE_TYPE (parm). - pt.c (coerce_template_parms): Ditto. - (push_template_decls): Ditto. - (grok_template_type): Deleted as template parameters are shared - among all instantiations. + * cp-tree.h (c_get_alias_set): Remove declaration added in + 1998-06-13 change that should never have been checked in. -Wed May 31 19:10:32 1995 Mike Stump +1998-06-17 Jason Merrill - * decl.c (grokdeclarator): Always give errors on constant overflow - for array indices. + * typeck.c (build_binary_op_nodefault): Change % in format strings + to %%. -Wed May 31 11:39:43 1995 Jason Merrill + * decl.c (grokvardecl): Don't build_static_name for decls that + aren't at namespace scope. - * typeck.c (commonparms): Don't abort if simple_cst_equal returns < 0. - (build_c_cast): Don't tack on a NON_LVALUE_EXPR when casting to - reference type. - (build_indirect_ref): Fix check for *&. + * init.c (perform_member_init): Catch default-initialization of + references. -Wed May 24 15:55:18 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +1998-06-17 Mark Mitchell - * decl.c (duplicate_decls): Check simple_cst_equal result against 0. - * decl2.c (finish_anon_union): Likewise. - * method.c (largest_union_member): Likewise. + * errfn.c (cp_thing): Handle the `%%' formatting sequence. -Wed May 24 14:41:11 1995 H.J. Lu (hjl@nynexst.com) +1998-06-17 Jason Merrill - * Make-lang.in (cxxmain.o): Replace single quotes with backslashes. + * method.c (hack_identifier): Complain about getting a namespace + or class template. + * typeck.c (decay_conversion): Remove check for namespaces. + * typeck2.c (incomplete_type_error): Likewise. + * parse.y (template_arg): Add PTYPENAME expansion. -Mon May 22 17:38:48 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) +1998-06-16 Andrew MacLeod - * Make-lang.in (g++, g++-cross, cc1plus, DEMANGLER_PROG): - Use $@ instead of output name so works even if have .exe. - (cxxmain.o): Use cp if ln -s fails. - (c++.install-man): Use $(exeext) in executable names. - (c++.mostlyclean, stage[1-4]): Use $(objext) in object file names. - * Makefile.in (../cc1plus): Use $(exeext) in name of executable. + * 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. -Wed May 24 01:39:03 1995 Jason Merrill +1998-06-16 Jason Merrill - * call.c (build_method_call): parms can be null, duh. + * call.c (check_dtor_name): Split out. + (build_scoped_method_call): Use it. + (build_method_call): Use it. + * init.c (build_offset_ref): Use it. -Tue May 23 01:32:09 1995 Jason Merrill + * typeck.c (build_static_cast): Fix handling of pointers to members. - * call.c (build_method_call): If convert_arguments failed, just bail. + * decl.c (finish_function): Just return nothing from a constructor. + * typeck.c (c_expand_return): Complain about returning a void + expression from a destructor. -Fri May 19 10:31:11 1995 Jason Merrill +1998-06-13 Mark Mitchell - * cvt.c (convert_force): Pass LOOKUP_NORMAL to cp_convert. + * class.c (alter_access): Accept a BINFO explaining how to get + from the entity whose accessed is being altered to the type doing + the altering. + (handle_using_decl): New function containing code split out from ... + (finish_struct_1): Here. - * tree.c (copy_to_permanent): Oops. + * cp-tree.h (complete_type_or_else): Declare. + * init.c (build_new_1, build_delete): Use it. + * typeck.c (require_complete_type): Use complete_type, rather than + expanding it inline. + (complete_type_or_else): New function. + (build_component_ref): Use it. + (pointer_int_sum): Make sure the type pointed to is complete. + (pointer_diff): Likewise. -Fri May 19 10:01:07 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * pt.c (for_each_template_parm): Traverse the TYPE_CONTEXT for + types. - * cp-tree.h (break_out_target_exprs): Add decl. + * search.c (get_matching_virtual): Note that member templates + cannot override virtual functions. -Thu May 18 13:02:30 1995 Jason Merrill +1998-06-12 Brendan Kehoe - * decl.c (start_function): Move *all* interface handling stuff after - the pushdecl. + * pt.c (check_explicit_specialization): If DECLARATOR turned into + an error_mark_node from lookup_template_function, return the same. + (determine_specialization): Also make sure TEMPLATE_ID isn't an + error_mark_node, before we try to read its operands. + * decl.c (grokdeclarator): If we got an error_mark_node from + check_explicit_specialization, just return it right back. - * tree.c (mapcar): Renamed from make_deep_copy and generalized. - (perm_manip): Return t if permanent, otherwise 0. - (copy_to_permanent): Use them. - (bot_manip): Helper for break_out_target_exprs. - (break_out_target_exprs): New function. Uses mapcar. +1998-06-12 Mark Mitchell - * typeck.c (convert_arguments): Use it. + * class.c (instantiate_type): Don't treat template-ids that don't + specify any template arguments as equivalent to ordinary + identifiers. Use OFFSET_REF instead of SCOPE_REF to refer to + pointer-to-members for member templates. Tidy slightly. + * cp-tree.def (TEMPLATE_ID_EXPR): Revise documentation. + * init.c (build_offset_ref): Handle template-ids like ordinary + identifiers, for the most part, but store a TEMPLATE_ID_EXPR in the + offset part of the OFFSET_REF. + * typeck.c (build_unary_op): Change check for unknown types to + look for OFFSET_REFs, not SCOPE_REFs. - * method.c (hack_identifier): Use convert_from_reference to - dereference a reference. +1998-06-11 Mark Mitchell -Wed May 17 17:54:54 1995 Mike Stump + * pt.c (is_member_template_class): New function. + (push_template_decl_real): Use it. - * call.c (convert_harshness): Move reference bashing before pointer - to member bashing. +1998-06-11 Benjamin Kosnik -Wed May 17 16:57:53 1995 Mike Stump + * friend.c (do_friend): Add support for nested classes using + member functions of the enclosing class as friends. - * cvt.c (convert_to_reference): Only complain, if complaints are - wanted. - * typeck.c (build_function_call_real): Ditto. If LOOKUP_SPECULATIVELY - is set and something won't work, return NULL_TREE. - * cvt.c (cp_convert): Ditto. Pass flags down to build_method_call. - (convert): Pass LOOKUP_NORMAL to cp_convert. - * typeck.c (convert_for_assignment): Ditto. - (convert_force): Pass LOOKUP_COMPLAIN to cp_convert. - (convert_arguments): Get out early if we get an error_mark_node. - (convert_for_initialization): Use cp_convert instead of convert so - that we can pass flags down. - * cp-tree.h (LOOKUP_SPECULATIVELY): Added documentation. +1998-06-10 Mark Mitchell -Wed May 17 01:43:58 1995 Jason Merrill + * call.c (convert_default_arg): Make global, not static. + (convert_arg_for_ellipsis): Split out from ... + (build_over_call): Here. + * cp-tree.h (convert_default_arg); Declare. + (convert_arg_to_ellipsis): Likewise. + (do_member_init): Remove. + * init.c (do_member_init): Remove; this code is dead. + (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 + for failure. - * typeck2.c (store_init_value): Don't take the MAIN_VARIANT of the - decl type. +1998-06-10 Jason Merrill - * class.c (finish_struct): Don't complain about a class with no - user-defined constructors but with a member that has no default - constructor, as this is OK for aggregates. + * search.c (covariant_return_p): Complain about ambiguous base. - * expr.c (cplus_expand_expr, NEW_EXPR): If this is an explicit - constructor call, mark slot addressable. + * typeck.c (build_component_ref): Diagnose ref to nested type. -Tue May 16 18:37:51 1995 Douglas Rupp (drupp@cs.washington.edu) +1998-06-10 Brendan Kehoe - * g++.c: Changed WINNT to _WIN32. + * decl.c (grokparms): Check that INIT isn't an error_mark_node + before giving error about invalid type for default arg. -Tue May 16 12:40:16 1995 Jason Merrill +1998-06-10 Jason Merrill - * lex.c (handle_sysv_pragma): Don't use token_buffer. + * call.c (build_method_call): Fix thinko. -Tue May 16 12:05:26 1995 Mike Stump +1998-06-10 Dave Brolley - * call.c (resolve_scope_to_name): Add initial semantic support for - namespaces. - * class.c (finish_struct): Ditto. - * cp-tree.h (NAMESPACE_LEVEL): Ditto. - * cvt.c (build_up_reference, convert_to_reference): Ditto. - * decl.c (binding_level::namespace_p, suspend_binding_level): Ditto. - (resume_binding_level, toplevel_bindings_p): Ditto - (namespace_bindings_p, declare_namespace_level): Ditto. - (resume_level, push_namespace, pop_namespace): Ditto. - (pop_everything, pushtag, duplicate_decls, pushdecl): Ditto. - (implicitly_declare, lookup_namespace_name, lookup_name_real): Ditto. - (start_decl, make_temporary_for_reference), Ditto. - (obscure_complex_init, finish_decl, expand_static_init): Ditto. - (grokvardecl, grokdeclarator, parmlist_is_exprlist): Ditto. - (store_parm_decls, hack_incomplete_structures): Ditto. - * decl2.c (get_temp_name, finish_anon_union, current_namespace): Ditto. - (push_namespace, pop_namespace, do_namespace_alias): Ditto. - (do_toplevel_using_decl, do_class_using_decl): Ditto. - * error.c (dump_decl): Ditto. - * init.c (build_member_call, build_offset_ref): Ditto. - * lex.c (identifier_type): Ditto. - * parse.y (lang_extdef, using_decl, extdef, component_decl_1): Ditto. - (nested_name_specifier_1): Ditto. - * spew.c (yylex): Ditto. - * tree.def (NAMESPACE_DECL): Ditto. + * decl2.c (lang_decode_option): New argc/argv interface. + * cp-tree.h (lang_decode_option): New argc/argv interface. + * lang-specs.h (default_compilers): Only call cpp if -E, -M or -MM is + specified for cpplib-enabled compilers. + * lex.c (lang_init): Don't check_newline for cpplib. + (init_parse): Don't initialize cpplib here. -Tue May 16 11:55:35 1995 Jason Merrill +1998-06-10 Brendan Kehoe - * decl.c (push_overloaded_decl): Return the new decl even if it - can't be pushed. + * typeck.c (build_component_ref): Make sure FIELD has a lang_specific + piece before checking DECL_MUTABLE_P. -Tue May 16 11:00:37 1995 Jason Merrill +1998-06-10 John Carr - * typeck.c (decay_conversion): Split out from default_conversion. - (default_conversion): Call it. - (build_binary_op): Ditto. - (build_binary_op_nodefault): Use decay_conversion for truth ops. + * tree.c (debug_binfo): Make printf format match arguments. -Mon May 15 12:47:56 1995 Jason Merrill + * error.c (OB_PUTI): Make printf format match arguments. - * decl.c (warn_extern_redeclared_static): This is a pedwarn. - (duplicate_decls): Always use the old decl's linkage info. Don't - play with linkage of consts. - (pushdecl): Don't play with linkage of consts. - (redeclaration_error_message): Don't complain about an old public - decl and a new non-public decl here. - (grokvardecl): Handle linkage of consts here. - (grokdeclarator): An 'extern inline' is public. Pass constp to - grokvardecl. - (start_function): Wait until after the pushdecl to do some linkage - stuff. +1998-06-10 Jason Merrill - * decl2.c (import_export_vtable): Make duplicates weak rather than - static if supported. - (import_export_inline): Ditto. - * pt.c (do_pending_expansions): Ditto. + * init.c (perform_member_init): Handle default-initialization. - * class.c (build_vbase_path): flag_assume_nonnull_objects only - affects reference conversion. + * except.c (build_throw): Handle throwing NULL. - * init.c (emit_base_init): Build up an RTL_EXPR and add it to - rtl_expr_chain. - * decl.c, decl2.c: s/base_init_insns/base_init_expr/. + * typeck.c (build_x_function_call): Use resolve_offset_ref. -Tue May 16 07:06:28 1995 Paul Eggert + * search.c (compute_access): Only strip an anonymous union + for a FIELD_DECL. - * method.c (numeric_output_need_bar): Renamed from misspelling. + * call.c (add_builtin_candidates): Tweak. - * typeck.c (build_ptrmemfunc): Fix misspellings in messages. + * cvt.c (build_expr_type_conversion): Restore code for conversion + from class types. + * decl2.c (delete_sanity): Use it. Clean up. -Sun May 14 10:26:22 1995 Richard Kenner + * typeck.c (comp_ptr_ttypes_real): Fix cv-qual comparisons. - * lang-options.h, lang-specs.h: New files. +1998-06-10 Branko Cibej -Thu May 11 00:31:48 1995 Jason Merrill + * typeck.c (c_expand_return): Don't warn about void expressions on + return statements in functions returning void. - * typeck.c (default_conversion): Don't check for BLKmode before - pulling out the decl_constant_value. +1998-06-09 Mark Mitchell - * decl.c (start_function): Clear named_labels and shadowed_labels. + * pt.c (fn_type_unification): Revise documentation. Tidy. + (type_unification): Likewise. - * typeck.c (build_function_call_real): Also synthesize methods here. +1998-06-09 Andrew MacLeod -Wed May 10 00:55:59 1995 Jason Merrill + * semantics.c (finish_try_block): Rename expand_start_catch, and delete + expand_end_catch. + * parse.y (function_try_block): Rename expand_start_catch, and delete + expand_end_catch. + * except.c (expand_end_eh_spec): Rename expand_start_catch, and delete + expand_end_catch. - * decl2.c (finish_file): Synthesize exported methods before the - reconsider loop. +1998-06-09 Jason Merrill - * parse.y: Move declaration of flag_new_for_scope to file scope. + * search.c (lookup_member): New fn. + * class.c (finish_struct_1): Use it. + * decl.c (lookup_name_real): Use it. -Tue May 9 19:10:33 1995 Mike Stump +Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi - * decl2.c: Add flag_new_for_scope for new -ffor-scope flag. - * parse.y (FOR): Conditionalize the pushing and poping of scope for - the for-init-statement upon the new flag_new_for_scope. - * parse.y (try_block): Simplify and use compstmt. + * Makefile.in (decl2.o): Depend on dwarf2out.h and dwarfout.h. -Mon May 8 12:41:52 1995 Jason Merrill + * cp-tree.h: Add prototype for `maybe_print_template_context' and + `maybe_make_one_only'. - * decl.c (define_function): Mark function decl artificial. + * decl.c (auto_function): Remove unused variable `decl'. -Sun May 7 00:51:28 1995 Jason Merrill + * decl2.c: Include dwarf2out.h and dwarfout.h. - * parse.y (simple_stmt, FOR): Put back push/pop for condition scope. + * lex.c: Remove redundant declarations of `set_float_handler' and + `asm_out_file'. - * decl2.c (grokclassfn): DECLs don't have cv-qualified types. - * tree.c (build_cplus_method_type): Ditto. +1998-06-08 Andrew MacLeod - * cp-tree.h (SET_DECL_ARTIFICIAL): Just set DECL_ARTIFICIAL to 1. + * 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 + 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 + __cp_eh_info instead of __cp_exception_info. - * typeck.c (build_function_call_real): If convert_arguments failed, - just bail. - (convert_arguments): If one of the arguments is error_mark_node, - just bail. +1998-06-08 Jason Merrill -Sat May 6 02:39:41 1995 Jason Merrill + * decl.c (cp_finish_decl): Disable inlining of extern inlines + with static variables. - * decl.c (duplicate_decls): Don't check DECL_NOT_REALLY_EXTERN for - decls that don't include it. +1998-06-08 Mark Mitchell -Fri May 5 14:23:30 1995 Jason Merrill + * init.c (build_offset_ref): Correct previous change to use build, + not build_min. - * decl.c (duplicate_decls): Decls that have DECL_INTERFACE_KNOWN or - DECL_NOT_REALLY_EXTERN set aren't extern decls. +1998-06-07 Mark Mitchell - * typeck.c (build_indirect_ref): Don't call default_conversion for a - parameter of reference_type. - * cvt.c (convert_from_reference): Just use build_indirect_ref. + * class.c (instantiate_type): Handle pointer-to-members where the + member is a template. + * init.c (build_offset_ref): Likewise. + * typeck.c (build_unary_op): Likewise. - * pt.c (do_type_instantiation): Only instantiate member functions - that actually come from templates. +1998-06-07 Richard Henderson -Fri May 5 09:46:05 1995 Mike Stump + * lex.c (lang_init_options): New function. + (lang_init): Remove flag_exceptions == 2 hack. + +1998-06-05 Jason Merrill - * parse.y: Generalized cleanup of poplevels, and compound statements - and compound statements in try blocks. Rewritten `for' rule so that - the scope of variables declared in the for clause is shortened to - span just to the end of the statement, instead of the whole - containing block. + * search.c (envelope_add_decl): Tweak for implicit typename. -Fri May 5 00:37:14 1995 Jason Merrill + * call.c (joust): Also warn about confusing conversion op/constructor + overload resolution. - * call.c (convert_harshness): Handle pointers to members better. + * spew.c (yylex): Also return the TYPE_DECL if got_object. + Don't clear got_object after '~'. + * call.c (build_scoped_method_call): Tweak destructor handling. + (build_method_call): Likewise. + * pt.c (tsubst_copy, case METHOD_CALL_EXPR): Don't mess with + TYPE_MAIN_VARIANT for destructors. + * semantics.c (finish_object_call_expr): Complain about calling a + TYPE_DECL. -Thu May 4 16:00:26 1995 Jason Merrill +1998-06-05 Per Bothner - * decl2.c (delete_sanity): Do access control here. - * init.c (build_delete): Instead of here. + * g++spec.c (lang_specific_pre_link, lang_specific_extra_ofiles): + Define - update needed by gcc.c change. - * Make-lang.in: Build c++filt. +1998-06-05 Jason Merrill -Wed May 3 02:59:53 1995 Jason Merrill + * error.c (cp_printers): Use 'o' instead of '_' for the null entry. - * decl2.c (cplus_decl_attributes): If we just modified a TYPE_DECL, - update our IDENTIFIER_TYPE_VALUE. +1998-06-05 Martin v. Loewis -Fri Apr 28 07:58:41 1995 Jason Merrill + * cp-tree.h (DECL_NAMESPACE_ALIAS, ORIGINAL_NAMESPACE): Declare. + * decl.c (lookup_name_real): Add namespaces_only parameter. + If set, return only NAMESPACE_DECLs. + (select_decl): Likewise. + (identifier_type_value): Give additional parameter. + (lookup_name_nonclass): Likewise. + (lookup_name): Likewise. + (find_binding): Skip namespace aliases. + (binding_for_name): Likewise. + (push_namespace): Check for namespace aliases. + (lookup_name_namespace_only): New function. + (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 + redeclaration. + * error.c (dump_decl): Support SCOPE_REF. + * parse.y (extdef): Wrap lookup with namespace_only for namespace + aliases and using declarations. - * lex.c (cons_up_default_function): Fix linkage of #pragma - implemented functions. +1998-06-04 Jason Merrill -Thu Apr 27 16:56:24 1995 Jason Merrill + * tree.c (really_overloaded_fn): Only see through one TREE_LIST. - * method.c (build_overload_name): Simplify and fix repeated type - folding. + * error.c (dump_expr): Clean up NEW_EXPR case. - * decl.c (grokdeclarator): Prohibit pointers to void or reference - members. +1998-06-04 Martin von Löwis -Thu Apr 27 09:49:07 1995 Mike Stump + Suggested by Brendan Kehoe + * decl2.c (do_toplevel_using_decl): When decl is a TYPE_DECL, + treat it as using ::decl. - * typeck2.c (process_init_constructor): Make sure initializers are - fully digested. + * decl2.c (arg_assoc_type): Process unknown_type_node and OFFSET_TYPE. -Thu Apr 27 01:11:55 1995 Jason Merrill + * tree.c (mapcar): Support NEW_EXPR. - * lex.c (cons_up_default_function): Always defer synthesis. + * error.c (dump_expr): Support NEW_EXPR. -Thu Apr 27 00:20:37 1995 Jason Merrill +1998-06-03 Jason Merrill - * decl2.c (mark_inline_for_output): Don't play with pending_inline - stuff. + * method.c (make_thunk): Use overload machinery to make name. + * search.c (covariant_return_p): New fn. + (get_matching_virtual): Use it. -Wed Apr 26 17:48:24 1995 Jason Merrill + * init.c (build_new_1): Fix check for void. - * call.c (user_harshness): New function; like build_type_conversion, - but doesn't actually build anything. - (compute_conversion_costs): Use it instead of build_type_conversion. +1998-06-01 Per Bothner -Wed Apr 26 17:11:25 1995 Jason Merrill + * cp-tree.h (TYPE_FOR_JAVA): New macro. + * decl.c, cp-tree.h (java_byte_type_node, java_short_type_node, + java_int_type_node, java_long_type_node, java_float_type_node, + java_double_type_node, java_char_type_node, java_boolean_type_node): + New "primitive" types, with predefined names __java_byte etc. + (record_builtin_java_type): New function. + (init_decl_processing): Make Java types with record_builtin_java_type. + (pushtag, grokdeclarator): Set TYPE_FOR_JAVA if in extern "JAVA". + (xref_baseypes): If base class was TYPE_FOR_JAVA, so is this class. + (grokfndecl): Call check_java_method for Java classes. + * method.c (is_java_type): Removed. Replaced with TYPE_FOR_JAVA. + (process_overload_item): Match types against specific + java_XX_type_node types, rather than using is_java_type. + * class.c (finish_struct_1): Don't add default copy constructor + or operator= if TYPE_FOR_JAVA. + (pop_lang_conext): Restore strict_prototyp proper if Java. + * decl2.c (acceptable_java_type, check_java_method): New functions. + * pt.c (instantiate_class_template): Copy TYPE_FOR_JAVA from pattern. + (tsubst): Move common statement after if statement. + * typeck.c (comptypes): If strict, TYPE_FOR_JAVA must match. - * typeck.c (build_function_call_real): Improve error message for - calling a non-function. +1998-06-01 Jason Merrill - * method.c (hack_identifier): Lose check for calling a data member. + * pt.c (for_each_template_parm): Use first_rtl_op. -Wed Apr 26 16:59:13 1995 Mike Stump + * tree.c (build_cplus_array_type_1): Also check index_type for + template parms. - * typeck2.c (build_functional_cast): Remove very old cruft. - Seems like good code is generated without it. +1998-05-31 Jason Merrill -Wed Apr 26 00:47:16 1995 Jason Merrill + * pt.c (tsubst): Always copy BINFO_BASETYPES. - * method.c (do_build_assign_ref): Fix handling of anonymous unions. - (do_build_copy_constructor): Ditto. +1998-05-29 scott snyder - * parse.y (simple_stmt, SWITCH): Call {push,pop}_switch. + * tree.c (layout_basetypes): If we change TYPE_SIZE, change + TYPE_SIZE_UNIT too. - * decl.c (push_switch): New function. - (pop_switch): Ditto. - (define_case_label): Check for jumping over initialization. +1998-05-29 Mark Mitchell - * call.c (build_method_call): Check for an inline function being - called before its definition has been seen. - * typeck.c (build_function_call_real): Ditto. + * decl.c (grokdeclarator): Don't complain about in-class + initialization of static consts if we don't really know the type + of the variable. - * decl.c (duplicate_decls): Check for a function being redeclared - inline after its address has been taken. +1998-05-29 Jason Merrill - * typeck.c (build_conditional_expr): Handle related class lvalues. + * cp-tree.h (DECL_DESTRUCTOR_P): New macro. + * 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 + vbases have the in_chrg parm. + * 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. -Tue Apr 25 13:20:45 1995 Jason Merrill +1998-05-28 Mark Mitchell - * pt.c (do_pending_expansions): Don't expand unused templates. + * pt.c (instantiate_decl): Make test for whether or not static + variables should be instantiated early match its comment. - * parse.y (component_decl): Accept a lone semicolon. +1998-05-28 Jason Merrill -Tue Apr 25 00:25:56 1995 Jason Merrill + * 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. + (check_default_args): Use cp_error_at. + * lex.c (do_pending_defargs): Call check_default_args. - * call.c (build_method_call): Don't allow an RTL_EXPR to serve as the - object parameter anymore. +1998-05-27 Brendan Kehoe - * expr.c (cplus_expand_expr): Don't create RTL_EXPRs with no insns. + * call.c (build_method_call): Make sure get_type_value returns + something before we try to use its TYPE_MAIN_VARIANT. + (build_scoped_method_call): Likewise. -Mon Apr 24 12:35:48 1995 Jason Merrill +1998-05-27 Jason Merrill - * parse.y (simple_stmt, decl case): Clear prefix_attributes. - (lang_extdef): Ditto. + * typeck2.c (digest_init): Complain about getting a TREE_LIST to + initialize an array. - * parse.y (maybe_parmlist): New rule for use in declarators where - this could either be a list of expressions or parameters. Calls - suspend_momentary before deciding which. - (direct_after_type_declarator): Use it. - (complex_direct_notype_declarator): Use it. + * search.c (expand_upcast_fixups): Don't set DECL_CONTEXT and + DECL_VIRTUAL_P. - * pt.c (tsubst): Propagate attributes const and noreturn. + * friend.c (do_friend): Clarify template warning. - * typeck.c (build_modify_expr): If warn_synth, call build_opfncall - before doing the default thing. +1998-05-27 Mark Mitchell -Thu Apr 27 21:49:36 1995 Doug Evans + * decl.c (shadow_label): Don't treat decls as identifiers. + (maybe_push_to_top_level): Clear shadowed_labels. - * typeck.c (common_type): Call lookup_attribute instead of - value_member. + * pt.c (instantiate_decl): Reset lineno and filename after calling + regenerate_decl_from_template. -Tue Apr 25 18:07:43 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + * decl.c (grokdeclarator): Don't try to use TYPE_OBSTACK on an + error_mark_node. - * Make-lang.in: Change "realclean" to "maintainer-clean". +1998-05-27 Kevin Buhr -Sun Apr 23 12:32:38 1995 Mike Stump + * parse.y (base_class): Use is_aggr_type, not IS_AGGR_TYPE. - * decl2.c (finish_file): Fix broken linked list handling. +1998-05-26 Kriang Lerdsuwanakij -Fri Apr 21 18:08:43 1995 Jason Merrill + * pt.c (process_template_parm): Accept TYPENAME_TYPE nodes. + (convert_nontype_argument): Handle cases when nontype template + parameters become classes after substitution. - * class.c (finish_base_struct): Don't set TYPE_HAS_COMPLEX_*_REF - as often. - (finish_struct): Ditto. +1998-05-26 Mark Mitchell - * various: Use TYPE_HAS_TRIVIAL_* instead of TYPE_HAS_COMPLEX_*. + * friend.c (is_friend): Use comptypes, rather than == to compare + types. Modify for new representation of template friends. + (make_friend_class): Likewise. + * pt.c (tsubst_friend_class): Undo 1998-05-21 change. Tweak. + (instantiate_class_template): Deal with template friends. - * cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): New macro. - (TYPE_HAS_TRIVIAL_ASSIGN_REF): New macro. + * decl.c (store_parm_decls): Remove redundant call to + expand_main_function. -Fri Apr 21 15:52:22 1995 Jason Merrill +1998-05-26 Benjamin Kosnik - * typeck.c (c_expand_return): Only expand a returned TARGET_EXPR if - it is of the same type as the return value. + * decl.c (start_decl): Check for DECL_LANG_SPECIFIC before + DECL_USE_TEMPLATE. -Fri Apr 21 03:01:46 1995 Jason Merrill +1998-05-26 Per Bothner - * decl2.c (finish_file): Reconsider if synthesizing a method wrote - out its assembly. + * language_as_string: Handle lang_java. - * typeck.c (convert_for_initialization): Don't call a trivial copy - constructor. +1998-05-26 Jason Merrill - * typeck2.c (store_init_value): Only abort if the type has a - non-trivial copy constructor. + * decl.c (pushdecl): Don't copy the type_decl. - * typeck.c (c_expand_return): If we're returning in a register and - the return value is a TARGET_EXPR, expand it. Only do - expand_aggr_init if we're returning in memory. - (expand_target_expr): Function to expand a TARGET_EXPR. - (build_modify_expr): Use it. +1998-05-26 Martin v. Löwis - * tree.c (build_cplus_new): Layout the slot. + * class.c (pushclass): Always store TYPE_MAIN_VARIANT in + current_class_type. + * decl.c (grokdeclarator): Put typedefs on the type's obstack. - * expr.c (cplus_expand_expr): Use expand_call to expand the call - under a NEW_EXPR, so the target is not discarded. + * parse.y (complex_direct_notype_declarator): Use $1 to access + scope of notype_qualified_id. -Thu Apr 20 14:59:31 1995 Mike Stump +1998-05-26 Dave Brolley - * gc.c (build_dynamic_cast): Tighten error checking. + * lex.c (parse_options,yy_cur,yy_lim): Add for cpplib. + (init_parse): Initialize cpplib interface. -Thu Apr 20 11:23:54 1995 Jason Merrill + * Makefile.in (CXX_OBJS): Make sure dependencies never end with an + empty continuation. - * expr.c (cplus_expand_expr): Only abort if the returned target is - different from what we expected if the type has a non-trivial copy - constructor. +1998-05-26 Mark Mitchell - * decl2.c (cplus_decl_attributes): Attributes applied to a template - really apply to the template's result. + * decl.c (pushtag): Avoid crashing on erroneous input. - * tree.c (lvalue_p): Check IS_AGGR_TYPE instead of TREE_ADDRESSABLE - to decide whether to consider a CALL_EXPR an lvalue. +1998-05-25 Martin v. Löwis - * class.c (finish_struct_bits): Only set TREE_ADDRESSABLE if the - type has a non-trivial copy constructor. + * decl.c (push_namespace): Only produce one unique name for + anonymous namespaces. + (get_unique_name): Remove. - * decl.c (start_function): If interface_known, unset - DECL_NOT_REALLY_EXTERN on the function. +1998-05-25 Mark Mitchell -Wed Apr 19 16:53:13 1995 Jason Merrill + * call.c (tourney): Don't do any extra comparisons. - * pt.c (do_function_instantiation): Handle explicit instantiation of - member functions. - (do_type_instantiation): Handle 'inline template class foo', - meaning just spit out the vtable. + * decl2.c (build_anon_union_vars): Don't crash on empty sub-unions. - * lex.c (cons_up_default_function): Set DECL_NOT_REALLY_EXTERN on - the consed functions. + * cp-tree.h (processing_template_parmlist): Declare. + * decl.c (pushtag): Don't call push_template_decl when we + shouldn't. + * pt.c (processing_template_parmlist): New variable. + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro. + (complete_template_args): Use it. + (add_to_template_args): Likewise. + (innermost_args): Likewise. + (tsubst): Likewise. + (begin_template_parm_list): Use processing_template_parmlist. + (end_template_parm_list): Likewise. - * decl2.c (import_export_inline): Set DECL_INTERFACE_KNOWN. + * cp-tree.h (ANON_UNION_TYPE_P): New macro. + * decl.c (grokdeclarator): Use it. + * decl2.c (grok_x_components): Likewise. + * init.c (initializing_context): Likewise. + * method.c (do_build_copy_constructor): Likewise. + (do_build_assign_ref): Likewise. + * search.c (compute_access): Likewise. + * typeck.c (build_component_ref): Likewise. -Wed Apr 19 16:28:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (grokdeclarator): Don't give a cv-qualified version of an + unnamed type a typedef name "for linkage purposes". - * call.c, class.c, decl2.c, gc.c, init.c, parse.y, pt.c, search.c, - typeck.c: Include output.h. + * pt.c (lookup_template_class): Don't look at + IDENTIFIER_CLASS_VALUE when there's no current_class_type. -Wed Apr 19 14:57:21 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu) + * method.c (build_overload_int): Handle error cases gracefully. - * call.c (build_method_call): Allow a signature member functions to - be called from a default implementation. + * pt.c (instantiate_decl): Handle static member variables + correctly. -Wed Apr 19 10:21:17 1995 Jason Merrill + * pt.c (tsubst): Use the tsubst'd type when producing new + TEMPLATE_PARM_INDEX nodes. - * repo.c (finish_repo): Remember what directory we are in. +1998-05-24 Mark Mitchell - * search.c (expand_upcast_fixups): Don't mess with abort_fndecl. + * tree.c (cp_tree_equal): Handle pointers to member functions. - * repo.c: Use obstacks instead of fixed-size buffers. Don't spit - out the second copy of the symbol name. Don't remember COLLECT_GCC. + * call.c (maybe_handle_implicit_object): Handle QUAL_CONVs. Make + sure the type of the REF_BIND is a reference type. + (maybe_handle_ref_bind, compare_ics): Rename reference_type to + target_type for clarity. -Wed Apr 19 02:32:40 1995 Mike Stump + * parse.y (xcond): Move call to condition_conversion ... + * semantics.c (finish_for_cond): Here. + * parse.c: Regenerated. + +1998-05-24 Jason Merrill - * search.c (virtual_context): New function to get the virtual - context of a function. - (expand_upcast_fixups): New function to generate runtime vtables. - (fixup_virtual_upcast_offsets): Ditto. - (expand_indirect_vtbls_init): Use fixup_virtual_upcast_offsets to - ensure that the this offsets for upcasts from virtual bases into - other virtual bases or non-virtual bases are correct at construction - time and destruction time. - * class.c (fixup_vtable_deltas): Modify to fixup all offsets in all - vtables in all virtual bases, instead of just one vtable in each - virtual base. - (fixup_vtable_deltas1): Ditto. + * decl.c (push_namespace): Namespaces have type void. + * typeck2.c (incomplete_type_error): Complain about namespace + used as expression. + * typeck.c (decay_conversion): Likewise. -Tue Apr 18 03:57:35 1995 Michael Meissner (meissner@cygnus.com) +1998-05-24 Martin von Löwis - * Makefile.in (lex.o): Add dependency on c-pragma.h. + * error.c (dump_expr): Support namespaces. - * lex.c (handle_sysv_pragma): Use NULL_PTR and NULL_TREE as - appropriate, instead of 0. +1998-05-23 Jason Merrill -Mon Apr 17 12:28:42 1995 Jason Merrill + * cp-tree.def: Add SRCLOC. + * cp-tree.h: Add struct tree_srcloc and accessor macros. + * 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 + calling add_pending_template. + * decl2.c (finish_file): Set up lineno and input_filename for + pending templates. - * decl.c (pushdecl): Use decls_match, not duplicate_decls, for - comparing local and global decls. +1998-05-22 Jason Merrill -Fri Apr 14 01:46:52 1995 Jason Merrill + * 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. - * typeck.c (convert_arguments): Only prohibit passing to ... of - types with non-trivial copy constructors. + * call.c (maybe_handle_ref_bind): Propagate ICS_USER_FLAG and + ICS_BAD_FLAG. - * repo.c (repo_template_used): Don't try to mess with no id. + * cvt.c (ocp_convert): Don't set LOOKUP_NO_CONVERSION for + copy-initialization. -Fri Apr 14 23:32:50 1995 Per Bothner + * class.c (build_vtable_entry): Use int_fits_type_p. + (build_vtable): Pass a signed offset to build_vtable_entry. + (prepare_fresh_vtable, modify_one_vtable, fixup_vtable_deltas1, + set_rtti_entry): Likewise. - * decl.c (duplicate_decls): Use cp_warning_at for redundant-decls. +1998-05-22 Per Bothner -Thu Apr 13 15:37:42 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * cp-tree.h: Add comments documenting which LANG_FLAGS are used. + (C_TYPE_VARIABLE_SIZE, C_DECL_VARIABLE_SIZE): Removed, not used. - * cp-tree.h (current_tinst_level): Delete declaration, since it's - static inside pt.c. +1998-05-22 Jason Merrill - * typeck.c (build_modify_expr): Catch incompatible array assignment. + * pt.c (print_template_context): Use fprintf instead of cp_error. - * parse.y (attribute_list, attrib): Rewrite actions to feed the - right stuff to decl_attributes. + * 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 + error messages will be useful. + (instantiate_template): Just return an error_mark_node. + (check_explicit_specialization): Don't mess with a returned + error_mark_node. -Thu Apr 13 11:24:10 1995 Jason Merrill + * pt.c (print_template_context): Add new argument. + (maybe_print_template_context): New fn. + (push_tinst_level): Increment tinst_level_tick. + (pop_tinst_level): Likewise. + * errfn.c (cp_thing): Call maybe_print_template_context. Use + xrealloc instead of xmalloc. - * search.c (dfs_debug_mark): Check for magic virtual like - import_export_vtable. + * typeck.c (build_unary_op, CONVERT_EXPR): Propagate TREE_CONSTANT. - * typeck.c (build_binary_op_nodefault): Don't call cp_pedwarn with - four args. +1998-05-21 Jason Merrill -Wed Apr 12 12:02:57 1995 Jason Merrill + * pt.c (tsubst_friend_class): Don't call redeclare_class_template + if the template we looked up is the same as the one we already + have. - * decl2.c (finish_file): Move prevtable pass before needs_messing_up - decision. +Thu May 21 11:54:44 1998 Dave Brolley -Tue Apr 11 11:20:27 1995 Jason Merrill + * lex.c: (handle_sysv_pragma): FILE* parameter not used. + (cpp_reader,parse_in): Add for cpplib. + (check_newline): Call handle_sysv_pragma with new interface. + (check_newline): Call GET_DIRECTIVE_LINE, not get_directive_line. - * decl.c (finish_decl): If we're writing out a static data member of - a class, we want the debug info for that class. + * input.c: (yy_cur,yy_lim,yy_get_token,GETC): Add for cpplib. + (sub_getch): Call GETC for cpplib. - * gc.c (build_t_desc): Check linkage of a class properly. + * cp-tree.h: (get_directive_line): Different prototype for cpplib. + (GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line. - * class.c (finish_struct): Set the 'headof' offset for the main - vtable properly. - (prepare_fresh_vtable): Fix typeinfo pointer here. - (modify_one_vtable): Instead of here. + * Makefile.in (CXX_OBJS): add @extra_cxx_objs@ for cpplib. -Mon Apr 10 12:15:59 1995 Jason Merrill +1998-05-21 Jason Merrill - * repo.c (repo_get_id): New function to return the interesting - identifier for a repo entity. - (repo_template_used): Use it. - (repo_template_instantiated): Mark the id as chosen. - (init_repo): Record whether or not the id was chosen. - (finish_repo): Note if an id was newly chosen. + * decl2.c (maybe_make_one_only): New fn. + (import_export_vtable): Use it. + (import_export_decl): Likewise. + * pt.c (mark_decl_instantiated): Likewise. - * pt.c (do_function_instantiation): Call repo_template_instantiated. - (do_type_instantiation): Ditto. Don't diagnose multiple - instantiation. +1998-05-21 Mark Mitchell - * decl2.c (finish_file): Use DECL_NOT_REALLY_EXTERN when deciding - whether or not to synthesize a method. + * decl2.c (find_representative_member): Rename to ... + (build_anon_union_vars): New function. + (finish_anon_union): Fix stupidity of previous change. - Undo these changes: - * class.c (finish_vtbls): build more vtables if flag_rtti is on. - * class.c (modify_all_direct_vtables): ditto. - * init.c (expand_direct_vtbls_init): expand more vtables if - flag_rtti is on. +1998-05-20 Jason Merrill -Sat Apr 8 17:45:41 1995 Mike Stump + * decl.c (grokfndecl): Handle definition of specialization in + friend declaration. - * gc.c (build_headof): Use ptrdiff_type_node instead of - integer_type_node on pointer arithmetic. + * error.c (dump_decl): Fix LOOKUP_EXPR handling. -Sat Apr 8 11:57:04 1995 Jason Merrill +1998-05-20 Mark Mitchell - * typeck.c (build_modify_expr): Undo previous change. + * class.c (delete_duplicate_fields_1): Use DECL_DECLARES_TYPE_P + to look for type declarations. + (finish_struct): Deal with templates on the CLASSTYPE_TAGS list. + * cp-tree.h (DECL_DECLARES_TYPE_P): New macro. + (finish_member_class_template): Declare. + * decl.c (pushtag): Put member class templates on the + 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. + * parse.y (component_decl): Move code to ... + * semantics.c (finish_member_class_template): New function. + Don't put member class templates on the list of components for a + 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. -Thu Apr 6 01:23:50 1995 Jason Merrill +1998-05-20 Martin von Loewis - * Makefile.in (compiler): Remove ../cc1plus before rebuilding it. + * decl.c (record_unknown_type): New function. + (init_decl_processing): Call it for the unknown and global type + nodes. - * repo.c (get_base_filename): Put the .rpo file in the directory - with the object file, not the source. +1998-05-20 Mark Mitchell - * typeck.c (build_conditional_expr): Handle pmf's better. + * decl2.c (find_representative_member): New function. + (finish_anon_union): Use it. - * repo.c (finish_repo): Also use ASM_OUTPUT_LABELREF to print out - the name of the symbol. + * cp-tree.h (MAIN_NAME_P): New macro. + (DECL_MAIN_P): Likwise. + * decl.c (pushdecl): Avoid crashing on redefinitions of `main'. + (grokfndecl): Use the new macros. + (grokdeclarator): Likewise. + (start_function): Likewise. + (store_parm_decls): Likewise. + (finsh_function): Likewise. + * friend.c (do_friend): Likewise. + * typeck.c (build_function_call_real): Likewise. + (build_unary_op): Likewise. -Wed Apr 5 15:24:12 1995 Jason Merrill +Wed May 20 02:16:01 1998 Jason Merrill - * repo.c (open_repo_file): Make repo filename DOS-compliant. - (*): Also write a new repo file if some previously-used - templates are no longer used. Only remember the identifier. + * decl2.c (start_objects, finish_objects, do_dtors, + do_ctors): Split out from... + (finish_file): ...here. - * lex.c (cons_up_default_function): If this function belongs to a - template class, call repo_template_used for it. +Tue May 19 20:36:23 1998 Jason Merrill - * repo.c (repo_template_used): Using a class means using its vtable, - if any. - (finish_repo): Ditto. + * tree.c (is_overloaded_fn): Don't abort on placeholders from + push_class_decls. - * typeck.c (build_modify_expr): Only wrap TARGET_EXPRs in RTL_EXPRs - if the type has a complex copy constructor. +Tue May 19 15:16:22 1998 Brendan Kehoe - * decl2.c (lang_decode_option): -frepo implies - -fno-implicit-templates. + * class.c (is_empty_class): Return 0 if TYPE is an error_mark_node. - * decl.c (start_function): Clear current_{base,member}_init_list. + * error.c (dump_expr): Handle an ARROW_EXPR. - * lex.c (init_lex): Also unset *_eq if ! flag_operator_names. +Tue May 19 15:13:39 1998 Mark Mitchell -Tue Apr 4 16:11:08 1995 Jason Merrill + * decl.c (saveable_obstack): Declare. + (pushdecl): Copy TYPE_DECLs to the same obstack as the type they + declare, if necessary. - * decl.c (struct cp_function): Add {base,member}_init_list. - (push_cp_function_context): Save current_{base,member}_init_list. - (pop_cp_function_context): Restore them. +Tue May 19 14:50:27 1998 Mark Mitchell -Mon Apr 3 16:55:08 1995 Jason Merrill + * call.c (compare_qual): Remove. + (is_subseq): Tweak. + (is_properly_derived_from): New function. + (maybe_handle_ref_bind): Likewise. + (maybe_handle_implicit_object): Likewise. + (compare_ics): Modify substantially to bring into conformance with + the standard. + * cp-tree.h (TYPE_PTRMEMFUNC_OBJECT_TYPE): New macro. + (comp_cv_qualification): Declare. + (comp_cv_qual_signature): Likewise. + * typeck.c (comp_cv_qualification): Likewise. + (comp_cv_qual_signature): Likewise. - * repo.c (get_base_filename): Take filename parm, fix logic bug. +Tue May 19 10:05:02 1998 Kaveh R. Ghazi - * typeck.c (build_compound_expr): Do not warn about a compound expr - in which the first expression has no side effects. - (build_x_compound_expr): Warn here instead. - (build_conditional_expr): Don't warn about a conditional expression - between an enum and the type it promotes to. + * Makefile.in (parse.o): Depend on toplev.h. - * init.c (build_new): Handle initialization of arrays of builtins - properly. + * class.c (typecode_p): Remove prototype and definition. -Mon Apr 3 15:08:04 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * cp-tree.h (currently_open_class, is_empty_class, member_p): + Add prototype. - * repo.c: Include config.h to get definitions of bcopy and rindex - on systems that don't have them (e.g., SVR4). + * decl.c (push_overloaded_decl_top_level): Remove prototype and + definition. -Mon Apr 3 14:41:55 1995 Mike Stump + * errfn.c (cp_error): Cast function pointer `error' to (errorfn *) + in call to `cp_thing'. + (cp_warning): Likewise for function pointer `warning'. - * decl2.c (finish_table): Pass NULL_TREE instead of init to - finish_decl so that it won't try and do error checking on the - initializer. + * except.c (do_function_call): Remove prototype and definition. + (call_eh_info): Wrap variable `t1' in macro NEW_EH_MODEL. -Mon Apr 3 10:45:50 1995 Jason Merrill + * method.c (is_java_type): Add prototype and make it static. - * repo.c (get_base_filename): Analyze COLLECT_GCC_OPTIONS to - determine whether this compile used -c -o. - (open_repo_file): Use get_base_filename. Remove the extension. - (finish_repo): Spit out the values of main_input_filename, - COLLECT_GCC and COLLECT_GCC_OPTIONS. + * parse.y: Include toplev.h. - * parse.y (structsp): Add TYPENAME_KEYWORD complex_type_name. + * pt.c (type_unification): Remove unused variable `arg'. + (instantiate_decl): likewise for `save_ti'. -Sun Apr 2 23:43:51 1995 Jason Merrill + * tree.c (propagate_binfo_offsets): Likewise for `base_binfos'. + +Tue May 19 02:43:25 1998 Jason Merrill - * search.c (compute_access): Don't try to do access control on - nested types. + * init.c (build_member_call): Handle template_ids. + * parse.y (primary): Add global_scope template_id. -Fri Mar 31 10:14:23 1995 Jason Merrill +Mon May 18 23:22:52 1998 Jason Merrill - * repo.c: New file to handle things repo. + * decl2.c (get_sentry): Use end_temporary_allocation. + Don't declare permanent_obstack. - * pt.c (instantiate_template): Call repo_template_used if the - definition is accessible. - (mark_function_instantiated): Split out from - do_function_instantiation. - (mark_class_instantiated): Split out from do_type_instantiation. +Mon May 18 12:28:44 1998 Mark Mitchell - * parse.y (template_instantiate_once): Call repo_template_used. + * parse.y (.finish_new_placement): New non-terminal. + (unary_expr, new_type_id): Use it. + * parse.c: Regenerated. + +Mon May 18 12:20:27 1998 Brendan Kehoe - * lex.c (lang_init): Call init_repo. + * pt.c (redeclare_class_template): Say where the original definition + of the template-parameter's default argument appeared. - * decl2.c: Handle flag_use_repository. - (finish_file): Call finish_repo. +Mon May 18 03:00:57 1998 Jason Merrill - * decl.c (start_method): Call repo_template_used if this is a - template method. + * call.c (build_over_call): Tweak empty class handling. - * Makefile.in (CXX_OBJS): Add repo.o. - (repo.o): Add dependencies. + * decl.c (make_typename_type): Use currently_open_class. - * Make-lang.in (CXX_SRCS): Add repo.c. + * class.c (instantiate_type): Don't abort on TREE_NONLOCAL_FLAG. - * decl.c (start_function): If DECL_INTERFACE_KNOWN and - DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL. +Mon May 18 01:43:01 1998 Martin v. Loewis - * typeck.c (build_binary_op_nodefault): Identify the invalid operand - types used. + * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE + for a type unless it is one. - * decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN. + * class.c (finish_struct_1): Use OVL_CURRENT in error message. -Thu Mar 30 17:54:42 1995 Jason Merrill +Mon May 18 01:24:08 1998 Jeffrey A Law (law@cygnus.com) - * typeck.c (build_binary_op_nodefault): Tidy up use of build_type - and result_type. When checking for comparison between signed - and unsigned, use result_type rather than the (possibly shortened) - type of op0. Also, don't warn about equality comparison of a - signed operand to an unsigned constant that fits in the signed - type. + * Makefile.in (program_transform_name, objdir): Define. - * method.c (do_build_copy_constructor): Reverse - current_base_init_list after we've built it up. + * Makefile.in (BISON): Use bison from the build tree if it exists. + (FLEX): Similarly. -Thu Mar 30 14:35:18 1995 Mike Stump +Sun May 17 14:52:08 1998 Martin v. Loewis - * except.c (build_throw): Never warn about the value of throw not - being used. + * typeck.c (type_unknown_p): Return true for TREE_LIST also. -Thu Mar 30 13:16:54 1995 Mike Stump + * call.c (build_method_call): Use TYPE_MAIN_VARIANT on typedefs. - * except.c (expand_start_catch_block): Check for bad catch parameter - declarations. +Sun May 17 14:51:41 1998 Jason Merrill -Thu Mar 30 13:06:11 1995 Jason Merrill + * call.c (build_scoped_method_call): Likewise. - * decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if - DECL_EXTERNAL is not already set. +Sun May 17 13:53:48 1998 Mark Mitchell -Thu Mar 30 11:26:24 1995 Mike Stump + * init.c (build_new_1): Call suspend_momentary around the creation + of values that must be saved for exception handling. + * 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 - * method.c (emit_thunk): Let poplevel know that the last level is - for a function so it can create a BLOCK_NODE and set DECL_INITIAL. + * decl.c (duplicate_decls): Use CANONICAL_TYPE_VARIANT to compare + old and new types. -Thu Mar 30 11:15:06 1995 Jason Merrill + * pt.c (tsubst): Make sure that BINFO_TYPE of new binfos is the + canonical type. - * decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN - here. + * call.c (build_over_call): Don't use IS_SIGNATURE on a namespace. - * decl.c (grokdeclarator): OK, don't abort if we see a decl with - METHOD_TYPE. - (finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on - all deferred inlines. +Fri May 15 20:28:00 1998 Jason Merrill -Wed Mar 29 19:35:02 1995 Jason Merrill + * decl.c (start_decl): Revert problem change. - * cp-tree.h (DECL_THIS_INLINE): New macro. - (DECL_NOT_REALLY_EXTERN): New macro. - (DECL_THIS_STATIC): New macro. + * Makefile.in (CONFLICTS): Fix. - * decl.c: Lose all references to current_extern_inline. Break - inline semantics into DECL_INLINE for actual inlining and - DECL_THIS_INLINE for the linkage wierdness. Use DECL_THIS_STATIC. - * decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to - emit an inline here. Associated changes. - * lex.c: Ditto. - * pt.c: Ditto. - * typeck.c: Ditto. +Fri May 15 15:34:02 1998 Benjamin Kosnik - * call.c (build_method_call): Don't bother trying to handle inlines - specially. - * cvt.c (convert_to_aggr): Ditto. + * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits. - * pt.c (do_function_instantiation): Handle instantiation of - public inlines, too. +Fri May 15 00:46:05 1998 Jason Merrill -Wed Mar 29 16:04:25 1995 Mike Stump + * class.c (finish_struct_1): Use BINFO_SIZE. - * except.c (init_exception_processing): Change the interface for - __throw_type_match and add decl for new rtti matching routine - __throw_type_match_rtti. - (build_eh_type): New routine to build a run time descriptor for the - expression given. - (expand_start_catch_block): Update to use new calling convention for - the matcher. - (expand_throw): Update to use build_eh_type. + * decl.c (start_decl): Use 'tem'. -Mon Mar 27 07:14:33 1995 Warner Losh +Thu May 14 16:30:47 EDT 1998 Andrew MacLeod - * g++.c: Removed __NetBSD__ from conditional. - Declare strerror if HAVE_STRERROR is defined; otherwise - declare sys_errlist and sys_nerr. - (my_strerror): New function. + * exception.cc: Include eh-common.h. + (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 + 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 + end_catch_block(). + * parse.y (function_try_block): call start_catch_block() and + end_catch_block(). -Tue Mar 28 14:16:35 1995 Jason Merrill +Thu May 14 12:27:34 1998 Brendan Kehoe - * search.c (get_binfo): Don't try to be so clever. + * typeck.c (original_type): New function. + (common_type): Use it to get the DECL_ORIGINAL_TYPE for T1 and T2, + to see if they're actually the same. + * cp-tree.h (original_type): Declare. - * tree.c (copy_to_permanent): Also suspend_momentary(). +Wed May 13 12:54:30 1998 Kaveh R. Ghazi - * cvt.c (cp_convert_to_pointer): Hand off to convert_fn_pointer even - if the types are the same. + * 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. + + * decl2.c (merge_functions): Remove unused variables `tmp' and + `tempn'. + + * error.c (expr_as_string): Mark parameter `v' with ATTRIBUTE_UNUSED. + (code_as_string): Likewise. + (language_as_string): Likewise. + (parm_as_string): Likewise. + (op_as_string): Likewise. + (assop_as_string): Likewise. + (cv_as_string): Likewise. + + * lex.c: Include output.h. + + * pt.c (type_unification): Cast first argument of `bzero' to a char*. + + * search.c (dfs_no_overlap_yet): Mark parameter `t' with + ATTRIBUTE_UNUSED. + + * tinfo.cc (__class_type_info::dcast): Change the type of variable + `i' from int to size_t. + + * typeck.c (language_lvalue_valid): Mark parameter `exp' with + ATTRIBUTE_UNUSED. + +Tue May 12 21:37:49 1998 Jason Merrill + + * error.c (dump_simple_decl): Use DECL_CLASS_SCOPE_P and/or + DECL_NAMESPACE_SCOPE_P. + (lang_decl_name): Likewise. + * pt.c (tsubst_friend_function, tsubst): Likewise. + * 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. + (compare_ics): Use DERIVED_FROM_P. + +Tue May 12 07:24:18 1998 Mark Mitchell + + * cp-tree.h (CANONICAL_TYPE_VARIANT): New macro. + * method.c (build_mangled_name): Use it. + (build_decl_overload_real): Likewise. + + * error.c (dump_simple_decl): New function, broken out from ... + (dump_decl): Use it. + +Mon May 11 11:38:07 1998 Mark Mitchell + + * ptree.c (lang_print_xnode): Add missing `break'. + + * pt.c (tsubst): Remove duplicate check for IDENTIFIER_NODE. + + * call.c (add_template_candidate): Adjust for changes to + fn_type_unification. + (add_template_candidate_real): Likewise. + (add_template_conv_candidate): 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. + * class.c (instantiate_type): Likewise. + * cp-tree.h (unification_kind_t): New type. + (fn_type_unification): Adjust prototype. + (type_unificaiton): Likewise. + * pt.c (UNIFY_ALLOW_NONE): New macro. + (UNIFY_ALLOW_MORE_CV_QUAL): Likewise. + (UNIFY_ALLOW_LESS_CV_QUAL): Likewise. + (UNIFY_ALLOW_DERIVED): Likewise. + (unify): Change prototype. + (maybe_adjust_types_for_deduction): New function. + (check_cv_quals_for_unify): Likewise. + (determine_specialization): Adjust. + (fn_type_unification): Likewise. + (type_unification): Likewise. + (type_unification_real): Likewise. Use + maybe_adjust_types_for_deduction. Fix mishandling of + back-unification of template functions passed as arguments. Pass + appropriate combination of UNIFY_ALLOW_* to unify. + (unify): Remove unused NTPARMS parameter. Use + check_cv_quals_for_unify. Remove bogus code that allowed + too-generous unification in order to adhere more closely to standard. + (get_bindings_real): Adjust. + (get_class_bindings): Likewise. + + * method.c (build_overload_identifier): Only use the innermost + template arguments when mangling. + * pt.c (tsubst_template_argument_vector): New function. + (complete_template_args): Deal with the situation where the + extra_args contain more than one level of arguments. + (lookup_template_class): Deal with member template classes, which + may have more than one level of arguments. + (tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE. + Improve handling of member template classes. Use + DECL_PRIMARY_TEMPLATE instead of inline expansion. Use + 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. + (finish_new_placement): Likewise. + (finish_declarator): Likewise. + (finish_translation_unit): Likewise. + (finish_parmlist): Likewise. + (begin_class_definition): Likewise. + (finish_class_definition): Likewise. + (finish_default_args): Likewise. + (finish_inline_definitions): Likewise. + * parse.y (GCC_ASM_KEYWORD): Remove. + (TYPENAME_ELLIPSIS): Likewise. + * parse.c: Regenerated. + Use new functions in semantics.c in the actions for many rules. + * gxx.gperf (GCC_ASM_KEYWORD): Just use ASM_KEYWORD. + * hash.h: Regenerated. + * semantics.c (finish_expr_stmt): Allow NULL expr. + (finish_unary_op_expr): New function, containing + code previously in parse.y. + (finish_id_expr): Likewise. + (begin_new_placement): Likewise. + (finish_new_placement): Likewise. + (finish_declarator): Likewise. + (finish_translation_unit): Likewise. + (finish_parmlist): Likewise. + (begin_class_definition): Likewise. + (finish_class_definition): Likewise. + (finish_default_args): Likewise. + (finish_inline_definitions): Likewise. + +Sun May 10 23:43:13 1998 Mark Mitchell + + * typeck.c (build_c_cast): Don't decay arrays and functions to + pointer type when converting to a class type. + +Sun May 10 22:53:56 1998 Jason Merrill + + * cp-tree.h (DECL_NAMESPACE_SCOPE_P): New macro. + (DECL_CLASS_SCOPE_P): Likewise. + +Sun May 10 22:48:22 1998 H.J. Lu (hjl@gnu.org) + + * class.c (finish_struct_1): Use OVL_CURRENT on TREE_VEC_ELT. + * decl2.c (constructor_name_full): Likewise. + +Sun May 10 22:48:12 1998 Mike Stump + + * tree.c (mapcar): Add OVERLOAD support. + + * init.c (resolve_offset_ref): We must use basetype_path before we + destroy it with a call to convert_pointer_to. + +Sat May 9 14:44:37 1998 Jason Merrill + + * class.c (currently_open_class): New fn. + * decl.c (lookup_name_real): Use it. + * search.c (lookup_field): Likewise. + +Fri May 8 23:32:42 1998 Martin von Loewis + + * cp-tree.def (OVERLOAD): New node. + * cp-tree.h (BINDING_TYPE, SET_IDENTIFIER_GLOBAL_VALUE, + SET_IDENTIFIER_NAMESPACE_VALUE): Define. + (NAMESPACE_BINDING): Remove. + (IDENTIFIER_GLOBAL_VALUE, IDENTIFIER_NAMESPACE_VALUE): Use + namespace_binding. + (OVL_FUNCTION, OVL_CHAIN, OVL_CURRENT, OVL_NEXT, OVL_USED): + Define. + (tree_overload): New struct. + (IDENTIFIER_TYPE_VALUE): Use identifier_type_value. + (REAL_IDENTIFIER_TYPE_VALUE): Define. + (IDENTIFIER_HAS_TYPE_VALUE): Use IDENTIFIER_TYPE_VALUE. + (lang_decl_flags): Remove in_namespace. + (lang_decl): Remove chain. + (DECL_CHAIN, DECL_NAMESPACE): Remove. + (flag_honor_std): Declare extern. + (identifier_type_value, pushdecl_namespace_level, push_using_decl, + namespace_binding, set_namespace_binding, + lookup_function_nonclass, cat_namespace_levels, + set_decl_namespace, lookup_arg_dependent, binding_init, ovl_cons, + scratch_ovl_cons, ovl_member, build_overload): Declare. + (decl_list_length, get_namespace_id, current_namespace_id, + overloaded_globals_p): Remove. + (lookup_using_namespace, qualified_lookup_using_namespace): Change + return type. + (push_scratch_obstack): New macro. + * 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. + Print DECL_NAME in when reporting ambiguities. + (build_object_call): Iterate using OVL_NEXT for fns, convs. + (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. + (build_over_call): Don't push a class level if the context is a + namespace. + (build_new_method_call): Iterate using OVL_NEXT. + * class.c (add_method): Chain overloaded members using + build_overload. Remove copying of method. + (grow_method): When iterating through the obstack, expect OVERLOAD + nodes. Chain overload members. + (finish_struct_methods): Chain overload members. Unpack OVERLOAD + nodes in call to get_baselinks. + (duplicate_tag_error): Expect OVERLOAD nodes when unchaining. + (finish_struct_1): Iterate over ctor using OVL_NEXT. Handle + 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 + and member function processing. + * decl.c (global_type_node): New static variable. + (in_std): New global. + (struct binding_level): New field usings. + (resume_binding_level): Assert that we are not in a class. + (toplevel_bindings_p): Just check for namespace_p or + pseudo_global. + (resume_level): Remove. + (find_binding): New function. + (binding_for_name): Call it. + (namespace_binding, set_namespace_binding): New functions. + (push_namespace): Associate binding level with new namespace, + resume_binding_level for existing namespace. Remove old code. + Fake std by counting. + (store_bindings): Use REAL_IDENTIFIER_TYPE_VALUE. + (maybe_push_to_top_level): Save current namespace. + (pop_from_top_level): Restore saved namespace. + (pop_namespace): Call suspend_binding_level. Remove old code. + (cat_namespace_levels): New function. + (set_identifier_type_value_with_scope): For namespace bindings, + set BINDING_TYPE, and use global_type_node. + Use REAL_IDENTIFIER_TYPE_VALUE otherwise. + (identifier_type_value): New function. + (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 + in their namespace. Push overloaded templates if they are on + namespace level. + (pushdecl_namespace_level): New function. + (pushdecl_top_level): Implement using pushdecl_namespace_level. + (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. + (redeclaration_error_message): Complain if the declarations come + from different namespaces. + (lookup_tag): On namespace level, look in the BINDING_TYPE. + (lookup_namespace_name): Pass tree_bindings from stack. Remove + old code. + (select_decl): New function. + (lookup_name_real): Call it for qualified and unqualified lookup. + Pass tree_bindings from the stack. + If prefer_type is 1, also accept namespaces. + (lookup_function_nonclass): New function. + (init_decl_processing): Set the binding level of the global + namespace to global_binding_level. + Build a proper type list for __builtin_apply. + Initialize std_node to "fake std" if flag_honor_std is set. + Initialize global_type_node. + Allocated bad_alloc in namespace std if flag_honor_std. + (define_function): Set the DECL_CONTEXT to the current_namespace. + (start_decl): A namespace is not considered as a context here. If + the DECL_CONTEXT is a namespace, push the decl. + (cp_finish_decl): Check for namespaces used as initializers. + (grokfndecl): Add namespace parameter. Remove processing of + DECL_CHAIN. + (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. + Set context for declarations that have not been pushed. + (store_parm_decls): Check for ::main only. + (finish_function): Likewise. + (start_method): Check for contexts that are namespaces. + (start_method): Remove DECL_CHAIN processing. + * decl2.c (flag_honor_std): Declare. + (lang_decode_option): Set it if -fhonor-std or -fnew-abi is given. + (decl_namespace_list): New static global. + (grok_x_components): Ignore namespaces as type contexts. + (check_classfn): Expect OVERLOAD nodes. + (grokfield): Remove DECL_CHAIN processing. + (finish_file): Call cat_namespace_levels. + (merge_functions): New function. + (ambiguous_decl): Rewrite. + (lookup_using_namespace): Produce tree_bindings. + (qualified_lookup_using_namespace): Likewise. + (set_decl_namespace, decl_namespace, current_decl_namespace, + push_decl_namespace, pop_decl_namespace): New functions. + (arg_lookup): New struct. + (add_function, arg_assoc_namespace, arg_assoc_class, + arg_assoc_type, arg_assoc_args, arg_assoc, lookup_arg_dependent): + New functions. + (get_namespace_id, current_namespace_id): Remove. + (do_toplevel_using_decl): Rewrite. + (do_class_using_decl): Complain about namespace qualifiers. + (do_using_directive): Sorry if not on namespace level. Complain + about unknown namespaces. + * error.c (dump_aggr_type): Check for namespace contexts. + * except.c (init_exception_processing): Push terminate into std. + * friend.c (is_friend): A namespace is not a context, here. + * init.c (expand_member_init): Remove DECL_CHAIN processing. + (build_offset_ref): Process OVERLOAD nodes. + * 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. + (do_identifier): Expect OVERLOAD nodes instead of TREE_LISTs. + (do_scoped_id): Expect OVERLOAD nodes. + Change calling convention for qualified_lookup_using_namespace. + (build_lang_decl): Don't set in_namespace anymore. + * method.c (typevec_size): New global. + (build_overload_nested_name): Return if global_namespace. + Otherwise, always expect a declaration context. + (build_qualified_name): Likewise. + Make sure we don't write beyond typevec_size. + (build_decl_overload_real): Likewise. + Allocate one extra slot for the namespace. + (hack_identifier): Mark code dead. + Process OVERLOAD and NAMESPACE_DECL nodes. + * parse.y (program): Pop namespaces until in global namespace. + (extdef): In a using-declaration, don't discard the identifier if + there is no declaration. + (left_curly): Ignore type contexts which are namespaces. + (typename_sub2): Use IDENTIFIER_TYPE_VALUE to retrieve the type + used as scope. + * pt.c (template_class_depth): Expect types to be namespaces. + (determine_specialization): Simplify by expecting OVERLOAD nodes. + (push_template_decl): Push into namespace level. + Reset ctx if it is a namespace. + 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. + (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. + Use id_context for mangling. + (for_each_template_parm): Handle OVERLOAD and NAMESPACE_DECL nodes. + (tsubst_friend_function): Ignore namespace contexts. + Push into namespace level. + (tsubst): Handle NAMESPACE_DECL nodes. + Remove DECL_CHAIN processing. + (type_unification_real): Recognize OVERLOAD instead of TREE_LIST nodes. + * ptree.c (print_lang_identifier): Print bindings. + (lang_print_xnode): Print OVERLOAD nodes. + * rtti.c (init_rtti_processing): Push type_info into std. + * search.c (lookup_fnfields_here): Expect OVERLOAD nodes. + (lookup_fnfields_1, get_virtuals_named_this, get_matching_virtual, + dfs_debug_mark, dfs_pushdecls, dfs_compress_decls, add_conversions, + lookup_fnfields_here): Likewise. + Process all nodes, instead of going through TREE_CHAIN. + * sig.c (build_signature_pointer_or_reference_type): Set context + to global_namespace. + (build_signature_table_constructor): Expect OVERLOAD nodes. + * spew.c (yylex): Save old setting of looking_for_typename. + * tree.c (decl_list_length): Remove. + (binding_init): New function. + (count_functions): Rewrite. + (is_overloaded_fn): Expect OVERLOAD nodes. + (really_overloaded_fn, get_first_fn, lvalue_type): Likewise. + (ovl_cons, scratch_ovl_cons, build_overload, build_overload_after, + ovl_member): New functions. + * typeck.c (require_complete_type): Expect OVERLOAD nodes. + (type_unknown_p): Likewise. + (require_instantiated_type): Likewise. + (build_component_ref): Declare code dead. + (build_x_function_call): Create and expect OVERLOAD nodes. + (build_function_call_real): Check for ::main only. + (build_unary_op): Likewise. Expect OVERLOAD nodes. + (convert_for_assignment): Check for TREE_LIST before accessing + TREE_VALUE. + * 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, + finish_enum): Likewise. + * init.c (build_offset_ref): Likewise. + * search.c (lookup_field): Likewise. + (lookup_fnfields): Likewise. + (dfs_debug_mark): Likewise. + * decl.c (poplevel): Use SET_IDENTIFIER_TYPE_VALUE. + (poplevel_class, pop_from_top_level): Likewise. + * decl2.c (finish_method): Likewise. + * class.c (build_vtable): Use SET_IDENTIFIER_GLOBAL_VALUE. + * decl.c (record_builtin_type): Likewise. + (init_decl_processing, grokfndecl): Likewise. + * lex.c (get_time_identifier, do_identifier, do_scoped_id): Likewise. + (make_lang_type): Likewise. + * 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, + 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 + + * call.c (build_user_type_conversion_1): Handle second_conv + properly for templates. + +Thu May 7 17:09:25 EDT 1998 Andrew MacLeod + + * method.c (build_decl_overload_real): Set TREE_USED flag to + zero for build_type_variants nodes as well. + +Wed May 6 19:27:09 1998 Jason Merrill + + * pt.c (tsubst): Don't tsubst the type of an IDENTIFIER_NODE. + +Wed May 6 16:49:48 1998 Jim Wilson + + * 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, + xref.o): Add toplev.h dependencies. + +Wed May 6 16:44:58 1998 Jeffrey A Law (law@cygnus.com) + + * errfn.c (cp_error, cp_warning): Remove declarations for + error and warning respectively. + +Wed May 6 14:28:18 1998 Kaveh R. Ghazi + + * error.c: Convert to using ctype macros defined in system.h. + * method.c: Likewise. + * xref.c: Likewise. + * lex.c: Likewise. Also remove redundant system header stuff. + +Wed May 6 06:36:41 1998 Robert Lipe + + * 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 + + * tree.c (perm_manip): Also regenerate the RTL of an extern. + (copy_to_permanent): Use end_temporary_allocation. + +Tue May 5 23:54:04 1998 Jason Merrill + + * 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 + + * 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 + + * Makefile.in: Add .SUFFIXES. + + * cp-tree.def: Remove NAMESPACE_DECL. + +Sun May 3 01:32:14 1998 Jason Merrill + + * 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. + +Thu Apr 30 18:59:23 1998 Jim Wilson + + * Makefile.in (g++FAQ.info): Put -o option before input file. + +Thu Apr 30 13:05:33 EDT 1998 Andrew MacLeod + + * gxxint.texi: Add info for squangling codes K and B. - * decl.c (start_function): Handle extern inlines more like C++ says - we should. +Tue Apr 28 13:22:01 1998 Mark Mitchell - * init.c (build_member_call): Hand constructor calls off to - build_functional_cast. + * semantics.c (begin_stmt_expr): Avoid duplicating the effect of + the expression in templates. + (finish_stmt_expr): Likewise. - * typeck2.c (build_functional_cast): Use DECL_NESTED_TYPENAME to get - the name of the type. +1998-04-28 Brendan Kehoe -Tue Mar 28 13:13:56 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl2.c (ambiguous_decl): Fix NAME parm to be a tree, not int. - * decl.c (grokdeclarator): Check for the decl returned by - grokfndecl to be null before using build_decl_attribute_variant. +Mon Apr 27 13:58:10 1998 Mark Mitchell -Mon Mar 27 18:04:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (maybe_push_to_top_level): Always clear + current_template_parms and processing_template_decl. + (pushtag): Remove check of current_class_type and some comments, + since maybe_push_to_top_level no longer creates confusion. - * init.c (build_new): Use build_pointer_type instead of - TYPE_POINTER_TO. +Sun Apr 26 12:10:18 1998 Mark Mitchell -Fri Mar 24 12:11:24 1995 Jason Merrill + * cp-tree.h (CLASSTYPE_IS_TEMPLATE): New macro. + (DECL_CLASS_TEMPLATE_P): Likewise. + (DECL_PRIMARY_TEMPLATE): Likewise. + (PRIMARY_TEMPLATE_P): Use it. + (push_template_decl_real): New function. + (redeclare_class_template): Take new template parameters as + input. + (is_specialization_of): New function. + (comp_template_args): Declare. + * decl.c (pushtag): Handle friend template classes. + (xref_tag): Likewise. Use new calling convention for + redeclare_class_template. + * decl2.c (grok_x_components): Handle friend templates. + * friend.c (is_friend): Use is_specialization_of where + appropriate. Deal with friend class templates. + (make_friend_class): Let a class template be friends with itself. + * pt.c (comp_template_args): Remove declaration. + (tsubst_friend_class): New function. + (push_template_decl_real): New function. + (push_template_decl): Use it. + (redeclare_class_template): Adjust for new calling convention. + (comp_template_args): Give it external linkage. + (instantiate_class_type): Use tsubst_friend_class to deal + with friend templates. + * typeck.c (comptypes): Use comp_template_args, rather than + expanding it inline. + * parse.y (component_decl): Handle a nested template type + like other component type declarations. - * typeck.c (build_conditional_expr): Handle pmfs. - (convert_for_assignment): Fix pmf support. + * pt.c (check_explicit_specialization): Handle overloaded + constructors correctly. - * cvt.c (convert_fn_ptr): Support !flag_vtable_thunks. - (cp_convert_to_pointer): Handle pmfs. - (cp_convert): Pass pmfs to cp_convert_to_pointer. + * pt.c (mabybe_get_template_decl_from_type_decl): New function. + (lookup_template_class): Use it. - * typeck.c (common_type): Handle inheritance for pmfs. +Thu Apr 23 21:19:06 1998 Jason Merrill - * typeck2.c (build_m_component_ref): Do access control. + * cp-tree.def: Add WRAPPER. USER_CONV now only has two ops. + * cp-tree.h: Add WRAPPER support. + * call.c (add_candidate): Split out from add_*_candidate fns. + (build_over_call): Take the candidate instead of function and args. + 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. + (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, + build_int_wrapper): New fns. - * typeck.c (comp_target_types): Check for conversion to void * - before checking trickier conversions. +Thu Apr 23 18:27:53 1998 Mark P. Mitchell - * decl.c (duplicate_decls): Propagate DECL_ABSTRACT_VIRTUAL_P. + * pt.c (unify): Fix typo in previous change. - * pt.c (push_tinst_level): Complain if template instantiation depth - is greater than max_tinst_depth. +Thu Apr 23 09:32:58 1998 Jason Merrill - * typeck.c (common_type): Assume that we can call common_type to - unify the target type of a pointer. + * error.c (dump_type_real): Declare canonical_name. -Thu Mar 23 00:48:44 1995 Jason Merrill + * typeck.c (comp_target_types): Fix PMFs. - * decl2.c (finish_file): Don't synthesize methods at - finish_vtable_prevardecl time. Do synthesize methods that are not - used, but are public and not external. +Wed Apr 22 13:24:48 1998 Mark Mitchell - * cvt.c (build_type_conversion): Only give an error if for_sure. + * class.c (finish_struct): Set TREE_PRIVATE and TREE_PROTECTED for + the DECL_RESULTs of a member TEMPLATE_DECL, not just the + TEMPLATE_DECL. - * typeck.c (comp_target_types): Only support pointer conversions if - nptrs > 0. + * 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. -Wed Mar 22 19:30:15 1995 Brendan Kehoe (brendan@lisa.cygnus.com) +Tue Apr 21 22:00:04 1998 Mark Mitchell - * init.c (build_new): Catch use of an initializer list where it - shouldn't be. + * errfn.c (cp_thing): Use xrealloc, not xmalloc, to copy memory. -Wed Mar 22 16:21:07 1995 Jason Merrill + * decl2.c (check_member_template): Set DECL_IGNORED for member + class templates, too. - * init.c (build_new): Wrap alloc_expr in an RTL_EXPR if nelts is - non-constant. + * decl2.c (grokfield): Remangle the name of a member TYPE_DECL. - * decl2.c: temp_name_counter is now public. +Tue Apr 21 18:59:11 1998 Benjamin Kosnik - * decl.c (struct cp_function): Add temp_name_counter field. - (push_cp_function_context): Save it. - (pop_cp_function_context): Restore it. + * decl.c (duplicate_decls): Only check DECL_FRIEND_P if function. - * typeck.c (common_type): Handle unifying function types, and unify - unmatched things to void* with a compiler_error, rather than - silently like before. +Tue Apr 21 14:22:00 1998 Jeffrey A Law (law@cygnus.com) -Wed Mar 22 15:10:34 1995 Mike Stump + * cp-tree.h (intTI_type_node, unsigned_intTI_type_node): Declare. + * decl.c (intTI_type_node, unsigned_intTI_type_node): Define. + (init_decl_processing): Handle TI types. + * typeck.c (unsigned_type, signed_type): Handle TI types. - * decl2.c (finish_prevtable_vardecl, finish_vtable_vardecl): Revert - Brendan's last change and fix latent problem that causes TD entries - to not come out when the things that need them has yet to be - expanded. +Sat Apr 18 15:25:21 1998 Jim Wilson -Wed Mar 22 15:12:00 1995 Jason Merrill + * g++spec.c (lang_specific_driver): New argument in_added_libraries. + New local added_libraries. Increment count when add library to + arglist. - * typeck.c (build_binary_op_nodefault, comparison ops): Update type0 - and type1, since we might have changed op0 or op1. +Fri Apr 17 21:25:00 1998 Mark Mitchell -Wed Mar 22 13:33:45 1995 Jason Merrill + * cp-tree.h (type_as_string_real): New function. + * pt.c (mangle_class_name_for_template): Use it. + * error.c (dump_aggr_type): Change prototype. + (dump_type_prefix): Likewise. + (dump_type_suffix): Likewise. + (dump_type_real): Convert from dump_type. If desired, the + "canonica" name of a typedef, i.e., the name of the underlying + type, can be printed. + (dump_type): Call dump_type_real. - * typeck.c (common_type): Don't mess up templates. +Fri Apr 17 14:30:45 1998 Jason Merrill -Wed Mar 22 04:56:00 1995 Jason Merrill + * decl2.c (lang_decode_option): -fnew-abi implies -fvtable-thunks. - * typeck.c (common_type): Handle ptms properly. Also handle - T* -> void*. - (build_binary_op_nodefault): New variable build_type controls what - type is given to the expression when it is created. Set this to - boolean_type_node for comparison ops instead of using result_type. - (comp_target_types): Allow T * -> void *. + * typeck.c (comp_target_types): Tweak pedantic case. + (comp_target_parms): Tweak pedantic case. Clean up somewhat. + Return -1 or 1 instead of 1 or 2. + (compparms): Remove STRICT handling. + (convert_for_assignment): Fix handling of pmfs. - * cvt.c (cp_convert_to_pointer): Do access control when converting - ptms, too. +Fri Apr 17 14:04:16 1998 Mark Mitchell -Tue Mar 21 17:25:06 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * typeck.c (comp_target_types): Handle references like pointers. + (comp_target_parms): Note that return code from comp_target_types + can be negative to indicate failure. - * parse.y (extern_lang_string): Catch use of linkage specs that - aren't all naming the same language. +Fri Apr 17 09:10:52 1998 Andreas Schwab - * class.c (finish_struct): Delete accidental duplicate code. + * Make-lang.in (c++.all.build): Don't depend on $(DEMANGLER_PROG), + which requires a working target compiler to build. -Tue Mar 21 14:00:57 1995 Jason Merrill +Fri Apr 17 08:57:35 1998 Jeffrey A Law (law@cygnus.com) - * typeck.c (build_binary_op_nodefault): Disable pedwarns about - comparing functions and incomplete types. + * tree.c (avoid_overlap): Add prototype. - * decl.c (finish_function): Only unset current_function_decl if - !nested. - (duplicate_decls): Last change went too far; we only want to stop - checking for value/reference ambiguity. + * spew.c (num_tokens): Add prototype. + (nth_noken, add_token, consume_token, debug_yychar): Likewise. -Tue Mar 21 01:26:39 1995 Mike Stump + * search.c (dfs_check_overlap): Add prototype. + (dfs_no_overlap_yet): Likewise. - * gc.c (build_generic_desc): Zap the DECL_SIZE so that we can lay it - out fresh, as the new type may be larger. + * pt.c (original_template): Add prototype. + (inline_needs_template_parms): Likewise. + (push_inline_template_parms_recursive): Likewise. + (retrieve_specialization, register_specialization): Likewise. + (print_candidates, reduce_template_parm_level): Likewise. + (build_template_decl, mark_template_parm): Likewise. + (tsubst_friend_function, get_bindings_real): Likewise. -Mon Mar 20 19:01:10 1995 Jason Merrill + * method.c (start_squangling): Add prototype. + (end_squangling, check_ktype, issue_ktype): Likewise. + (build_overloaded_scope_ref, check_btype): Likewise. + (build_mangled_template_parm_index): Likewise. - * expr.c (extract_init): Try to expand the RTL for the - initialization and figure out what it will look like so we can avoid - run-time initialization. Disabled for now. - (extract_scalar_init): Helper for scalar initialization. - (extract_aggr_init): Helper for aggregate initialization. + * lex.c (init_cpp_parse): Add prototype. + (handle_cp_pragma, handle_sysv_pragma): Likewise. + (reduce_cmp, token_cmp): Likewise. - * decl.c (duplicate_decls): Don't complain about ambiguous - declarations. - (obscure_complex_init): Now returns a tree. Call extract_init if - we're optimizing and this is a toplevel decl. - (finish_decl): Update accordingly. + * except.c (call_eh_info): Add prototype. + (push_eh_info, get_eh_info, get_eh_value, get_eh_type): Likewise. + (get_eh_caught, get_eh_handlers, do_pop_exception): Likewise. - * lex.c (check_newline): If we're just changing files (not pushing - or popping), update input_file_stack->name. + * decl2.c (is_namespace_ancestor): Add prototype. + (namespace_ancestor, add_using_namespace): Likewise. + (ambiguous_decl): Likewise. -Mon Mar 20 17:55:04 1995 Mike Stump + * decl.c (indent): Add prototype. - * pt.c (type_unification): Only TEMPLATE_DECLs are handled right now - in the transitive unification code. + * call.c (add_template_candidate_real): Add prototype. -Mon Mar 20 16:07:50 1995 Brendan Kehoe (brendan@lisa.cygnus.com) +Fri Apr 17 01:57:12 1998 Jason Merrill - * decl.c (shadow_tag): Don't allow inline, virtual, or explicit on - non-functions. - (grokdeclarator): Don't allow friends to be defined in local classes. + * decl2.c (build_expr_from_tree): Just return a PMF. -Sat Mar 18 04:03:33 1995 Jason Merrill +Fri Apr 17 00:45:12 1998 Mark Mitchell - * decl2.c (finish_prevtable_vardecl): Use DECL_DECLARED_STATIC - rather than DECL_SAVED_INSNS to decide whether or not this method - was declared inline. + * typeck2.c (process_init_constructor): Don't strip cv-qualifiers + when doing initializations. - * method.c (synthesize_method): Turn off DECL_INLINE if - function_cannot_inline_p thinks we're too large. + * pt.c (unify): Use comptypes to compare type args. - * typeck.c (build_indirect_ref): Use build_expr_type_conversion. +Fri Apr 17 00:24:22 1998 Jason Merrill -Fri Mar 17 17:47:36 1995 Jason Merrill + * decl.c (duplicate_decls): Fix check for when it's safe to free + the new decl. - * class.c (instantiate_type): Handle pmfs. + * pt.c (mangle_class_name_for_template): Don't pass a typedef type + to type_as_string. - * typeck.c (convert_for_assignment): Check types when assigning one - pmf to another. +Thu Apr 16 17:47:30 1998 Jeffrey A Law (law@cygnus.com) - * decl.c (define_label): Fix logic for printing out the name of the - label in an error message. + * pt.c (build_template_parm_index): Add prototype. - * error.c (dump_expr): Support ARRAY_REF. + * search.c (my_tree_cons): Don't clear words outside the + newly allocated node. -Fri Mar 17 17:43:02 1995 Brendan Kehoe (brendan@lisa.cygnus.com) +Wed Apr 15 15:34:44 1998 Dave Brolley - * decl2.c (finish_vtable_vardecl): Call build_t_desc here. - (finish_prevtable_vardecl): Instead of here. + * lex.c (init_parse): Now returns char* containing the filename. -Fri Mar 17 14:40:45 1995 Jason Merrill +Wed Apr 15 13:20:06 1998 John Carr + Jeff Law - * decl.c (expand_static_init): Also use expand_aggr_init if the - initializer is a TREE_LIST. - (grokdeclarator): Only pedwarn about extra qualification if -pedantic. + * errfn.c: Rework to avoid problems when HOST_WIDE_INT is longer + than a pointer. - * pt.c (unify): Fix unification of return type. +Sun Apr 12 22:31:19 1998 Richard Kenner - * expr.c (fixup_result_decl): Use store_expr, rather than - emit_move_insn, to move the return value into the place where - callers will expect it. + * cvt.c (cp_convert_to_pointer): Use TYPE_PRECISION. -Thu Mar 16 22:05:25 1995 Jason Merrill +Fri Apr 10 12:16:49 1998 Benjamin Kosnik - * init.c (build_offset_ref): Call assmble_external on functions. - * typeck.c (build_component_ref): Ditto. + * decl.c (duplicate_decls): Don't warn for redundant decls if + friend: let add_friend take care of it. -Thu Mar 16 20:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com) +Thu Apr 9 02:40:48 1998 Jason Merrill - * decl.c (struct saved_scope): Add members base_init_list and - member_init_list. - (push_to_top_level): Save current_base_init_list and - current_member_init_list to them. - (pop_from_top_level): Put it back. + * 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 + here, too. + * 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 Mar 16 19:21:14 1995 Jason Merrill +Thu Apr 9 22:16:57 1998 Per Bothner - * pt.c (instantiate_template): Call assemble_external. + * 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. + * method.c (build_mangled_name): Check for is_java_type. -Thu Mar 16 18:07:54 1995 Brendan Kehoe (brendan@phydeaux.cygnus.com) +Thu Apr 9 22:16:57 1998 Benjamin Kosnik - * class.c: Include rtl.h, to get NULL_RTX. - (finish_struct): Also zero out DECL_SAVED_INSNS, to avoid problems - on hosts with different sizes for each part of the union. - * tree.c: Also include rtl.h. - (layout_basetypes): Same change for DECL_SAVED_INSNS. + * 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. -Thu Mar 16 13:57:36 1995 Jason Merrill +Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com) - * pt.c (unify): Fix array domain unification for 64-bit targets. + * lex.c (finput): New variable. + (init_cpp_parse): Renamed from init_parse. + (init_parse): Handle !USE_CPPLIB. Call init_cpp_parse when finished. + (finish_parse): New function. + * cp-tree.h (init_lex, init_parse): Remove declarations. - * decl2.c (finish_file): Push bizarre type decl before walking the - vtables the first time. - (walk_vtables): OK, don't set prev to vars if the vardecl_fn messed - with TREE_CHAIN (prev). +Mon Apr 6 02:25:05 1998 Jason Merrill - * init.c (emit_base_init): Use convert_pointer_to_real instead of - convert_pointer_to when converting to a direct base. + * call.c (build_call): Still evaluate the actual argument. + * class.c (is_empty_class): Update for -fnew-abi. -Wed Mar 15 20:26:29 1995 Mike Stump + * decl2.c: -fnew-abi implies -fsquangle. - * pt.c (type_unification): Handle transitive unification better. + * method.c (do_build_assign_ref): Don't do anything to copy + an empty class. + (do_build_copy_constructor): Likewise. + * call.c (build_over_call): Likewise. -Wed Mar 15 13:56:16 1995 Jason Merrill +Sat Apr 4 18:43:58 1998 Jason Merrill - * decl2.c (walk_vtables): Always set prev to vars. - (mark_vtable_entries): Call assemble_external on the vtable entries. + * tree.c (avoid_overlap): Return a value. - * class.c (finish_struct): Set the vtable's size to NULL_TREE before - calling layout_decl, so that it gets updated properly. +Sat Apr 4 12:52:35 1998 Jeffrey A Law (law@cygnus.com) - Finally re-enable dynamic synthesis. This time it works. - * method.c (synthesize_method): Pass decl_function_context (fndecl) - to {push,pop}_cp_function_context. - * decl.c (push_cp_function_context): Now takes a tree argument. - (pop_cp_function_context): Ditto. - * call.c (build_method_call): Enable synthesis. - * lex.c (cons_up_default_function): Ditto. + * method.c (check_btype): Add missing argument to xrealloc. + (check_ktype): Likewise. -Tue Mar 14 19:14:19 1995 Doug Evans +Fri Apr 3 02:22:59 1998 Jason Merrill - * parse.y (setattrs): Chain onto prefix_attributes rather than - setting it. + Implement empty base optimization. + * 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. + * tree.c (avoid_overlap): New fn. + (build_base_fields): Use it to avoid overlapping empty bases. + * cp-tree.h, decl2.c, lang-options.h: Add -fnew-abi. -Wed Mar 15 13:00:00 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (cplus_expand_expr_stmt): Strip unused INDIRECT_REFs. - * decl.c (pushdecl): Check if the type of the VAR_DECL is an - error_mark_node before trying to read TYPE_LANG_SPECIFIC. + Re-implement allocation of base class subobjects. + * tree.c (unshare_base_binfos): New fn. + (layout_basetypes): Use it. Now handles offsets of both virtual and + non-virtual bases, after layout_type. + (layout_vbasetypes): Remove. + (build_base_fields): Generate FIELD_DECLs for each non-virtual base. + (build_vbase_pointer_fields): Split out from old layout_basetypes. + * class.c (finish_base_struct): Lose offset handling code. + Move nonvdtor warning here. Don't mess with t_binfo anymore. + (finish_struct_1): Don't mess with t_binfo anymore. Use fns above. + * cp-tree.h: Adjust. -Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com) +Thu Apr 2 14:25:13 1998 Jason Merrill - * decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold, - and convert the size and integer_one_node to the index type. + * cp-tree.h: Lose CLASSTYPE_VBASE_SIZE, some unused stuff. + * decl.c, decl2.c, pt.c, ptree.c, lex.c: Likewise. + * class.c (duplicate_tag_error): Likewise. + (finish_struct_1): Set CLASSTYPE_SIZE, CLASSTYPE_MODE, CLASSTYPE_ALIGN. + * tree.c (layout_vbasetypes): Update from layout_record, remove + var_size support, use CLASSTYPE_SIZE instead of CLASSTYPE_VBASE_SIZE. + (layout_basetypes): Likewise. -Mon Mar 13 08:01:02 1995 Jason Merrill +Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com) - * typeck.c (get_member_function_from_ptrfunc): Save the instance - argument, and tack it onto the front of the COND_EXPR to make the - semantics come out right. Grab the instance argument from - '*instance_ptrptr', rather than having it passed in separately. + * 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. - * various: Change various consed-up comparison operations to have - boolean type. Remove the instance argument in calls to - get_member_function_from_ptrfunc. - - * error.c (dump_expr): Dump true and false as "true" and "false". +Wed Apr 1 15:38:36 1998 Jason Merrill - * decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the - global init function. + * friend.c (is_friend): Fix access control for local classes. - * decl.c (finish_function): Only set DECL_EXTERNAL here if the - inline function is public. + * class.c (is_empty_class): New fn. + * call.c (build_call): Don't pass empty class objects to a function. -Sat Mar 11 00:58:03 1995 Jason Merrill +Wed Apr 1 14:58:35 1998 Mark Mitchell - * init.c (is_friend): Be more careful about checking - DECL_CLASS_CONTEXT on non-member functions. + * call.c (build_over_call): Do name resolution for default + arguments of function templates in the scope of the templates. - * decl2.c (finish_vtable_vardecl): Don't bother calling - assemble_external here. - (prune_vtable_vardecl): New function that just splices out the - vtable decl from the top-level decls. - (import_export_inline): Unset DECL_EXTERNAL at first. - (finish_file): Don't bother calling assemble_external here. Do - splice out all of the vtables. +Tue Mar 31 13:43:57 1998 Jeffrey A Law (law@cygnus.com) -Fri Mar 10 14:42:29 1995 Jason Merrill + * call.c: Include system.h. Remove includes, declarations and + defines provided by system.h. + * class.c, cvt.c, decl.c, decl2.c, errfn.c error.c: Likewise. + * except.c, expr.c friend.c, g++spec.c, init.c, input.c: Likewise. + * lex.c, parse.y, pt.c, ptree.c repo.c rtti.c, search.c: Likewise. + * semantics.c, sig.c, spew.c, tree.c, typeck.c: Likewise. + * typeck2.c, xref.c: Likewise. + * Makefile.in: Dependencies updated as appropriate. + * Make-lang.in: Likewise. - * decl.c (finish_function): If we're not emitting the function yet, - call assemble_external for it. +Mon Mar 30 12:15:00 1998 Mark Mitchell - * decl2.c (finish_prevtable_vardecl): Don't call mark_vtable_entries - here. - (finish_vtable_vardecl): Don't do the linkage deduction thing here. - Also don't splice out the current vtable if it is unused. - (finish_file): Move the second walk_vtables and the synthesis check - inside the 'reconsider' loop. Move thunk emission after the - 'reconsider' loop. - -Thu Mar 9 16:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * pt.c (tsubst): Don't bother calling cp_build_type_variant, since it - was passing bogus values for readonly and volatile from the original - template decl, not the resultant type of the tsubst call. - - * class.c (duplicate_tag_error): Use cp_error_at to point out the - previous definition of the tag. - -Thu Mar 9 10:46:17 1995 Jason Merrill - - * decl.c (start_function): Clear base_init_insns and protect_list. - (struct cp_function): Add base_init_insns field. - (push_cp_function_context): Also save base_init_insns. - (pop_cp_function_context): Also restore base_init_insns. - -Wed Mar 8 13:31:44 1995 Jason Merrill - - * init.c (member_init_ok_or_else): Check for initializing a static - member here. - (emit_base_init): Instead of here. - -Tue Mar 7 16:03:26 1995 Jason Merrill - - * call.c (build_method_call): Disable synthesis as needed. - * lex.c (cons_up_default_function): Ditto. - -Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * parse.y: New rules to allow attributes in a prefix position. - (prefix_attributes): New variable. Pass it into cplus_decl_attributes. - (setattr): New rule. - (reserved_declspecs, declmods): Catch attributes here. - * decl2.c (cplus_decl_attributes): Add PREFIX_ATTRIBUTES argument. - * decl.c (duplicate_decls): Pass DECL_MACHINE_ATTRIBUTES to - descendent typedef. - (grokdeclarator): Added code to support machine attributes. - * Makefile.in (stamp-parse): Expect 5 shift/reduce failures. - -Mon Mar 6 15:07:02 1995 Jason Merrill + * pt.c (fn_type_unification): Allow incomplete unification without + an immediate error message. - * call.c (build_method_call): Don't synthesize methods outside of a - function. +Mon Mar 30 08:55:42 1998 Jason Merrill - Make base initialization more re-entrant so that synthesis on the - fly will work (and, eventually, template instantation on the fly). - * init.c (sort_member_init): Don't bother with members that can't be - initialized. Reorganize a bit. Don't initialize base members here. - (sort_base_init): New function, like sort_member_init, but for base - classes. Steals some code from emit_base_init. - (emit_base_init): Simplify. Call sort_{member,base}_init before - doing any initialization, so we don't have to save - current_{member,base}_init_list in push_cp_function_context. - (expand_aggr_vbase_init_1): Adjust for sort_base_init. - (expand_aggr_vbase_init): Simplify. - * decl.c (struct cp_function): Add protect_list field. - (push_cp_function_context): Also save protect_list. - (pop_cp_function_context): Also restore protect_list. - * call.c (build_method_call): Enable synthesis at point of call. - * lex.c (cons_up_default_function): Ditto. + * tree.c (member_p): New fn. + * decl2.c (finish_file): Only set DECL_STATIC_FUNCTION_P for + initializing class members. - * parse.y: Turn -ansi checks back into -pedantic checks. + * cp-tree.def (TEMPLATE_PARM_INDEX): Class 'x'. + * ptree.c (lang_print_xnode): Handle TEMPLATE_PARM_INDEX. - * init.c (build_new): Fix -fcheck-new for array new. + * call.c (build_method_call): Handle non-scoped destructors, too. + * pt.c (tsubst_copy): Likewise. -Sat Mar 4 15:55:42 1995 Fergus Henderson + * pt.c (print_template_context): Split out... + (push_tinst_level): ...from here. - * typeck.c (build_compound_expr): warn if left-hand operand of - comma expression has no side-effects. + * friend.c (is_friend): Don't pass a type to decl_function_context. -Fri Mar 3 15:16:45 1995 Jason Merrill + * typeck.c (convert_for_initialization): Always hand off + conversions to class type. - * parse.y (primary): Change 'object qualified_id *' rules to 'object - overqualified_id *'. +Sun Mar 29 20:01:59 1998 Jason Merrill -Fri Mar 3 12:48:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * friend.c (is_friend): Local classes have the same access as the + enclosing function. - * parse.y (unary_expr): Catch doing sizeof an overloaded function. - Make the error look the same as the one we issue in c_sizeof. +Sun Mar 29 00:47:32 1998 Jeffrey A Law (law@cygnus.com) - * typeck.c (build_binary_op_nodefault): Give an error for trying - to compare a pointer-to-member to `void *'. + * typeck.c (expand_target_expr): Delete dead function. -Fri Mar 3 11:28:50 1995 Jason Merrill - - * typeck.c (build_unary_op): Handle bool increment with smoke and - mirrors here, rather than in expand_increment where it belongs, - because Kenner doesn't agree with me. - -Fri Mar 3 00:08:10 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * decl.c (grokparms): Catch a PARM_DECL being used for a default - argument as well. - -Thu Mar 2 20:05:54 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * init.c (build_new): Don't allow new on a function type. - - * parse.y (primary): Avoid a crash when seeing if the arg is of - the same type as that given for the typespec in an explicit dtor call. - -Thu Mar 2 00:49:38 1995 Jason Merrill - - * decl.c (finish_function): Change test for calling - mark_inline_for_output. - -Wed Mar 1 11:23:46 1995 Jason Merrill - - * typeck.c (build_modify_expr): Complain if - build_default_binary_type_conversion fails. - - * init.c (expand_default_init): Handle arguments of unknown type - properly. + * search.c: Put various prototypes inside #ifdef MI_MATRIX. - * cvt.c (build_expr_type_conversion): Only complain about ambiguity - if 'complain'. - * various: Pass 'complain'. + * repo.c (save_string): Delete dead function. - * typeck.c (comptypes): Be more picky about comparing UPTs. + * method.c (thunk_printable_name): Delete dead function. -Wed Mar 1 11:03:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * lex.c (yynextch): Delete dead function. - * decl.c (grokdeclarator): If declarator is null, say that the - type used has an incomplete type. + * expr.c (tree_extract_aggr_init): #if 0 out. -Wed Mar 1 10:06:20 1995 Jason Merrill + * except.c (do_unwind): Delete dead function. + (easy_expand_asm): Likewise. - * pt.c (instantiate_template): Copy the template arguments to the - permanent_obstack. Also use simple_cst_equal to compare them when - looking for a previous instantiation. + * cvt.c (build_conversion_type_1): Delete dead function. - * tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming - they are array domain types). + * cp-tree.h (push_expression_obstack): Declare. -Tue Feb 28 23:24:55 1995 Jason Merrill + * call.c (source_type): #if 0 out. - * cp-tree.h: Define WANT_* constants for passing to - build_expr_type_conversion. - * cvt.c (build_expr_type_conversion): New function to build - conversion to one of a group of suitable types. - (build_default_binary_type_conversion): Use it. - * decl2.c (grok_array_decl): Ditto. - * typeck.c (build_unary_op): Ditto. - (build_array_ref): Tidy up a bit. - (build_binary_op): Ditto. + * class.c (alter_access): Remove unused label. Add braces + around empty else clause. -Tue Feb 28 19:57:31 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * lex.c (yyprint): Fix argument to printf. - * decl.c (grokdeclarator): Don't allow decl of an argument as `void'. +Sat Mar 28 17:43:52 1998 Mark Mitchell -Tue Feb 28 17:23:36 1995 Jason Merrill + * pt.c (tsubst): Clear TREE_USED for new FUNCTION_DECLs. - * parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals - reserved_declspecs' rule. + * pt.c (instantiate_class_template): Make sure template + arguments are permanent. + * init.c (resolve_offset_ref): Don't go looking around in + template types. - * parse.y (expr_or_declarator): Remove notype_qualified_id rule. - (direct_notype_declarator): Ditto. - (complex_direct_notype_declarator): Add notype_qualified_id rule. + * semantics.c: Add routines to handle expressions, and some + declaration processing. + * parse.y: Use them. + (current_class_depth): Move declaration to cp-tree.h. + * parse.c: Regenerated. + * cp-tree.h: Use them. + (current_class_depth): Declare. + * pt.c (tsubst_copy): Use begin_stmt_expr and finish_stmt_expr. - * lex.c (real_yylex): Handle :> digraph properly. +Fri Mar 27 20:23:18 1998 Mark Mitchell -Tue Feb 28 12:26:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * decl.c (grokdeclarator): Check if it's a friend, not if it's - non-virtual, that's being initialized. Move the check up to - before FRIENDP would get cleared. Catch an unnamed var/field - being declared void. Say just `field' instead of `structure field' - in the error message. Only go for the operator name if DECLARATOR - is non-null. - -Tue Feb 28 00:08:01 1995 Jason Merrill - - * decl.c (start_function): Complain about abstract return type. - (grokdeclarator): Complain about declaring constructors and - destructors to be const or volatile. Complain about declaring - destructors to be static. - - * pt.c (uses_template_parms): Handle pmfs. - - * decl.c (grokdeclarator): Don't call variable_size for array bounds - that only depend on template constant parameters. - -Mon Feb 27 15:38:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com) - - * error.c (dump_decl): Only look to see if it's a vtable if we - actually have a name to check out. + * error.c (dump_decl): Be a bit more explicit with template + type arguments, when verbose. + +Fri Mar 27 18:16:40 1998 Jason Merrill -Mon Feb 27 13:37:53 1995 Jason Merrill + * inc/exception: Reorder closing braces. - * cvt.c (convert_to_aggr): Lose misleading shortcut. +Fri Mar 27 13:22:18 1998 Mark Mitchell -Sun Feb 26 17:27:32 1995 Doug Evans + * pt.c (redeclare_class_template): New function. + * cp_tree.h (redeclare_class_template): Declare it. + * decl.c (xref_tag): Use it. - * decl.c (set_nested_typename): Always set DECL_IGNORED_P, - not just for dwarf. +Thu Mar 26 11:16:30 1998 Jason Merrill -Sun Feb 26 00:10:18 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * call.c (build_over_call): Check IS_AGGR_TYPE, not + TYPE_LANG_SPECIFIC. + * typeck.c (convert_arguments): Likewise. - * decl.c (grokdeclarator): Don't allow a static member to be - declared `register'. + * decl.c (grokdeclarator): Remove const and volatile from type after + setting constp and volatilep. - * init.c (make_friend_class): Move up to a pedwarn for the warning - about a class declaring friends with itself. + * class.c (finish_struct_1): Don't warn about bool bitfield larger + than one bit. - * decl.c (grokdeclarator): You can't do `volatile friend class foo' - or `inline friend class foo'. Only try to make a friend out of - TYPE if we didn't already reset it to integer_type_node. +Thu Mar 26 10:25:52 1998 Mark Mitchell -Sat Feb 25 22:32:03 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * pt.c (convert_nontype_argument): STRIP_NOPS where appropriate. - * decl.c (grokdeclarator): Don't allow initialization of a - non-virtual function. +Thu Mar 26 10:24:05 1998 Mark Mitchell - * decl.c (start_function): Do a pedwarn if we're changing `main' - to have an int return type. + * call.c (build_object_call): Complain about ambiguous operator(), + rather that crashing. + (build_new_op): Likewise. + (build_op_delete_call): Likewise. -Sat Feb 25 00:02:05 1995 Jason Merrill +Thu Mar 26 10:23:24 1998 Mark Mitchell - * typeck.c (build_modify_expr): Handle simple assignment from - TARGET_EXPRs by building up an RTL_EXPR to force expansion. Whew. + * cvt.c (perform_qualification_conversions): Use comp_target_types + instead of comp_ptr_ttypes. -Fri Feb 24 18:27:14 1995 Brendan Kehoe (brendan@lisa.cygnus.com) +Wed Mar 25 16:10:50 1998 Mark Mitchell - * decl.c (grokdeclarator): Also don't allow virtual outside of a - class decl for a scope method definition performed at global binding. + * cp-tree.h (enforce_access): Declare. + * call.c (enforce_access): Make it extern, not static. + * class.c (alter_access): Use enforce_access; modify code for ISO + compliance, rather than ARM rules. - * init.c (build_offset_ref): Don't allow creation of an OFFSET_REF - of a bitfield. +Wed Mar 25 12:10:45 1998 Kriang Lerdsuwanakij - * decl.c (grokdeclarator): Don't allow a const to be declared mutable. + * cp-tree.h: Fix typo. - * typeck.c (build_binary_op): Return an error_mark_node if either - one of the args turned into an error_mark_node when we tried to - use default_conversion. +Wed Mar 25 02:01:02 1998 Jason Merrill - * typeck.c (build_unary_op): Forbid using postfix -- on a bool. + * expr.c (cplus_expand_expr): Only do PCC_STATIC_STRUCT_RETURN thing + if (aggregate_value_p (type)). - * decl.c (grokdeclarator): Allow `signed' and `unsigned' to be - used on `__wchar_t'. + * decl2.c (constructor_name_full): Handle TYPENAME_TYPE. -Fri Feb 24 13:59:53 1995 Mike Stump +Tue Mar 24 16:12:01 1998 Mark Mitchell - * except.c (end_protect_partials): Do it the right way. + * tree.c (mapcar): When dealing with a DECL, use it's constant + value, if any. + * pt.c (lookup_template_class): Don't mangle the names of template + classes whose arguments are unknown. -Wed Feb 22 15:42:56 1995 Jason Merrill + * pt.c (tsubst_expr): Handle GOTO_STMT correctly. - * typeck.c (build_binary_op_nodefault): Upgrade warning about - comparing distinct pointer types to pedwarn. +Tue Mar 24 12:21:55 1998 Benjamin Kosnik - * typeck2.c (digest_init): Cope with extra braces. + * decl.c (init_decl_processing): Set TYPE_PRECISON for bools to 1. - * typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead - of INT_CST_LT (..., interger_zero_node). +Tue Mar 24 12:21:48 1998 Jim Wilson -Wed Feb 22 14:45:52 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for + boolean_type_node to 1. - * except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy - function for systems that don't have EH. +Tue Mar 24 10:23:47 1998 Mark Mitchell -Tue Feb 21 19:18:31 1995 Jason Merrill + * error.c (dump_expr): Remove unused variable `l'. - * call.c (can_convert_arg): Like can_convert, but takes an arg as - well. + * pt.c (for_each_template_parm): New function, created by + converting uses_template_parms. + (tree_fn_t): New typedef. + (uses_template_parms): Use it. + (mark_template_parm): New function. + (push_template_decl): Check that the argument list of a partial + specialization uses all the template parameters. - * pt.c (type_unification): Allow implicit conversions for parameters - that do not depend on template parameters. + * Make-lang.in (c++filt): Don't delete cxxmain.c after we're done + with it; we might want it for debugging. + * cp-tree.h (type_unification): Change interface. + * class.c (finish_struct_1): Skip nested template types, just like + ordinary nested types. + (instantiate_type): Use new interface to type_unification. + * lex.c (init_lex): Add __sz as opname for sizeof. + * method.c (build_overload_scope_ref): New function. + (build_overload_int): Handle complex expressions. Set + numeric_output_need_bar if necessary. + (build_overload_value): Handle non-PARM_DECL nodes; this + routine is now used by build_overload_int. Remove some + assignments to numeric_output_need_bar. Use + build_overload_scope_ref. + (build_qualified_name): Note that some template mangled names end + with digits, and set numeric_output_need_bar appropriately. Use + build_underscore_int. + * pt.c (unify): Change interface. + (type_unification_real): Likewise. + (determine_specialization): Use new interfaces. + (tsubst): Deal gracefully with situations in which the argument + vector is not fully filled. + (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. -Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu) +Mon Mar 23 12:24:37 1998 Jason Merrill - * Make-lang.in, config-lang.in: ($exeext): New macro. - * Make-lang.in: Try a "cp" if "ln" fails. - * cp-tree.h (decl_attributes): Added argument. - * decl2.c (cplus_decl_attribute): Add arg to decl_attributes. - * cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT. - Modified spawnvp to have to correct number of arguments for OS/2, NT. + * pt.c (complete_template_args): Initialize skip properly. -Tue Feb 21 18:36:55 1995 Mike Stump + * decl.c (make_typename_type): Revert. + (make_implicit_typename): Remove. + (lookup_name_real): Don't call it. Call lookup_field if we see a + TYPE_DECL from a template base. + * search.c (lookup_field): Do implicit typename stuff. - * decl.c (finish_function): Add calls to end_protect_partials to end - the exception region that protects constructors so that partially - constructed objects can be partially destructed when the constructor - throws an exception. - * init.c (perform_member_init, sort_member_init, emit_base_init): - Added support for partially constructed objects. - * init.c (build_partial_cleanup_for): New routine to do partial - cleanups of a base class. - * decl2.c (finish_file): Move the emitting of the exception table - down, after we emit all code that might have exception regions in - them. - * except.c (end_protect_partials, might_have_exceptions_p): New - routines. - (emit_exception_table): Always output table if called. - * cp-tree.h (protect_list, end_protect_partials, - might_have_exceptions_p, emit_exception_table): Added. +Sun Mar 22 00:50:42 1998 Nick Clifton + Geoff Noer -Tue Feb 21 16:05:59 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + * Makefile.in: Various fixes for building cygwin32 native toolchains. + * Make-lang.in: Likewise. - * gc.c (build_typeid): Pass a NULL_TREE, not the bogus, unused - address of a local variable. - * class.c (build_vfn_ref): Only try to build the PLUS_EXPR if we - were given a non-null PTR_TO_INSTPTR. +Fri Mar 20 18:07:39 1998 Kriang Lerdsuwanakij -Tue Feb 21 01:53:18 1995 Jason Merrill + * pt.c (tsubst, TEMPLATE_TEMPLATE_PARM): Simplify. - * decl.c (duplicate_decls): Always lay out the merged decl. +Fri Mar 20 10:42:07 1998 Jason Merrill - * decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates. - (finish_prevtable_vardecl): Ditto. + * decl.c (make_implicit_typename): Rewrite removed code. + (make_typename_type): Call it if the type we look up comes from + a base that uses template parms. - * method.c (synthesize_method): Set interface_{unknown,only} - according to the settings for our class, not the file where it comes - from. + * pt.c (complete_template_args): Rewrite. + (tsubst, FUNCTION_DECL): Use it. -Sat Feb 18 12:26:48 1995 Mike Stump +Fri Mar 20 08:12:43 1998 H.J. Lu (hjl@gnu.org) - * except.c: Handle systems that define __i386__ but not __i386. + * semantics.c (finish_asm_stmt): Fix combine strings. Call + c_expand_asm_operands () if output_operands, input_operands or + clobbers is not NULL_TREE. -Fri Feb 17 15:31:31 1995 Jason Merrill +Fri Mar 20 00:10:19 1998 Kriang Lerdsuwanakij - * decl2.c (reparse_decl_as_expr): Support being called without a - type argument. + * pt.c (complete_template_args): New function. + (get_bindings): Deal with specializations of function templates + with return type containing parameters from outer class + templates. + (tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level, + substitute arguments and compose a new type. - * parse.y (primary): Add '(' expr_or_declarator ')'. Adds 4 r/r - conflicts. Sigh. +Thu Mar 19 19:01:48 1998 Mark Mitchell -Fri Feb 17 12:02:06 1995 Mike Stump + * pt.c (tsubst): Clear DECL_PENDING_INLINE_INFO for new + FUNCTION_DECLs. - * parse.y (template_def, fndef, fn.def1, return_init, condition, - initdcl0, initdcl, notype_initdcl0, nomods_initdcl0, - component_decl_1, after_type_component_declarator0, - notype_component_declarator0, after_type_component_declarator, - notype_component_declarator, after_type_component_declarator, - full_parm, maybe_raises, exception_specification_opt): Fix up, - include exception_specification_opt maybeasm maybe_attribute and - maybe_init if missing. Rename maybe_raises to - exception_specification_opt to match draft wording. Use maybe_init - to simplify rules. +Thu Mar 19 11:51:58 1998 Jason Merrill -Fri Feb 17 01:54:46 1995 Jason Merrill + * decl.c (make_implicit_typename): Lose useless code. - * init.c (build_new): Set TREE_NO_UNUSED_WARNING on COMPOUND_EXPRs - built for news of scalar types. + * call.c (standard_conversion): Handle A* -> const A* properly. -Thu Feb 16 17:48:28 1995 Jason Merrill + * pt.c (get_bindings_real): Rename from get_bindings. Add + check_rettype parm. + (get_bindings): Pass 1. + (get_bindings_overload): Pass 0. - * typeck.c (build_binary_op_nodefault): Update code for warning - about signed/unsigned comparisons from C frontend. Realize that the - code in the C frontend is, if anything, even more bogus. Fix it. - (build_binary_op): Undo default_conversion if it wasn't useful. +Wed Mar 19 09:08:12 1998 Mark Mitchell - * typeck.c (build_unary_op, ADDR_EXPR): Lose bogus special case for - PRE*CREMENT_EXPR. + * pt.c (check_explicit_specialization): When reverting a static + member function, also remove the `this' parameter from + last_function_parms. - * decl2.c (import_export_vtable): Don't try the vtable hack - if the class doesn't have any real non-inline virtual functions. - (finish_vtable_vardecl): Don't bother trying to find a non-inline - virtual function in a non-polymorphic class. - (finish_prevtable_vardecl): Ditto. +Thu Mar 19 02:27:48 1998 Jason Merrill - * decl2.c (import_export_vtable): Use and set DECL_INTERFACE_KNOWN. + * pt.c (tsubst_copy, CONST_DECL): Don't bother tsubsting + a function context. - * cp-tree.h (DECL_INTERFACE_KNOWN): Use DECL_LANG_FLAG_5. + * decl.c (store_bindings): Use free_binding_vecs. + (pop_from_top_level): Likewise. - * init.c (expand_virtual_init): Always call assemble_external. +Wed Mar 18 12:41:43 1998 Jason Merrill - * class.c (build_vfn_ref): Always call assemble_external. - (build_vtable): Always call import_export_vtable. - (prepare_fresh_vtable): Ditto. - (add_virtual_function): Don't bother setting TREE_ADDRESSABLE. + * decl.c (make_implicit_typename): Only change the type of a + TYPENAME_TYPE. -Thu Feb 16 03:28:49 1995 Jason Merrill +Wed Mar 18 10:09:51 1998 Mark Mitchell - * class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine - whether an enumerated type fits in a bitfield. + * semantics.c: New file, containing routines to perform the + semantic phase of parsing. + * parse.y: Use it. + * pt.c (tsubst_expr): Likewise. + * cp-tree.h: Declare the various functions in semantics.c. + Provide macros to access _STMT tree nodes. + * 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 -Wed Feb 15 15:38:12 1995 Jason Merrill + * pt.c (push_template_decl): Only check primary templates. - * class.c (grow_method): Update method_vec after growing the class - obstack. + * pt.c (check_explicit_specialization): Complain about default args + in explicit specialization. -Wed Feb 15 13:42:59 1995 Mike Stump + * parse.y (nomods_initdcl0): Also call cp_finish_decl for a + constructor_declarator. - * parse.y (handler_seq): Push a level for the catch parameters. +Tue Mar 17 14:44:54 1998 Mark Mitchell -Wed Feb 15 12:42:57 1995 Jason Merrill + * typeck2.c (build_x_arrow): Don't crash when an aggregate type + has no overloaded operator ->. - * init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my - bases, in case they've been clobbered. + * call.c (build_field_call): Don't crash when presented with a + field that is actually a nested type. -Wed Feb 15 12:07:29 1995 Mike Stump + * decl.c (pushtag): Deal with friend class injection in local + classes. - * class.c (finish_base_struct): Set up BINFO_INHERITANCE_CHAIN here, - so that one day it will always be valid. - * tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto. + * call.c (build_object_call): Don't crash if OBJ is a + pointer-to-member-function. - * cp-tree.h (copy_binfo): Removed, unused. - * tree.c (copy_binfo): Ditto. +Tue Mar 17 11:40:26 1998 Jason Merrill -Wed Feb 15 00:05:30 1995 Jason Merrill + * pt.c (push_template_decl): Complain about template with C linkage, + anonymous template class. - * init.c (build_new): Save the allocation before calling - expand_vec_init on it. +Mon Mar 16 12:10:39 1998 Jason Merrill - * decl.c (finish_enum): The TYPE_PRECISION of the enum type mush - match the TYPE_PRECISION of the underlying type for constant folding - to work. + * class.c (pushclass): Only use the mi_matrix stuff #ifdef MI_MATRIX. + * search.c: Likewise. -Tue Feb 14 15:31:25 1995 Mike Stump + * lex.c (do_pending_defargs): Only call + maybe_{begin,end}_member_template_processing for FUNCTION_DECLs. - * except.c (push_eh_entry, expand_start_all_catch, - expand_leftover_cleanups, expand_end_catch_block): Keep track of - the context in which the exception region occurs. - (build_exception_table): If the region was not output, don't output - the entry in the eh table for it. + * parse.y (initdcl0_innards): Move maybeasm back into initdcl0 et al. -Tue Feb 14 02:15:43 1995 Jason Merrill +Mon Mar 16 10:47:22 1998 Mark Mitchell - * init.c (expand_default_init): Only use a previous constructor call - if it's a call to our constructor. Does the word "Duh" mean - anything to you? + * parse.y: Deal with CONSTRUCTORS in new_initializers. - * decl.c (grokparms): Fine, just don't call - convert_for_initialization at all. OK? Happy now? +Mon Mar 16 10:54:21 1998 Mark Mitchell -Mon Feb 13 02:23:44 1995 Jason Merrill + * 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 + into a compound statement. + +Sun Mar 15 02:07:26 1998 Jason Merrill - * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class - method vector has a second element before returning it. + * cp-tree.h (TEMPLATE_PARMS_FOR_INLINE): New macro. + * pt.c (inline_needs_template_parms): New fn. + (original_template): New fn. + (push_inline_template_parms_recursive): New fn. + (maybe_begin_member_template_processing): Use them. + (maybe_end_member_template_processing): Likewise. + (is_member_or_friend_template): Rename to is_member_template. + Member functions of local classes are never member templates. - * decl.c (grokparms): Don't strip REFERENCE_TYPE before calling - convert_for_initialization. +Sun Mar 15 01:14:22 1998 Kriang Lerdsuwanakij -Sun Feb 12 03:57:06 1995 Jason Merrill + * lex.c (do_identifier): Handle TEMPLATE_DECL that was + added in the class scope to catch redefinition error. - * typeck.c (build_modify_expr): Compare function name to - constructor_name (current_class_type) instead of current_class_name. + * pt.c (reduce_template_parm_level): Also copy + the DECL_TEMPLATE_PARMS field. - * decl.c (grokparms): Don't do anything with the return value of - convert_for_initialization. +Sun Mar 15 10:54:08 1998 Mark Mitchell - * error.c (dump_decl): Also dump_readonly_or_volatile on the decl. + * pt.c (tsubst): Clear TYPE_REFERENCE_TO when creating a + reduced-level template type parameter. - * decl.c (duplicate_decls): Tweak error message. +Sun Mar 15 12:26:02 1998 Manfred Hollstein - * typeck.c (build_const_cast): Implement checking. - (build_reinterpret_cast): Implement some checking. + * cp-tree.h (struct lang_decl_flags): Add needs_final_overrider. + (DECL_NEEDS_FINAL_OVERRIDER_P): New macro. + * class.c (override_one_vtable): Set DECL_NEEDS_FINAL_OVERRIDER_P. + * decl.c (duplicate_decls): Propagate it. + * 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 - * cp-tree.h (CONV_FORCE_TEMP): Require a new temporary when - converting to the same aggregate type. - (CONV_STATIC_CAST): Include it. - (CONV_C_CAST): Ditto. - * cvt.c (convert_force): Use CONV_C_CAST instead of CONV_OLD_CONVERT. - (cp_convert): Only force a new temporary if CONV_FORCE_TEMP. + * lang-specs.h: Properly put brackets around array elements in + initializer. -Fri Feb 10 16:18:52 1995 Jason Merrill + * typeck.c (build_binary_op_nodefault): Correctly place parens around + && and || in expression. - * typeck.c (build_c_cast): Use non_lvalue to tack something on - where necessary. +Thu Mar 12 09:26:04 1998 Manfred Hollstein - * decl.c (auto_function): Now a function. - * except.c (init_exception_processing): terminate, unexpected, - set_terminate, and set_unexpected have C++ linkage. + * call.c (default_parm_conversions): Remove prototype definition. + (build_method_call): Remove unused variable result. - * typeck.c (build_unary_op, TRUTH_NOT_EXPR): Use convert instead of - truthvalue_conversion for converting to bool, as it handles - user-defined conversions properly. - (condition_conversion): Ditto. + * cvt.c (ocp_convert): Remove unused variable conversion. - * except.c (expand_throw): Don't call convert_to_reference. - Pass the correct parameters to build_new. + * decl2.c (ambiguous_decl): Add explicit parameter definition for name. - * method.c (do_build_assign_ref): Don't use access control when - converting to a base reference here. - (do_build_copy_constructor): Or here. + * except.c (do_unwind): #if 0 definition of unused variables fcall + and next_pc. - * init.c (build_new): Unset TREE_READONLY on the dereferenced - pointer before assigning to it. + * expr.c (extract_scalar_init): #if 0 prototype and function + definition. - * decl.c (maybe_build_cleanup): Don't bother stripping const here. + * init.c (expand_aggr_init_1): Remove unused variable init_type. + (build_new_1): Remove unused variable t. - * decl2.c (delete_sanity): You can now delete pointer to const. + * pt.c (instantiate_class_template): Remove unused variable newtag; + cast called function return value to void. + (do_decl_instantiation): Remove unused variables name and fn. -Fri Feb 10 13:28:38 1995 Jason Merrill + * tree.c (get_type_decl): Add default return to shut up compiler from + complaining control reaches end of non-void function. - * decl.c (finish_function): Don't rely on actual parameters being - evaluated left-to-right. - * except.c (expand_end_catch_block): Ditto. + * typeck.c (build_x_conditional_expr): Remove unused variable rval. -Fri Feb 10 00:52:04 1995 Jason Merrill +Thu Mar 12 09:12:15 1998 Manfred Hollstein - * tree.c (real_lvalue_p): Like lvalue_p, but class temps aren't - considered lvalues. - * cvt.c (convert_to_reference): Use real_lvalue_p instead of - lvalue_p. + * call.c (default_parm_conversions): Remove prototype definition. + (build_method_call): Remove unused variable result. + (build_over_call): Add default case in enumeration switch. - * cvt.c (build_type_conversion_1): Don't call convert on aggregate - types. - (convert_to_reference): Fix erroneous text substitution. +Thu Mar 12 08:39:13 1998 Manfred Hollstein - * typeck2.c (initializer_constant_valid_p): Update from C frontend. - Add new argument to all callers. + * decl2.c (lang_decode_option): Change j's type to size_t. - * typeck.c (convert_arguments): Check for error_mark_node before - trying to do anything with the actual parameter. + * tree.c (layout_vbasetypes): record_align and desired_align are of + type unsigned int; const_size and nonvirtual_const_size likewise. - * typeck.c (condition_conversion): Build up a CLEANUP_POINT_EXPR and - fold it. - (bool_truthvalue_conversion): Remove. Fix all callers to call - truthvalue_conversion instead. - (various): Fold CLEANUP_POINT_EXPRs. +Wed Mar 11 07:25:20 1998 Mark Mitchell - * parse.y (conditions): Call condition_conversion rather than - building up a CLEANUP_POINT_EXPR. + * parse.y (new_initializer): Make sure all initializers are + lists. - * pt.c (end_template_decl): Don't warn_if_unknown_interface here - under -falt-external-templates. +Tue Mar 10 07:32:36 1998 Mark Mitchell -Thu Feb 9 05:24:10 1995 Jason Merrill + * decl2.c (import_export_decl): Mark tinfo functions for + cv-qualified versions of class types as DECL_NOT_REALLY_EXTERN. - * init.c (build_new): Complain about new of const type without - initializer. Other cleanup. +Fri Mar 6 23:27:35 1998 Jeffrey A Law (law@cygnus.com) - * call.c (compute_conversion_costs): Don't call - build_type_conversion with a reference type; convert to the target - type and check its lvaluetude. - * cvt.c (convert_to_reference): Ditto. + * method.c: Fix typo. - * cvt.c (build_type_conversion_1): There will never be any need to - dereference references here now. +Fri Mar 6 10:06:59 1998 Kaveh R. Ghazi -Thu Feb 9 00:37:47 1995 Mike Stump + * 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. - * except.c (expand_builtin_throw): Make sure we only `use' the - value of return_val_rtx. +Wed Mar 4 22:26:53 1998 Andreas Schwab -Wed Feb 8 15:45:55 1995 Jason Merrill + * lex.c (do_scoped_id): Fix parenthesizing. - * parse.y (structsp): Don't complain about declaring a type being - defined to be a friend. +Wed Mar 4 12:11:53 1998 Michael Tiemann - * decl2.c (warn_if_unknown_interface): Note the template in question - and the point of instantiation, for -falt-external-templates. - * lex.c (reinit_parse_for_method): Pass the decl to - warn_if_unknown_interface. - * pt.c (instantiate_template): Ditto. - (end_template_decl): Ditto. + * 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. - * decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the - nested name again, to make local classes work a bit better. +Wed Mar 4 11:47:55 1998 Jason Merrill - * typeck.c (build_function_call_real): Dereference reference after - checking for incomplete type. + * typeck.c (unary_complex_lvalue): &D::i has type B::* if i comes + from B. - * init.c (build_new): Accept new of const and volatile types. +Wed Mar 4 11:28:08 1998 Mark Mitchell -Wed Feb 8 14:04:16 1995 Jason Merrill + * pt.c (finish_member_template_decl): Deal more gracefully with + invalid declarations. - * decl.c (grokdeclarator): Fix error message. +Tue Mar 3 01:38:17 1998 Jason Merrill -Wed Feb 8 03:16:15 1995 Jason Merrill + * cvt.c, decl.c, decl2.c, init.c, rtti.c, typeck.c, typeck2.c, + cp-tree.h: Clean up more old overloading code, old RTTI code, and + some formatting quirks. - * typeck.c (convert_for_initialization): Do bash arrays when - converting to a reference to non-array. + * 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 + -fno-ansi-overloading and overloading METHOD_CALL_EXPR. + * class.h: Remove. + * Makefile.in: Adjust. -Tue Feb 7 15:50:33 1995 Jason Merrill + * pt.c (unify): Don't allow reduced cv-quals when strict. - * cvt.c (cp_convert): Don't call convert_to_reference, or - automatically dereference references. Do pass reference conversions - to cp_convert_to_pointer. - (cp_convert_to_pointer): Support references. + * call.c, class.c, pt.c, cp-tree.h: Remove nsubsts parm from + *type_unification* and unify. - * call.c (build_method_call): Don't build up a reference to the - parameter here; let build_overload_call handle that. +Mon Mar 2 12:11:06 1998 Jason Merrill - * typeck.c (build_c_cast): Call convert_to_reference directly if - converting to a reference type. - * method.c (do_build_copy_constructor): Ditto. - * method.c (do_build_copy_constructor): Ditto. - (do_build_assign_ref): Ditto. + * parse.y (explicit_template_type): Remove TEMPLATE keyword. + (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 + anything if our type uses template parms. - * call.c (build_method_call): Dereference a returned reference. - * typeck.c (build_function_call_real): Ditto. +Mon Mar 2 11:04:59 1998 Jim Wilson - * decl.c (xref_basetypes): Check for unions with basetypes here. - (xref_tag): Instead of here. + * decl.c (start_function): Don't call temporary_allocation for a + nested function. - * pt.c (process_template_parm): Template type parm decls are - artificial. +Sun Mar 1 21:06:37 1998 Jason Merrill -Mon Feb 6 04:32:09 1995 Jason Merrill + * pt.c (instantiate_class_template): Don't mess with friends if + our type uses template parms. - * parse.y (typed_declspecs): Add missing semicolon. - (do_xref_defn): Resurrect. - (named_class_head_sans_basetype): Move template specialization - definition cases to named_class_head_sans_basetype_defn. +Sat Feb 28 12:06:44 1998 Jason Merrill - * decl2.c (grokfield): Call pushdecl_class_level after setting the - TYPE_NAME, not before. + * parse.y (nested_name_specifier): Use explicit_template_type. + (typename_sub): Allow a template_type, an explicit_template_type, + or an implicit template type at the end. + * 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 + destructor call. + * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member + destructor is represented by the type. -Sun Feb 5 02:50:45 1995 Jason Merrill + * cp-tree.h (TYPENAME_TYPE_FULLNAME): New macro. + * parse.y (nested_name_specifier): Add 'template' case. + (explicit_template_type): New rule. + (typename_sub): Use it. + * decl.c (make_typename_type): Handle getting a template-id for NAME. + * pt.c (tsubst): Likewise. - * call.c (convert_harshness): Don't call sorry here. Don't allow - conversions between function pointer types if pedantic. +Fri Feb 27 11:17:50 1998 Jason Merrill - * pt.c (overload_template_name): Pass globalize=1 to xref_tag. + * pt.c (add_to_template_args): Fix thinko. + (instantiate_class_template): Call it later. - * lex.c (cons_up_default_function): Use the full name for the return - type of op=. + * pt.c (get_class_bindings): Add outer_args parm. + (most_specialized_class): Likewise. + (instantiate_class_template): Pass it. + (more_specialized_class): Likewise. + (lookup_template_class): Get context from template if none + was specified. + (finish_member_template_decl): Don't do anything with a + partial specialization. + * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of + AGGREGATE_TYPE_P. + * class.c (finish_struct): Member class templates have already been + checked for name clashes. + * decl.c (pushdecl_with_scope): Handle pushing at class level. + +Fri Feb 27 02:25:16 1998 Jason Merrill + + * pt.c (tsubst, TEMPLATE_DECL): Support member class templates. + (tsubst, *_PARM): Support multiple levels of template classes. + (instantiate_class_template): Look up the pattern from the + original template. + (lookup_template_class): Handle getting a template for d1. + (push_template_decl): Correct setting of 'primary'. + (reduce_template_parm_level): Add 'levels' parm. + (finish_member_template_decl): Support member class templates. + (template_class_depth): Handle multiple levels. + * parse.y (component_decl_1, fn.def2): Remove member template case. + (component_decl): Add member template cases. + * decl2.c (check_member_template): We now handle member template + classes. + * 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 + return it. + * spew.c (yylex): Handle PTYPENAME like TYPENAME. + + * typeck.c (get_delta_difference): Do adjust for conversions to + and from virtual base. + +Wed Feb 25 09:51:29 1998 Jason Merrill + + * typeck.c (get_delta_difference): Give hard error for conversion + from virtual base. + + * cp-tree.h: Tweak formatting. + +Wed Feb 25 00:35:33 1998 Jason Merrill + + * decl.c (push_namespace): Handle redeclaration error. + + * cp-tree.h (IDENTIFIER_NAMESPACE_VALUE): New macro. + (IDENTIFIER_NAMESPACE_BINDINGS): New macro. + (NAMESPACE_BINDING): New macro. + (IDENTIFIER_GLOBAL_VALUE): Use NAMESPACE_BINDING. + * *.c: Use them. + + * pt.c (push_template_decl): Use innermost_args. + + * decl.c (get_unique_name): Tweak from earlier in the name. + +Tue Feb 24 22:15:04 1998 Martin von Loewis + + * 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 + * 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. + (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. + (lookup_name_real): For global scoping, lookup in + global_namespace. For namespace scoping, lookup in given + namespace. For unscoped lookup, iterate over namespace, + considering using directives. + (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. + (build_qualified_name): Likewise. + (build_decl_overload_real): Likewise. + * lex.c (build_lang_decl): set namespace for new declaration to + current_namespace. + (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 + build_x_function_call instead. + (build_offset_ref): When scope is namespace, collapse processing + to lookup_namespace_name instead. + * error.c (dump_decl): Support NAMESPACE_DECL. + * decl.c (pushdecl): Bind globals to current namespace. + (push_overloaded_decl): Likewise. + (lookup_tag): Likewise. + (lookup_name_current_level): Likewise. + (xref_tag): Likewise. + (start_function): Likewise. + * lex.c (do_identifier): Likewise. + (identifier_typedecl_value): Likewise. + (real_yylex): Likewise. + * method.c (do_inline_function_hair): Likewise. + * parse.y (unscoped): Likewise. + * pt.c (check_explicit_specialization): Likewise. + (lookup_template_class): Likewise. + * rtti.c (call_void_fn): Likewise. + * sig.c (build_sigtable): Likewise. + * ptree.c (lang_print_xnode): New function. + +Tue Feb 24 01:40:24 1998 Jason Merrill + + * 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, + fail silently. + * decl.c (xref_basetypes): Do call complete_type for basetypes + that involve template parameters. + +Tue Feb 24 00:36:43 1998 Jason Merrill + + * typeck2.c (process_init_constructor): Fix labeled init check. + +Mon Feb 23 05:08:55 1998 Jason Merrill + + * pt.c, call.c, decl.c, method.c, cp-tree.h: Remove unused NARGS + argument to tsubst and friends. + + * pt.c (tsubst, FUNCTION_DECL): Tidy. + + * typeck.c (build_x_function_call): Handle static member function + templates like non-templates. Handle friend templates like normal + function templates. + * pt.c (tsubst, *_PARM): Don't use orig_level. + (get_bindings): Don't call add_to_template_args. + (instantiate_template): Likewise. + (tsubst, FUNCTION_DECL): Call add_to_template_args as appropriate. + * ptree.c (print_lang_type): Print index/level for template parms. - * decl.c (set_nested_typename): Don't worry about anonymous types, - as they already have a unique name. - (pushdecl): Remove redundant set_nested_typename - (xref_tag): Split out base handling into xref_basetypes. +Mon Feb 23 02:52:29 1998 Mark Mitchell - * cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are - not considered incomplete even though their definition is unknown. + * 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. + * cp-tree.h (template_parm_index): New structure, used as the tree + structure for a TEMPLATE_PARM_INDEX. + (TEMPLATE_PARM_IDX): New macro. + (TEMPLATE_PARM_LEVEL): Likewise. + (TEMPLATE_PARM_DESCENDANTS): Likewise. + (TEMPLATE_PARM_ORIG_LEVEL): Likewise. + (TEMPLATE_PARM_DECL): Likewise. + (TEMPLATE_TYPE_PARM_INDEX): Likewise. + (TEMPLATE_TYPE_ORIG_LEVEL): Likewise. + (TEMPLATE_TYPE_DECL): Likewise. + (TEMPLATE_CONST_IDX): Remove. + (TEMPLATE_CONST_LEVEL): Likewise. + (TEMPLATE_CONST_SET_INFO): Likewise. + (TEMPLATE_TYPE_SET_INFO): Likewise. + (TEMPLATE_TYPE_IDX): Redefine in terms of TEMPLATE_PARM_INDEX + node. + (TEMPLATE_TYPE_LEVEL): Likewise. + * decl.c (decls_match): Call comp_template_parms, rather than + expanding it inline. + (duplicate_decls): If two template declarations are being merged, + then their TEMPLATE_INFOs should be merged as well. + (grokfndecl): Save template-id information when declaring a friend + with explicit template arguments. Pass arguments to + check_explicit_specialization via correct convention; at some + point check_explicit_specialization changed, but these call-sites + did not. + (grokdeclarator): Tidy up slightly. + * decl2.c (check_classfn): Tidy up slightly. Don't assume that + 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. + (dump_expr): Likewise. Use the TEMPLATE_PARM_DECL to get at the + decl for a non-type parameter, rather than printing `'. + * friend.c (is_friend): Handle TEMPLATE_DECL friends. + (do_friend): Deal with template friends. + * lex.c (do_pending_inlines): Call + maybe_begin_member_template_processing, rather than + conditionally calling begin_member_template_processing. + (process_next_inline): Likewise. Call + maybe_end_member_template_processing, rather than + conditionally calling end_member_template_processing. + (do_pending_defargs): Likewise. + (do_identifier): Use TEMPLATE_PARM_INDEX instead of + TEMPLATE_CONST_PARM. + * method.c (build_mangled_template_parm_index): New function. + (build_overload_value): Use it. + (build_overload_name): Likewise. + * pt.c (finish_member_template_decl): Allow friend declarations. + (template_class_depth): New function. + (is_member_template): Rename, and modify, to become... + (is_member_or_friend_template): New function. + (end_member_template_processing): Rename, and modify, to become... + (maybe_end_member_template_processing). + (build_template_parm_index): New function. + (reduce_template_parm_level): New function. + (process_template_parm): Modify to use build_template_parm_index. + (push_template_decl): Deal with friend templates. + (uses_template_parms): Use TEMPLATE_PARM_INDEX instead of + TEMPLATE_CONST_PARM. + (tsubst_friend_function): New function. + (instantiate_class_template): Generate the DECL_FRIENDLIST + for a new instantiation by using tsubst_friend_function rather + than just tsubst. + (tsubst): Don't tsubst into a type which is a TEMPLATE_DECL. + Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM, and the + appropriate new macros. Use reduce_template_parm_level to + generate lower-level template parameters. Handle tsubst'ing into + TEMPLATE_DECLS that declare TEMPLATE_TEMPLATE_PARMS. Don't forget + to tsubst the DECL_CONTEXT and DECL_CLASS_CONTEXT of newly created + templates. Similarly for the template parameters for a new + 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. + (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 + clarify the code. + +Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com) - * decl.c (xref_defn_tag): Lose. - (xref_tag): xref_next_defn = ! globalize. - (pushdecl): Don't set DECL_NESTED_TYPENAME on artificial decls. The - ones that should have it set will have it set by pushtag. - (pushdecl_class_level): Ditto. - (pushtag): Tidy up a bit. - (set_nested_typename): Push a decl for the nested typename from - here, rather than from xref_defn_tag. + * error.c: Include sys/types.h. - * parse.y (do_xref): Lose. - (named_class_head): If we see 'class foo:' we know it's a - definition, so don't worry about base lists for non-definitions. +Thu Feb 19 14:49:09 1998 Jeffrey A Law (law@cygnus.com) - * pt.c (push_template_decls): Template parm decls are artificial. + * method.c (build_mangled_name): Start CPP directives in column zero. - * decl.c (duplicate_decls): Restore check for qualifier - disagreement for non-functions. - (decls_match): Remove check for qualifier disagreement. +Thu Feb 19 10:36:48 1998 Jason Merrill -Fri Feb 3 14:58:58 1995 Jason Merrill + * typeck2.c (process_init_constructor): Sorry about non-trivial + labeled initializers. + * parse.y (initlist): Reenable labeled initializers. - * decl.c (grok_reference_init): Convert initializer from - reference. - * typeck.c (convert_for_initialization): Ditto. +Thu Feb 19 10:15:55 1998 Kriang Lerdsuwanakij - * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME. + * 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 - * cvt.c (cp_convert): Don't convert to the same class type by just - tacking on a NOP_EXPR. - (convert_to_reference): Use comp_target_types instead of comptypes - so that we don't allow conversions two levels down. + * cvt.c (cp_convert_to_pointer): Preserve TREE_CONSTANT. + * typeck2.c (initializer_constant_valid_p): Allow conversions + between pointers and refrerences. -Thu Feb 2 15:07:58 1995 Jason Merrill +1998-02-19 Brendan Kehoe - * class.c (build_vbase_path): Bash types to make the backend happy. - * cvt.c (build_up_reference): Bash the types bashed by - build_vbase_path to be reference types instead of pointer types. - (convert_to_reference): Ditto. + * typeck.c (build_unary_op): Only warn about incr/decr a pointer + if pedantic || warn_pointer_arith. - * typeck.c (build_c_cast): Don't strip NOPs if we're converting to a - reference type. +Thu Feb 19 09:37:21 1998 Kriang Lerdsuwanakij - * parse.y (structsp): Put back error for 'struct B: public A;'. + * pt.c (unify): Handle TEMPLATE_DECL. -Wed Feb 1 23:02:06 1995 Mike Stump +1998-02-18 Brendan Kehoe - * except.c: Add support for mips systems that don't define __mips - but do define mips, like Ultrix. + * cp-tree.h (strip_attrs): Remove decl. -Wed Feb 1 22:39:07 1995 Mike Stump +1998-02-18 Doug Evans - * except.c: Add support for exception handling on the Alpha. + * decl.c (duplicate_decls): Call merge_machine_decl_attributes. + Update olddecl's attributes too. + (strip_attrs): Remove function. + * typeck.c (common_type): Call merge_machine_type_attributes. -Wed Feb 1 10:12:14 1995 Mike Stump +Tue Feb 17 14:07:52 1998 Mark Mitchell - * decl2.c (finish_file): Fix bug in Jan 31st change. + * parse.y (initdcl0_innards): New grammar symbol. + (nomods_initdecls, nomods_initdcl0): Change type from itype to + none, since the resulting value is never used. + (parse_decl): New function. + (datadef): Remove redundant actions. + (initdcl0, notype_initdcl0, nomods_initdcl0): Use initdcl0_innards. + * parse.c: Regenerated. + +Tue Feb 17 11:54:16 1998 Jason Merrill -Tue Jan 31 16:59:15 1995 Gerald Baumgartner (gb@lorenzo.cs.purdue.edu) + * parse.y (simple_stmt): Use getdecls() to check for decl. - * sig.c (build_signature_pointer_or_reference_type): Don't set - IS_AGGR_TYPE for signature pointers/reference so expand_default_init - doesn't expect to find a copy constructor. - * call.c (build_method_call): Treat signature pointers/reference - as if IS_AGGR_TYPE were set. - -Tue Jan 31 13:28:56 1995 Mike Stump - - * gc.c (get_typeid): Pawn off error messages to build_t_desc. - (build_t_desc): Inform the user here if they try and build - with -frtti and don't include . - - * decl2.c (finish_prevtable_vardecl): Support rescanning. - (finish_file): Move finish_prevtable_vardecl up to before the global - initializers are done as tdecls are initialized in the global - initializer. Also Pick up any new tdecls or vtables needed by - synthesized methods. - - * class.c (finish_struct): Simplify. We have to do rtti scanning at - end, so we might as well do all of it there. - -Tue Jan 31 05:35:02 1995 Jason Merrill - - * call.c (build_method_call): Fix -fthis-is-variable for 32-bit - targets, too. - -Tue Jan 31 00:11:04 1995 Mike Stump - - * decl2.c (finish_prevtable_vardecl): New routine, mostly split from - finish_vtable_vardecl. It has the first half functionality from - that routine. - * decl2.c (finish_vtable_vardecl): Update to not include stuff not - in finish_prevtable_vardecl. - * decl2.c (finish_file): Call finish_prevtable_vardecl. - * gc.c (build_generic_desc): Allow it to be called when not at the - global binding layer, but behave as if we were. - (build_t_desc): Rearrange a bit so that it really works and is - easier to follow. - * class.c (finish_struct): Don't decide on tdecls here, as we have - to wait until the end of the file in general to decide whether or - not they come out. - -Mon Jan 30 01:00:40 1995 Jason Merrill - - * init.c (build_delete): Check access to operator delete before - calling the destructor. - * method.c (build_opfncall, DELETE_EXPR): build_method is allowed to - return error_mark_node. - * call.c (build_method_call): Use the one-argument op delete even if - it's an error. +Sat Feb 14 11:50:51 1998 Manfred Hollstein - * init.c (build_new): Fix -fthis-is-variable support. - * call.c (build_method_call): Ditto. + * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New + macros. + (c++.install-common): Install c++filt properly as native or as cross + variant. + (c++.uninstall): Add c++filt. - * call.c (convert_harshness): Make conversion from a pointer to bool - worse than conversion to another pointer. +Fri Feb 13 14:55:37 1998 Jason Merrill -Sat Jan 28 16:46:10 1995 Jason Merrill + * call.c (standard_conversion): Fix multi-level ptr conversions. - * init.c (build_new): Check new return value if -fcheck-new. +Fri Feb 13 14:06:22 1998 Mike Stump - * lex.c (check_newline): Clear end_of_file when we're done, too. + * init.c (build_new): Propagate error_mark_node up. -Sat Jan 28 10:38:39 1995 Mike Stump +Fri Feb 13 13:24:32 1998 Jason Merrill - * decl2.c (finish_vtable_vardecl): Make rtti TD tables follow - vtables whereever they go. + * parse.y (simple_stmt): If the condition isn't a declaration, + start the controlled block after the test. - * gc.c (build_t_desc): Remove old way of setting it up, as it wasn't - right. +Fri Feb 13 02:26:10 1998 Andreas Schwab -Sat Jan 28 09:10:44 1995 Mike Stump + * 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 + builtins. - * decl2.c (finish_vtable_vardecl): Now set the - interface/implementation of vtables on the first virtual function, - if one exists, otherwise we use the old method. This is a major win - in terms of cutting down the size of objects and executables in - terms of text space and data space. Now most of the savings that - #pragma interface/implementation gives is automatic in a fair number - of cases. +Fri Feb 13 01:36:42 1998 Jason Merrill -Sat Jan 28 04:57:33 1995 Jason Merrill + * call.c (standard_conversion): A BASE_CONV replaces an RVALUE_CONV. - * decl.c (grokdeclarator): Discard the template parameters in a - template constructor declaration so that the function is always - named constructor_name (ctype). +Fri Feb 13 00:21:59 1998 Jason Merrill - * lex.c (check_newline): Use ungetc to put back the character before - calling HANDLE_PRAGMA. + * cp-tree.h: Add access_protected_virtual_node. + * class.c (init_class_processing): Initialize it. + * decl.c (xref_basetypes): Use it. + * parse.y (base_class_access_list): Likewise. -Fri Jan 27 17:23:47 1995 Mike Stump + * Make-lang.in (DEMANGLER_PROG): Add $(exeext). + (c++.install-common): Install c++filt. - * decl2.c (check_classfn): If the cname is T and fn_name is T, - make sure we still match them. +Thu Feb 12 12:46:51 1998 Benjamin Kosnik -Fri Jan 27 16:32:10 1995 Jason Merrill + * decl.c (shadow_tag): Give error for typedef-ing built-in types. - * parse.y: Add END_OF_LINE token. +Wed Feb 11 23:28:05 1998 Mark Mitchell - * lex.c (check_newline): Set linemode when we see a # directive, and - unset it when we're done. Turn all 'return's into 'goto skipline'. - Fix all uses of '\n', since we won't see it anymore. Put back the - character we read before checking for a sysv or target pragma. - (real_yylex): If we see an EOF in linemode, return END_OF_LINE. - (handle_sysv_pragma): Don't look at the input stream; quit when we - see an END_OF_LINE token. + * call.c (reference_binding): Use comptypes when comparing + TYPE_MAIN_VARIANTS to handle non-canonical array/index types. - * input.c (getch): Return EOF if we're in line mode and at the end - of a line. - (put_back): Don't put back an EOF. +Wed Feb 11 16:42:04 1998 Mark Mitchell -Thu Jan 26 19:26:34 1995 Mike Stump + * tree.c (is_overloaded_fn): Use really_overloaded_fn. + (really_overloaded_fn): Move check here from is_overloaded_fn. + (get_first_fn): Use really_overloaded_fn and is_overloaded_fn. - * except.c (expand_throw): Do the newing of the exception object - before we load the type descriptor or the address so that we don't - wipe any of the values out. +Wed Feb 11 15:54:18 1998 Mark Mitchell -Thu Jan 26 19:20:00 1995 Mike Stump + * typeck.c (build_ptrmemfunc): Type-check pointer-to-member + conversions. - * except.c (init_exception_processing): Don't use r12 on the rs6000. +Mon Feb 9 22:23:31 1998 Mark Mitchell + + * cp-tree.h (push_template_decl): Return the decl passed in, or an + equivalent duplicate. + * decl.c (pushtag): Use the return value from push_template_decl. + (duplicate_decls): When duplicating a template declaration, merge + the DECL_TEMPLATE_RESULTs as well. + (make_implicit_typename): Don't try to dive into typename types to + find a context for making a new implicit typename. + (start_decl): Use the return value from push_template_decl. + (grokdeclarator): Complain about declarations list `const operator + int'. Since we don't correctly handle in-class initializations of + non-static data members, complain about this (now illegal) + practice. Issue an error for initializations of non-const statics + since that is illegal as well, and since we don't handle that case + correctly either. + (start_function): Use the return value from push_template_decl. + (start_method): Likewise. + * decl2.c (grokfield): Likewise. Since the change to + grokdeclarator ensures that all initialized fields are in fact + static, remove a redundant test for TREE_PUBLIC. + * parse.y (initlist): Disable labeled initializers since they do + not work as per the documentation, and since they do not use the + same syntax as the C front end. + * pt.c (push_template_decl): Return the decl passed in, or an + equivalent duplicate. + (lookup_template_class): When searching in a nested context, + use the right arguments. + (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 -Tue Jan 24 16:36:31 1995 Jason Merrill + * pt.c (convert_nontype_argument): Fix typo. + (check_explicit_specialization): Allow old-style specialization + of class template members. - * decl.c (grokparms): Don't try to build up a reference at this point. +Tue Feb 10 20:36:52 1998 Jason Merrill + Manfred Hollstein - * typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR - will suffice to convert from integer_zero_node. + * decl.c (grokdeclarator): Use DECL_USE_TEMPLATE instead + when deciding to override DECL_ASSEMBLER_NAME. -Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu) +Tue Feb 10 15:30:55 EST 1998 Andrew MacLeod - * class.c (instantiate_type): Change error message text. - * typeck2.c (store_init_value): Likewise. + * 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 + process_overload_item. + (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_mangled_name. + (ALLOCATE_TYPEVEC, DEALLOCATE_TYPEVEC): Remove macro and expand inline. + (start_squangling): New function to initialize squangling structs. + (end_squangling): New function to destroy squangling structs. + (nrepeats): Rename variable to Nrepeats. + (issue_nrepeats): New function for issuing 'n' type repeats. + (check_ktype): New function to check for type K name compression. + (build_overload_nested_name): Add a check for K name compression. + (build_qualified_name): Add a check for K name compression and don't + 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 + squangling -Mon Jan 23 21:57:14 1995 Mike Stump +Sun Feb 8 23:47:38 1998 scott snyder - * pt.c (tsubst): When we copy a node, don't forget to copy - TREE_CHAIN, we use it later. + * method.c (make_thunk): Avoid name buffer overflow. -Mon Jan 23 03:33:47 1995 Jason Merrill +Sat Feb 7 16:48:54 1998 Jason Merrill - * typeck.c (convert_for_assignment): Initialize variable before use. + * pt.c (instantiate_decl): Call cp_finish_decl for vars even if we + don't define them yet. -Fri Jan 20 01:17:59 1995 Jason Merrill + * parse.y (nomods_initdcl0): Add constructor_declarator case. - * g++.c (main): Link with both libstdc++ and libg++ if called as - something ending with "g++", otherwise only libstdc++. Move -lm to - the end of the line. +Fri Feb 6 21:32:25 1998 Richard Kenner -Thu Jan 19 15:43:11 1995 Jason Merrill + * config-lang.in (diff_excludes): Use basename only. - * call.c (build_method_call): Don't mess with 'this' before calling - compute_conversion_costs. +Thu Feb 5 19:10:40 1998 Jason Merrill -Wed Jan 18 15:40:55 1995 Jason Merrill + * tinfo2.cc: Add tinfo for signed char. - * search.c (get_matching_virtual): Give line number for previous - declaration. +Thu Feb 5 14:38:23 1998 Mike Stump - * call.c (convert_harshness): Handle conversions to references - better. + * search.c (compute_access): Handle protected constructors in derived + classes as accessible. - * cvt.c (build_up_reference): OK, handle {MIN,MAX}_EXPR *properly*. +Wed Feb 4 01:26:49 1998 Jason Merrill -Wed Jan 18 15:21:38 1995 Mike Stump + * expr.c (cplus_expand_expr, PCC_STATIC_STRUCT_RETURN code): + Call convert_from_reference sooner. - * class.c (instantiate_type): Use DECL_CHAIN to walk lists instead, - as the TREE_CHAIN for methods will take us to the next differently - named function, DECL_CHAIN won't. +Tue Feb 3 23:50:52 1998 Mark Mitchell -Wed Jan 18 14:26:59 1995 Jason Merrill + * 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. - * tree.c (lvalue_p): Handle {MIN,MAX}_EXPR. + * decl2.c (finish_file): Make sure that static inlines with + definitions are not marked DECL_EXTERNAL before returning. - * decl2.c (lang_decode_option): -Wall implies -Wparentheses. - warn_parentheses defaults to 0. +Tue Feb 3 22:43:42 1998 Jason Merrill - * decl.c (grokparms): Put back call to require_instantiated_type. + * decl.c: Lose arg_looking_for_template. + (lookup_name_real): Likewise. + * parse.y: Lose processing_template_arg, template_arg1 + (primary): Likewise. + * spew.c (yylex): Set lastiddecl for PTYPENAMEs, too. -Tue Jan 17 19:56:15 1995 Mike Stump +Tue Feb 3 22:04:01 1998 Kriang Lerdsuwanakij - * except.c (exception_section): Use the data section on the rs6000. - Change calling convention for named_section. + * 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 + template arguments here. -Wed Jan 17 18:20:57 1994 Fergus Henderson + * parse.y (template_parm): Use template_arg instead of PTYPENAME + for default template 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 + TEMPLATE_TEMPLATE_PARM and RECORD_TYPE. - * cp-tree.h : Make if (x=0) warn with wall - * parse.y : Make if (x=0) warn with wall +Tue Jan 6 01:42:44 1998 Mumit Khan -Tue Jan 17 14:12:00 1995 Jason Merrill + * lex.c (file_name_nondirectory): Also check for '/'. - * decl.c (BOOL_TYPE_SIZE): BITS_PER_WORD if SLOW_BYTE_ACCESS, - BITS_PER_UNIT otherwise. +Mon Feb 2 11:24:22 1998 Mark Mitchell - * search.c (get_matching_virtual): Don't check the binfo if the - types are the same. + * parse.y (primary): Deal with statement-expressions in + templates. + * pt.c (tsubst_copy): Handle BIND_EXPR. + * tree.c (mapcar): Likewise. - * cvt.c (cp_convert): Just call truthvalue_conversion to convert to - bool. + * call.c (add_template_candidate_real): Pass extra parameter to + 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. + (revert_static_member_fn): Declare. + * decl.c (revert_static_member_fn): Remove declaration. Change + linkage from internal to external. + (cp_finish_decl): Deal with virtual functions in classes local to + template functions. + * decl2.c (finish_file): Don't forget to emit increment/decrement + expressions in initializers for file-scope variables. + * parse.y (typename_sub2): If the typename doesn't names a + template, rather than a type, issue an error message. + * pt.c (check_explicit_specialization): Handle specializations of + static member functions. + (coerce_template_parms): Handle offset references to lists of + member functions. + * search.c (note_debug_info_needed): Don't crash when handed a + type which is being defined. + * typeck.c (complete_type): Don't crash when handed NULL_TREE; + that can happen with some illegal code. + +Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi + + * call.c (user_harshness): Initialize `code' to 0. + (build_method_call): Initialize `candidates', `cp' and `len' to 0. + (null_ptr_cst_p): Add parentheses around && within ||. + (standard_conversion): Likewise. + (z_candidate): Likewise. + (build_user_type_conversion_1): Initialize `args' to NULL_TREE. + (build_object_call): Likewise for `mem_args'. + (build_new_op): Likewise for `mem_arglist'. Add `return' from + default case in enumeration switch. + + * class.c (build_vtable_entry): Add explicit braces to avoid + ambiguous `else'. + (build_class_init_list): Likewise. + (finish_struct_1): Initialize `width' to 0. + (instantiate_type): Initialize `name' to NULL_TREE. Add + explicit braces to avoid ambiguous `else'. + + * cvt.c (convert_to_aggr): Add explicit braces to avoid ambiguous + `else'. + + * decl.c (grok_reference_init): Eliminate unused parameter, all + callers changed. + (record_builtin_type): Initialize `tdecl' to NULL_TREE. + (init_decl_processing): Initialize `vb_off_identifier' to NULL_TREE. + (cp_finish_decl): Initialize `ttype' to NULL_TREE. + (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'. + (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 + used as truth value. + + * decl2.c (coerce_delete_type): Hide definition of `e3'. + + * error.c: Include . + (dump_expr): Change the type of `i' to size_t. Remove unused + label `error'. + + * except.c (init_exception_processing): Remove unused variable `d'. + (expand_throw): Likewise for `label'. + + * friend.c (add_friends): Add explicit braces to avoid ambiguous + `else'. + + * init.c (sort_member_init): Initialize `last_field' to NULL_TREE. + (sort_base_init): Likewise for `binfo'. + (expand_member_init): Likewise for `rval'. + (build_member_call): Add parentheses around assignment used as + truth value. + (build_offset_ref): Add explicit braces to avoid ambiguous `else'. + (build_new): Initialize `nelts' to NULL_TREE. Initialize + `old_immediate_size_expand' to 0. + (build_new_1): Initialize `nelts' and `alloc_node' to NULL_TREE. + (build_vec_delete_1): Remove unused variable `block'. + (expand_vec_init): Initialize `itype' to NULL_TREE. + + * lex.c: Include if we don't have . Protect + declaration of `index' and `rindex' with autoconf macros. + (reinit_parse_for_expr): Remove unused variables + `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. + + * method.c: Include if we don't have . + Protect declaration of `index' with autoconf macro. + + * parse.y (primary): Add explicit braces to avoid ambiguous `else'. + Initialize `type' to NULL_TREE. + (structsp): Remove unused variable `id'. + + * pt.c (coerce_template_parms): Add explicit braces to avoid + ambiguous `else'. + (lookup_template_class): Initialize `template' to NULL_TREE. + (instantiate_class_template): Remove unused variable `name' and `e'. + (tsubst): Likewise for `i'. Initialize `last' to NULL_TREE. + (do_poplevel): Initialize `saved_warn_unused' to 0. + (type_unification): Remove unused varable `parm'. + (unify): Likewise for `j'. + + * 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. + (get_base_distance): Likewise. + (lookup_field): Initialize `rval_binfo_h', `type', `basetype_path' + and `new_v' to NULL_TREE. + (lookup_fnfields): Likewise for `rval_binfo_h'. + (breadth_first_search): Add parentheses around assignment used as + truth value. + (get_template_base): Initialize `type' to NULL_TREE. + + * sig.c (append_signature_fields): Initialize `last_mfptr' to + NULL_TREE. + (build_signature_table_constructor): Likewise for + `last_rhs_field', `pfn' and `vt_off'. + (build_sigtable): Likewise for `init'. + + * tree.c (break_out_calls): Initialize `t2' to NULL_TREE. + (propagate_binfo_offsets): Likewise for `delta'. + (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. + (build_x_function_call): Initialize `ctypeptr' to NULL_TREE. + (build_function_call_real): Add explicit braces to avoid ambiguous + `else'. + (convert_arguments): Initialize `called_thing' to 0. + (convert_for_initialization): Initialize `savew' and `savee' to 0. + + * typeck2.c (incomplete_type_error): Initialize `errmsg' to 0. + (digest_init): Initialize `old_tail_contents' to NULL_TREE. + (build_x_arrow): Likewise for `last_rval'. + + * xref.c (GNU_xref_decl): Initialize `cls' to 0. + +Sun Feb 1 12:45:34 1998 J"orn Rennecke + + * decl.c (init_decl_processing): Use set_sizetype. + * decl2.c (sizetype): Don't declare. + * typeck.c (c_sizeof): Convert result of *_DIV_EXPR to sizetype. + (c_sizeof_nowarn, build_binary_op_nodefault): Likewise. + (build_component_addr, unary_complex_lvalue): Likewise. + * rtti.c (expand_class_desc): Likewise. + * class.c (get_vfield_offset): Likewise. + +Thu Jan 29 10:39:30 1998 Mark Mitchell + + * pt.c (convert_nontype_argument): Move check for is_overloaded_fn + early to avoid bogus error. Handle overloaded function + names provided as template arguments correctly. + (coerce_template_parms): Don't mishandle overloaded functions when + dealing with template template parameters. + (lookup_template_class): Issue an error message, rather than + crashing, when the TYPE_DECL provided is not a template type. + +Wed Jan 28 23:14:44 1998 Jason Merrill + + * class.c (instantiate_type): Don't just return a known type if + it's wrong. + +Wed Jan 28 11:04:07 1998 Mark Mitchell + + * 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. -Mon Jan 16 13:28:48 1995 Jason Merrill + * parse.y (structsp): Print an error message, rather than crashing, + when a class-head does not name a class. - * various: Use boolean_type_node, boolean_true_node, - boolean_false_node. + * 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. + * typeck.c (c_alignof): Likewise. + * decl2.c (build_expr_from_tree): Handle ALIGNOF_EXPR. + * error.c (dump_expr): Likewise. + * pt.c (tsubst_copy): Likewise. + * tree.c (cp_tree_equal): Likewise. + * 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 + unconditionally, since it will do nothing if there is no + current_local_enum. Use the new calling sequence. + * pt.c (tsubst_enum): Use the new calling sequence for + grok_enum_decls. + + * 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 + + * pt.c (convert_nontype_argument): Use decl_constant_value. + +Tue Jan 27 16:42:21 1998 Mark Mitchell + + * call.c (add_template_candidate_real): New function. + (add_template_candidate): Use it. + (add_template_conv_candidate): Likewise. + (joust): Pass extra argument to more_specialized. + * class.c (instantiate_type): Handle a single FUNCTION_DECL. + (is_local_class): Remove. + (finish_struct): Check TI_PENDING_SPECIALIZATION_FLAG. + * cp-tree.h (is_local_class): Remove. + (perform_array_to_pointer_conversion): Likewise. + (finish_member_template_decl): Add. + (check_explicit_specialization): Return a tree, not an int. + (more_specialized): Take additional argument. + (get_bindings): Likewise. + (TI_PENDING_SPECIALIZATION_FLAG): New macro. + * cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes. + (perform_array_to_pointer_conversion): Remove. + * decl.c (saved_scope): Add processing_specialization, + processing_explicit_instantiation fields. + (maybe_push_to_top_level): Save them. + (pop_from_top_level): Restore them. + (grokfndecl): Use new return value from + check_explicit_specialization. + (start_decl): Don't check flag_guiding_decls before pushing + decls. + (cp_finish_decl): Remove previous (bogus) change. + (grok_declarator): Use decl_function_context rather than + is_local_class. + * decl2.c (finish_file): Pass extra argument to get_bindings. + (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. + * method.c (build_overload_identifier): Mangle local classes in + template functions correctly. + * parse.y (finish_member_template_decl): Move to pt.c. + * pt.c (finish_member_template_decl): Moved here from parse.y. + (print_candidates): New function. + (determine_specialization): Change interface. Properly look for + most specialized versions of template candidates. + (check_explicit_specialization): Fully process explicit + instantiations. + (push_template_decl): Avoid looking at CLASSTYPE fields in + FUNCTION_DECLS. + (determine_overloaded_function): Remove. + (convert_nontype_argument): Change name from + convert_nontype_parameter. Use determine_overloaded_function + instead of instantiate_type. + (mangle_class_name_for_template): Handle type contexts as well as + function contexts. + (classtype_mangled_name): Likewise. + (lookup_template_class): Likewise. + (tsubst): Likewise. + (more_specialized): Take explict template arguments as a + parameter. + (most_specialized): Likewise. + (get_bindings): Likewise. Check that return types match before + proclaiming a function a match. + (do_decl_instantiation): Remove code searching for function to + instantiate; that is now done in check_explicit_specialization. + (add_maybe_template): Pass extra argument to get_bindings. + * tree.c (really_overloaded_fn): Use is_overloaded_fn to simplify + implementation. + * typeck.c (build_component_ref): Check for invalid arguments. + +Tue Jan 27 01:44:02 1998 Jason Merrill + + * 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 + don't use any template parms. + +Sun Jan 25 03:30:00 1998 Jason Merrill + + * decl.c (cp_finish_decl): When bailing on a comdat variable, also + unset DECL_NOT_REALLY_EXTERN. + + * parse.y (typename_sub*): Fix std::. + +Sat Jan 24 12:13:54 1998 Jason Merrill + + * 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 + + * lex.c (DIR_SEPARATOR): Define to be '/' if not already defined. + (file_name_nondirectory): Use. + +Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij + + * 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 + 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 + type created from template template parameters. + * parse.y (bad_parm): Likewise + + * class.c (finish_struct): Handle TEMPLATE_TEMPLATE_PARM. + (push_nested_class): Likewise. + * cp-tree.def (TEMPLATE_TEMPLATE_PARM): New tree code. + * cp-tree.h (DECL_TEMPLATE_TEMPLATE_PARM_P): New macro. + (copy_template_template_parm): Declare. + * decl.c (arg_looking_for_template): New variable. + (lookup_name_real): Handle TEMPLATE_TEMPLATE_PARM. + Try to return TEMPLATE_DECL or TEMPLATE_TEMPLATE_PARM + node if arg_looking_for_template is nonzero. + (pushdecl): Handle TEMPLATE_TEMPLATE_PARM. + (grok_op_properties, xref_tag, xref_basetypes): Likewise. + (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_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): + 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): + Handle TEMPLATE_TEMPLATE_PARM. + * parse.y (maybe_identifier): New nonterminal. + (template_type_parm): Use it. + (template_template_parm, template_arg1): New nonterminal. + (template_parm): Add template_template_parm rules. + (template_arg): Set processing_template_arg. + (template_arg1): Rules moved from template_arg. + (primary, nonnested_type): Set arg_looking_for_template if we are + processing template arguments. + * pt.c (begin_member_template_processing): Handle TEMPLATE_DECL. + (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 + TEMPLATE_TEMPLATE_PARM. + (current_template_args): Handle TEMPLATE_DECL. + (tsubst, tsubst_copy, unify): Handle TEMPLATE_TEMPLATE_PARM. + * search.c (dfs_walk, dfs_record_inheritance): + Handle TEMPLATE_TEMPLATE_PARM. + * tree.c (copy_template_template_parm): New function. + (mapcar): Handle TEMPLATE_TEMPLATE_PARM. + * typeck.c (comptypes): Handle TEMPLATE_TEMPLATE_PARM. + +Mon Jan 19 22:40:03 1998 Mark Mitchell + + * decl.c (start_decl): Don't allow duplicate definitions of static + data members. + + * call.c (build_user_type_conversion_1): Handle user-defined + template conversion operators correctly. + + * 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. + Consider FUNCTION_DECLS to declare objects with top-level binding, + when calling make_decl_rtl. + (grokdeclarator): Give members of local classes internal linkage. + (start_function): Remove declaration of last_tree. + (finish_function): Set flag_keep_inline_functions around call to + rest_of_compilation if we are processing a member function in a + local class. + (start_method): Call push_template_decl for member functions of + local classes in template functions. + * decl2.c (import_export_decl): Don't give external linkage to + instantiations of templates with internal linkage. + * parse.y (last_tree): Remove declaration. + (template_type): Pass extra parameter to lookup_template_class. + (self_template_type): Likewise. + (structsp): Move call to reset_specialization into left_curly. + (left_curly): Call reset_specialization, and begin_tree. + * pt.c (saved_trees): New variable. + (mangle_class_name_for_template): Change prototype. Use + additional function context to name local classes in templates + 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. + (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. + (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. - * search.c (get_matching_virtual): Allow covariant returns that - don't require pointer adjustment. + * pt.c (register_specialization): Do not register specializations + that aren't ready to be registered yet. + (check_explicit_specialization): Handle explicit specialization of + constructors and destructors. + (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. + + * class.c (finish_struct_methods): Remove calls to + check_explicit_specialization from here. + (finish_struct): And insert them here. + * cp-tree.h (perform_qualification_conversions): New function. + (perform_array_to_pointer_conversion): Likewise. + (begin_explicit_instantiation): Likewise. + (end_explicit_instantiation): Likewise. + (determine_specialization): Renamed from + determine_explicit_specialization. + (comp_template_parms): New function. + (processing_explicit_instantiation): New variable. + * cvt.c (perform_qualification_conversions): New function. + (perform_array_to_pointer_conversion): Likewise. + * decl.c (duplicate_decls): Don't consider template functions + alike unless they have the same parameters. Refine handling of + instantiation/specialization mismatches. + (start_decl): Don't call pushdecl for template specializations, + since they don't affect overloading. + (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 + themselves specializations. Remove use of `2' as parameter to + grokfndecl since that value isn't used. + * lex.c (cons_up_default_function): Save and restore + processing_explicit_instantiation around calls to grokfield. + * parse.y (finish_member_template_decl): New function. + (component_decl_1): Use it. + (fn.def2): Likewise. + (template_arg_list_opt): New nonterminal. + (template_type): Use it. + (self_template_type): Likewise. + (template_id): Likewise. + (object_template_id): Likewise. + (notype_template_declarator): Likwise. + (begin_explicit_instantiation): Likewise. + (end_explicit_instantiation): Likewise. + (explicit_instantiation): Use them. + * pt.c (coerce_template_parms): Add parameters. + (processing_explicit_instantiation): New variable. + (convert_nontype_parameter): New function. + (determine_overloaded_function): Likewise. + (begin_explicit_instantiation): Likewise. + (end_explicit_instantiation): Likewise. + (retrieve_specialization): Likewise. + (register_specialization): Likewise. + (processing_explicit_specialization): Removed. + (determine_specialization): Handle specializations of member + functions of template class instantiations. + (check_explicit_specialization): Refine to conform to standard. + (comp_template_parms): New function. + (coerce_template_parms): Call convert_nontype_parameter. + (tsubst): Refine handling of member templates. Use + register_specialization. + (instantiate_template): Use retrieve_specialization. + (do_decl_instantiation): Likewise. + (instantiate_decl): Likewise. + (type_unification): Improve handling of explict template + 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 + than determine_explicit_specialization. + +Mon Jan 19 13:18:51 1998 Jason Merrill + + * cvt.c (build_up_reference): A TARGET_EXPR has side effects. + +Fri Jan 16 11:40:50 1998 Bruno Haible + + * error.c (dump_decl): For enum tags, output the tag, not its value. + +1998-01-13 Brendan Kehoe + + * decl.c (init_decl_processing): Only call init_rtti_processing + FLAG_RTTI is set. + +Mon Jan 12 01:35:18 1998 Jason Merrill + + * init.c (build_new_1): Split out from build_new. + (build_new): Just return a NEW_EXPR. + * expr.c (cplus_expand_expr): Handle NEW_EXPR. + + * decl2.c (get_temp_regvar): Tweak. + + * cp-tree.h (TREE_CALLS_NEW): Comment out. + * class.c (resolves_to_fixed_type_p): Remove use. + * method.c (build_opfncall): Likewise. + * call.c (build_new_op): Likewise. + +Wed Jan 7 23:47:13 1998 Jason Merrill + + * exception.cc (__eh_alloc, __eh_free): New fns. + (__cp_push_exception, __cp_pop_exception): Use them. + (__uncatch_exception): Call terminate here if no exception. + * except.c (build_terminate_handler): New fn. + (expand_start_catch_block): Use it. + (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 + methods. - * typeck.c (build_conditional_expr): Don't call default_conversion - on ifexp. +Mon Dec 22 11:36:27 1997 Kaveh R. Ghazi + + * call.c (add_builtin_candidate): Add default case in enumeration + switch. + (build_new_op): Likewise. + (convert_like): Likewise. + * cvt.c (build_expr_type_conversion): Likewise. + * tree.c (real_lvalue_p): Likewise. + (lvalue_p): Likewise. + (cp_tree_equal): Likewise. + * typeck.c (comptypes): Likewise. + (build_component_ref): Likewise. + (build_function_call_real): Likewise. + (build_binary_op_nodefault): Likewise. + (build_unary_op): Likewise. + (build_modify_expr): Likewise. + * typeck2.c (initializer_constant_valid_p): Likewise. - * cvt.c (build_up_reference): Handle MIN_EXPR and MAX_EXPR. +Sun Dec 21 15:59:00 1997 Nick Clifton - * decl.c (grokdeclarator): Upgrade warning about &const to pedwarn. + * decl2.c (lang_decode_option): Add support for -Wunknown-pragmas. -Sun Jan 15 22:17:32 1995 dcb@lovat.fmrco.COM (David Binderman) +Thu Dec 18 14:51:50 1997 Mark Mitchell - * pt.c (do_function_instantiation): Free targs once we're done. + * pt.c (coerce_template_parms): Make sure to digest_init if + possible. -Sun Jan 15 22:17:32 1995 Jason Merrill + * decl.c (duplicate_decls): Make the newdecl virtual if the + olddecl was, just as is done with other attributes of olddecl. - * decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD. - (init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE - for bool. +Thu Dec 18 14:43:19 1997 Jason Merrill -Sat Jan 14 05:33:55 1995 Jason Merrill + * typeck.c (unary_complex_lvalue): Ignore op0 when taking the + address of an OFFSET_REF. - * decl2.c (finish_file): We need to mess up if there are any - variables in the list, not just if there is one with a constructor. + * cp-tree.def: Add AGGR_INIT_EXPR. + * error.c, tree.c, typeck.c: Replace uses of NEW_EXPR with + AGGR_INIT_EXPR where appropriate. + * expr.c (cplus_expand_expr): Likewise. Simplify. -Fri Jan 13 14:42:55 1995 Jason Merrill + * decl2.c (finish_file): Remove call to register_exception_table. - * decl.c (duplicate_decls): Propagate DECL_STATIC_{CON,DE}STRUCTOR. - (finish_function): Handle DECL_STATIC_{CON,DE}STRUCTOR. - (finish_function): Trust rest_of_compilation. +Wed Dec 17 17:08:52 1997 Benjamin Kosnik - * decl2.c (finish_file): Also call functions designated as static - constructors/destructors. + * pt.c (instantiate_class_template): Don't do injection when + processing_template_decl is true, as pollutes current_binding_level + for base classes. - * decl.c (grokdeclarator): Allow access decls of operator functions. - (grokparms): Only do convert_for_initialization if the initializer - has a type. - (duplicate_decls): Put back push_obstacks_nochange call. +Wed Dec 17 21:17:39 1997 Peter Schmid - * lex.c (real_yylex): Downgrade complaint about the escape sequence - being too large from pedwarn to warning. + * pt.c (maybe_fold_nontype_arg): Add prototype. - * decl.c (grokdeclarator): Don't complain about long long in system - headers. +Tue Dec 16 10:31:20 1997 Jason Merrill - * lex.c (real_yylex): Handle digraphs. + * tree.c (mapcar): Handle TRY_CATCH_EXPR et al. + * error.c (dump_expr): Likewise. -Thu Jan 12 12:17:24 1995 Jason Merrill +Mon Dec 15 12:22:04 1997 Jason Merrill - * decl.c (init_decl_processing): -f{no-,}strict-prototype only - affects C linkage declarations now. + * typeck.c (build_function_call_real): Remove "inline called before + definition" pedwarn. - * typeck.c (comp_target_types): Grok simple contravariant conversions. - (common_type): t1 and t2 are interchangeable. + * pt.c (coerce_template_parms): Use maybe_fold_nontype_arg. - * various: Test return value of comp_target_types differently in - different places; it now returns -1 for a contravariant conversion - (which is fine in symmetric cases). +Sun Dec 14 22:34:20 1997 Jason Merrill - (common_type): Prefer long double to double even when - they have the same precision. + * cvt.c (cp_convert_to_pointer): Fix base conversion of pm's. - * decl.c (grokparms): Call convert_for_initialization to check - default arguments. + * pt.c (type_unification_real): Change __null to type void* with + a warning. - * init.c (build_new): void_type_node has a size (of 0). +Sun Dec 14 20:38:35 1997 Mark Mitchell - * decl.c (decls_match): Also check for agreement of TREE_READONLY - and TREE_THIS_VOLATILE. - (push_class_level_binding): Properly handle shadowing of - nested tags by fields. + * call.c (implicit_conversion): Don't call + build_user_type_conversion_1 with a NULL expr, since it will + crash. - * search.c (dfs_pushdecls): Ditto. + * pt.c (unify): Don't try to unify array bounds if either array is + unbounded. - * decl2.c (finish_file): Don't second-guess self-initialization. +Fri Dec 12 16:09:14 1997 Jason Merrill - * cvt.c (convert_to_reference): Work with expr directly, rather than - a copy. + * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at): + Replace extern decls with casts. - * decl.c (push_overloaded_decl): Only shadow artificial TYPE_DECLs. + * decl.c (expand_start_early_try_stmts): Don't mess with a sequence. + Update last_parm_cleanup_insn. + (store_after_parms): Remove. + * cp-tree.h: Adjust. - * init.c (add_friend): Downgrade duplicate friend message from - pedwarn to warning. +Thu Dec 11 22:18:37 1997 Jason Merrill - * decl.c (duplicate_decls): Push obstacks before calling common_type. + * 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. + (import_export_decl): Likewise. + * pt.c (mark_decl_instantiated): Likewise. -Thu Jan 12 17:15:21 1995 Michael Ben-Gershon + * decl2.c (finish_file): Lose handling of templates in pending_statics. - * except.c (push_eh_entry): set LABEL_PRESERVE_P flag for - exception table labels. - (expand_start_all_catch): Ditto. - (expand_leftover_cleanups): Ditto. - (expand_end_catch_block): Ditto. - * except.c (make_first_label): new function. - (expand_start_all_catch): add a call to make_first_label() before - using a label as a jump destination. - (expand_end_all_catch): Ditto. - (expand_leftover_cleanups): Ditto. - (expand_end_catch_block): Ditto. - (expand_builtin_throw): Ditto. - (expand_throw): Ditto. - * except.c: Add ARM processor support for exception handling. +Thu Dec 11 21:12:09 1997 Jason Merrill -Thu Jan 12 12:17:24 1995 Jason Merrill + * decl2.c (finish_file): Lose call to expand_builtin_throw. + * except.c (expand_builtin_throw): Remove. + * cp-tree.h: Remove ptr_ptr_type_node. + * decl.c: Likewise. - (complete_array_type): Copy code from C frontend. +Thu Dec 11 20:43:33 1997 Teemu Torma + + * 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. - * lex.c (real_yylex): Don't multiply the length of a wide string - literal by WCHAR_BYTES. + From Scott Snyder : + * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of + saved_pc. + (init_exception_processing): Removed saved_pc initialization. - * decl.c (pushdecl): Check for redeclaration of wchar_t here. - (duplicate_decls): Instead of here. - (define_label): Complain about a label named wchar_t. - (grokdeclarator): Complain about declarations of - operator-function-ids as non-functions. +Wed Dec 10 11:04:45 1997 Jason Merrill - * typeck.c (unary_complex_lvalue): Also wrap prefix -- and ++ in - COMPOUND_EXPRs. - (build_unary_op): Wrap unary plus in a NON_LVALUE_EXPR. + * pt.c (instantiate_decl): Defer all templates but inline functions. - * lex.c (real_yylex): Don't skip whitespace when reading the next - character after ->. +Mon Dec 8 23:17:13 1997 Jason Merrill -Wed Jan 11 16:32:49 1995 Mike Stump + * init.c (expand_vec_init): Don't fold a list of parameters. - * except.c: Allow cc1plus to be built with native compiler on rs6000. - (expand_start_all_catch): Add assemble_external calls for various - routines we call. - (expand_leftover_cleanups): Ditto. - (expand_start_catch_block): Ditto. - (do_unwind): Ditto. - (expand_builtin_throw): Ditto. + * decl.c (copy_args_p): Handle copy elision for types with virtual + bases. + * call.c (build_over_call): Likewise. -Wed Jan 11 01:05:42 1995 Jason Merrill +Sun Dec 7 22:38:12 1997 Mark Mitchell - * decl.c (pushtag): Only look for a previous decl in the current - binding level. Use explicit global scope in DECL_NESTED_TYPENAME. + * pt.c (lookup_template_function): Copy the template arguments, + not just the list containing them, to the permanent obstack. - * gxx.gperf: Add __signature__ and __sigof__ keywords. +Sun Dec 7 15:53:06 1997 Jason Merrill - * decl2.c (lang_decode_option): -ansi does not set flag_no_asm. It - does set flag_no_gnu_keywords and flag_operator_names. + * except.c (expand_start_catch_block): suspend_momentary for the + terminate handler. - * lex.c (init_lex): 'overload' is not a keyword unless -traditional. - Unset extension keywords if -fno-gnu-keywords. - Allow operator names ('bitand') if -foperator-names. - Never unset 'asm'; -fno-asm only affects 'typeof'. + * error.c (dump_decl): Handle LOOKUP_EXPR. - * decl.c (lookup_name_real): The got_object special lookup only - applies to types. +Sun Dec 7 15:45:07 1997 Mark Mitchell -Tue Jan 10 18:07:51 1995 Jason Merrill + * rtti.c (build_dynamic_cast): Copy the cast-to type to the + permanent obstack if we are processing a template decl. + * typeck.c (build_static_cast): Likewise. + (build_const_cast): Likewise. + (build_reinterpret_cast): Likewise. - * spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set. + * pt.c (coerce_template_parms): Coerce some expressions, even + when processing_template_decl. - * parse.y (primary): Unset got_object after all rules that use the - 'object' nonterminal. - (object): Set got_object. +Sun Dec 7 01:46:33 1997 Bruno Haible - * lex.h: Declare got_object. + * typeck.c (build_binary_op_nodefault, pointer_diff): Symmetric + handling of pointer difference expressions. - * decl.c (lookup_name_real): Also lookup names in the context of an - object specified. + * typeck.c (comp_target_types): Comparison of function/method types + is independent of nptrs. -Tue Jan 10 14:30:30 1995 Mike Stump +Sun Dec 7 01:40:27 1997 Mark Mitchell - * typeck.c (get_member_function_from_ptrfunc): Use ptrdiff_type_node - for things that have to be added to pointers, not size_type. Cures - problems with pointer to members on Alphas. - (build_binary_op_nodefault): Ditto. - (get_delta_difference_: Ditto. - (build_ptrmemfunc): Ditto. + * pt.c (tsubst): Avoid creating pointer to reference and + reference to reference types. -Tue Jan 10 01:49:25 1995 Jason Merrill +Sat Dec 6 01:29:37 1997 Jason Merrill - * decl.c (pushtag): Stick the new decl in TYPE_NAME before pushing - it. + * parse.y (do_id): New nonterminal. + (template_id): Use it. - * typeck.c (build_component_ref): Don't build up a COMPONENT_REF - when dealing with overloaded member functions; just act like - build_offset_ref. - (commonparms): Remove misleading comment. +Fri Dec 5 01:17:34 1997 Jason Merrill - * decl.c (duplicate_decls): Complain about repeated default - arguments here. - (redeclaration_error_message): Instead of here. - (pushdecl): Complain about missing default arguments here. - (grokparms): Instead of here. - (lookup_name_current_level): Also match on DECL_ASSEMBLER_NAME. - (grok_reference_init): Do not complain about missing initializer if - declared 'extern'. + * parse.y (template_id): do_identifier for PFUNCNAMEs, too. + * spew.c (yylex): Don't do_identifier here. + * decl2.c (build_expr_from_tree): Revert last change. - * search.c (lookup_field): Don't return a TYPE_DECL if there is a - function alternative and want_type is not set. + * decl2.c (build_expr_from_tree): Expand the name for a method call. + * parse.y (object_template_id): Don't try to take the DECL_NAME. -Mon Jan 9 18:16:23 1995 Jason Merrill +Wed Dec 3 20:02:39 1997 Jason Merrill - * decl.c (pushtag): Don't set TYPE_NAME to an identifier. Do push - the decl when the type has no TYPE_NAME. - (lookup_nested_type): Don't assume that type has TYPE_NAME set. - (lookup_name_real): Call lookup_field with want_type = - prefer_type. + * init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for + alloc_expr. + * call.c (build_op_delete_call): Adjust. - * search.c (lookup_field): Handle want_type properly in the presence - of fields with the same name. + * except.c (expand_end_catch_block): Lose rethrow region. + (expand_start_catch_block): Likewise. + (expand_end_catch_block): Don't expand_leftover_cleanups. - * decl.c (set_nested_typename): Set nested name for file-scope types - to include leading ::. - (pushdecl): Set the nested typename if the decl doesn't have one, - rather than if the type's canonical decl doesn't have one. +Wed Dec 3 13:24:04 1997 Benjamin Kosnik -Mon Jan 9 16:48:16 1995 Steve Chamberlain (sac@jonny.cygnus.com) + * pt.c (tsubst): Remove tree_cons call (places redundant info into + DECL_TEMPLATE_INSTANTIATION). - * typeck.c (pointer_int_sum): Use offset size when calculating - index expression. +Wed Dec 3 11:44:52 1997 Jason Merrill -Mon Jan 9 03:44:33 1995 Jason Merrill + * tree.c (is_overloaded_fn): Handle getting a fn template. + (really_overloaded_fn): Likewise. + * error.c (dump_decl): Handle TEMPLATE_ID_EXPRs better. + * pt.c (check_explicit_specialization): Tweak. + (determine_explicit_specialization): Tweak. - * typeck.c (convert_for_assignment): Complain about contravariance - violation here. - (comp_target_types): Instead of here. - (build_unary_op): resolve_offset_ref before checking for a valid - type. + * tree.c, cp-tree.h (get_target_expr): New fn. - * spew.c (yylex): Decrement looking_for_typename after we see a - _DEFN. +Wed Dec 3 08:47:27 1997 Paul Eggert - * decl.c (pushdecl): Don't install an artificial TYPE_DECL in - IDENTIFIER_LOCAL_VALUE if we already have a decl with that name. + * pt.c (check_explicit_specialization): Fix misspelling in + diagnostic: `preceeded'. + * typeck.c (get_delta_difference): Fix misspelling in diagnostic: + `conversiona'. - * typeck.c (convert_for_assignment): Converting pointers to bool - does not need a cast. +1997-12-02 Mark Mitchell -Sun Jan 8 18:16:45 1995 Jason Merrill + * pt.c (determine_explicit_specialization): Avoid an internal + error for bad specializations. - * class.c (instantiate_type): Initialize nsubsts parm. + * method.c (build_overload_value): Handle SCOPE_REF. - * pt.c (do_function_instantiation): Ditto. +Tue Dec 2 19:18:50 1997 Mike Stump -Sat Jan 7 14:37:05 1995 Jason Merrill + * class.c (prepare_fresh_vtable): Enable even more complex MI + vtable names. - * pt.c (tsubst): Use TREE_STATIC instead of DECL_INLINE && - DECL_SAVED_INSNS to determine whether or not we've seen a definition - of this function. - (instantiate_template): Ditto. +Tue Dec 2 01:37:19 1997 Jason Merrill - * call.c (convert_harshness): Allow const reference binding when - called from the overloading code, but not when called from - can_convert (since it isn't a conversion). - (convert_harshness): Put back some disabled code. + * exception.cc (__check_eh_spec): Optimize a bit. -Fri Jan 6 14:10:57 1995 Jason Merrill + * exception.cc (__cp_pop_exception): Lose handler arg. + * except.c (do_pop_exception): Likewise. + (push_eh_cleanup): Let the cleanup mechanism supply the handler. + (expand_end_catch_block): Likewise. - * call.c (convert_harshness): There is no implicit conversion from - void* to other pointer types (unless the parameter is (void*)0). - (convert_harshness): Non-lvalues do not convert to reference types. +Fri Nov 28 01:58:14 1997 Jason Merrill - * class.c (finish_struct_methods): Still set - TYPE_HAS_{INT,REAL}_CONVERSION. + * pt.c (check_explicit_specialization): Complain about using a + template-id for a non-specialization. - * call.c (can_convert): Don't use aggregate initialization. +Fri Nov 28 12:35:19 1997 Scott Christley - * cp-tree.h: Declare lookup_conversions. + * repo.c: Prototype rindex only if needed. + * xref.c: Likewise. -Thu Jan 5 21:08:00 1995 Mike Stump +Fri Nov 28 01:56:35 1997 Bruno Haible - * parse.y (simple_stmt): Fix duplicate case value error messages to - be more readable. + * error.c (dump_decl): Handle TEMPLATE_ID_EXPR. -Wed Jan 4 16:44:19 1995 Jason Merrill +Thu Nov 27 00:59:46 1997 Jason Merrill - * cvt.c (build_type_conversion): Total rewrite to use - convert_harshness instead of reproducing conversion logic here. Now - much shorter. + * typeck.c (build_const_cast): Handle references here instead of + handing off to convert_to_reference. - * call.c (convert_harshness): Support conversions to bool. - (can_convert): Checks whether a conversion is less harsh - than USER_CODE, for build_type_conversion. + * except.c: Lose Unexpected, SetTerminate, SetUnexpected, + TerminateFunctionCall. + (init_exception_processing): Likewise. Terminate et al are now + the fns, not ADDR_EXPRs. + (various): Lose redundant assemble_external calls. + (do_unwind): s/BuiltinReturnAddress/builtin_return_address_fndecl/. - * search.c (add_conversions): Function for passing to dfs_walk which - adds all the type conversion operators in the current type to a list. - (lookup_conversions): Calls dfs_walk with add_conversions and return - the list. - (dfs_walk): Don't require a qfn. + * cp-tree.h (struct lang_decl_flags): Add comdat. + (DECL_COMDAT): New macro. + * decl.c (duplicate_decls): Propagate it. + (cp_finish_decl): Handle it. + * decl2.c (import_export_decl): Just set DECL_COMDAT on VAR_DECLs. - * cp-tree.h: Lose CLASSTYPE_CONVERSIONS hackery. - (CLASSTYPE_FIRST_CONVERSION): Points to elt 1 of CLASSTYPE_METHOD_VEC. + * class.c: Remove static pending_hard_virtuals. + (add_virtual_function): Take pointers to pending_virtuals + and pending_hard_virtuals. + (finish_struct_1): Pass them. Declare pending_hard_virtuals. - * class.c (finish_struct_bits): Lose CLASSTYPE_CONVERSIONS hackery. - (grow_method): A separate function for building onto the growing - method vector. - (finish_struct_methods): Use it. Put all type conversion operators - right after the constructors. Perhaps we should sort the methods - alphabetically? +Wed Nov 26 20:28:49 1997 Jason Merrill -Mon Jan 2 14:42:58 1995 Jason Merrill + * 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 + instantiated template classes. + * pt.c (mark_class_instantiated): Revert last change. - * call.c (build_method_call): Lose another misleading shortcut. + * except.c (expand_throw): Call mark_used on the destructor. -Fri Dec 30 17:57:30 1994 Mike Stump +Wed Nov 26 15:13:48 1997 Jeffrey A Law (law@cygnus.com) - * gc.c (build_bltn_desc): Handle bool as a built-in type. + * lex.c (lang_init): Enable flag_exceptions by default if no + command line switch was specified. -Fri Dec 30 14:20:21 1994 Mike Stump +1997-11-26 Mark Mitchell - * tree.c (layout_vbasetypes): Ensure that we don't loose alignment - on the complete type because of small virtual bases. + * pt.c (unify): Handle `void' template parameters in + specializations. -Fri Dec 30 12:22:29 1994 Mike Stump +Wed Nov 26 01:11:24 1997 Jason Merrill - * decl.c (n_incomplete): Bump n_incomplete up to int to match C - front end. - (pushdecl): Also count decls pushed that are of a type being defined - as incomplete things. - * class.c (finish_struct): Move hack_incomplete_structures up to - just after we set it as not being defined, so that the decls we - build for RTTI don't count as incomplete. + * rtti.c (build_dynamic_cast): Handle template case here. + (build_dynamic_cast_1): Not here. -Thu Dec 29 18:20:57 1994 Mike Stump + * typeck2.c (digest_init): Make copies where appropriate. - * pt.c (tsubst): Fix problem with defining constructors in templated - classes with virtual bases. + * decl2.c (delete_sanity): resolve_offset_ref. -Wed Dec 28 08:31:00 1994 Mike Stump + * except.c: Call terminate without caching so many bits. - * parse.y (TYPEID): Strip top-level cv-qualifiers on typeid - expressions. - * gc.c (build_typeid): Ditto. + * except.c (expand_start_catch_block): Fix catching a reference + to pointer. -Thu Dec 22 17:26:33 1994 Mike Stump +Tue Nov 25 11:28:21 1997 Jason Merrill - * cvt.c (build_up_reference): Fix breakage introduced on Nov 29, - don't assert on complex AGGR inits. + * init.c (build_new): Copy size to the saveable obstack. -Thu Dec 22 14:32:31 1994 Mike Stump + * init.c (build_new): Stick a CLEANUP_POINT_EXPR inside the + TRY_CATCH_EXPR for now. - * method.c (build_overload_value): Handle pointer to members as - template arguments. +Mon Nov 24 12:15:55 1997 Jason Merrill -Thu Dec 22 13:09:07 1994 Mike Stump + * typeck.c (mark_addressable): Don't assume a FUNCTION_DECL + has DECL_LANG_SPECIFIC. - * typeck.c (unary_complex_lvalue): Don't call sorry if we know how - to do take the address of a data member for a pointer to data - member. + * exception.cc (struct cp_eh_info): Add handlers field. + (__cp_push_exception): Initialize it. + (__cp_pop_exception): Decrement it. Don't pop unless it's 0. + (__throw_bad_exception): Remove. + * except.c (call_eh_info): Add handlers field. + (get_eh_handlers): New fn. + (push_eh_cleanup): Increment handlers. -Thu Dec 22 10:04:19 1994 Mike Stump +Fri Nov 21 12:22:07 1997 Jason Merrill - * decl.c (grokdeclarator): Use the typedef name for linkage if the - type doesn't otherwise have a name. + * except.c (expand_start_eh_spec): Use the try/catch code. + (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. + * 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. - * decl2.c (grokfield): Ditto. + * except.c (expand_start_catch_block): We only need the rethrow + region for non-sjlj exceptions. + (expand_end_catch_block): Likewise. Use outer_context_label_stack. - * class.c (finish_struct): Since we reuse the TYPE_DECL for the - DECL_NAME of enums, structs and classes, we have to avoid trying to - put it in the TYPE_FIELDS again. +Thu Nov 20 14:40:17 1997 Jason Merrill -Wed Dec 21 11:07:05 1994 Mike Stump + * Make-lang.in (CXX_LIB2FUNCS): Add new op new and op delete objs. + (various.o): Likewise. + * inc/new: Add placement deletes. Add throw specs for default new. + * new.cc (set_new_handler): Move here from libgcc2. + * new1.cc (new (nothrow)): Catch a bad_alloc thrown from the handler. + (new): Move from libgcc2. Throw bad_alloc. + * new2.cc: Move the rest of the op news and op deletes from libgcc2. + * decl.c (init_decl_processing): Update exception specs on new and + delete. - * decl2.c (check_classfn): Ignore this parameter on static functions - when checking to see if we match. + * method.c (build_decl_overload_real): Don't mess with global + placement delete. -Tue Dec 20 17:47:02 1994 Mike Stump + * init.c (build_new): Check for null throw spec, not nothrow_t. - * typeck.c (unary_complex_lvalue): Handle address of non-left most - pointers to members by calling get_delta_difference. + * decl.c (duplicate_decls): Don't complain about different exceptions + from an internal declaration. -Mon Dec 19 22:40:53 1994 Mike Stump + * call.c (build_op_delete_call): Fix check for member fns again. - * decl2.c (check_classfn): Don't use decls_match yet, as it modifies - static functions to early. + * decl2.c (import_export_decl): Interface hackery affects + virtual synthesized methods. -Thu Dec 19 22:37:48 1994 Mike Stump +Wed Nov 19 18:24:14 1997 Jason Merrill - * method.c (make_thunk): Handle encoding of positive thunk offsets. + * decl.c (start_decl): Don't just complain about a mismatched + scope, fix it. -Sat Dec 17 13:29:50 1994 Doug Evans + * decl.c (make_implicit_typename): Handle case where t is not + actually from context. + * tree.c (get_type_decl): Lose identifier case. + * spew.c (yylex): Lose useless call to identifer_typedecl_value. + * parse.y (nonnested_type): Just use lookup_name. + (complex_type_name): Just use IDENTIFIER_GLOBAL_VALUE. - * Make-lang.in (.PHONY): Tell GNU make C++ and c++ are phony targets. +Wed Nov 19 11:45:07 1997 Michael Tiemann -Thu Dec 15 16:32:12 1994 Mike Stump + * error.c (dump_function_name): Test DECL_LANG_SPECIFIC in case + T was built in C language context (for example, by + output_func_start_profiler). - * decl2.c (check_classfn): Use decls_match to check if this has - already been declared, as the DECL_ASSEMBLER_NAME may have been - changed via asm("new_name"). - * decl.c (decls_match): Make public. +Wed Nov 19 10:39:27 1997 Jason Merrill -Thu Dec 15 15:17:55 1994 Mike Stump + * decl.c (make_implicit_typename): New fn. + (lookup_name_real): Use it. Use current_class_type as the context. - * *.[chy] (expand_aggr_init) Add fourth argument to handle - distinction between = init and (init) style of initializations. - * *.[chy] (finish_decl): Add fifth argument to to handle - distinction between = init and (init) style of initializations. +Mon Nov 17 23:42:03 1997 Bruno Haible -Tue Dec 13 19:16:05 1994 Mike Stump + * pt.c (do_poplevel): Don't prohibit jumps into this contour. - Fix some random `explicit' bugs. +Mon Nov 17 02:01:28 1997 Jason Merrill - * cvt.c (convert_to_reference): Add third parameter to - convert_force. - (convert_force): Ditto. - * call.c (build_method_call): Ditto. - * decl2.c (setup_vtbl_ptr): Ditto. - * init.c (expand_virtual_init): Ditto. - (build_member_call): Ditto. - (build_delete): Ditto. - (build_vbase_delete): Ditto. - * typeck.c (build_component_addr): Ditto. - (build_c_cast): Ditto. - (build_modify_expr): Ditto. - * cp-tree.h (CONV_NONCONVERTING): Ditto. Add so that we can - distinguish the context in which the conversion appears. Add thrid - argument to build_c_cast. - * cvt.c (cp_convert): Pass whether or not we want to consider - non-converting constructors down to build_method_call. - * decl2.c (reparse_absdcl_as_casts): Add third argument to - build_c_cast. - * gc.c (build_m_desc): Ditto. - * init.c (build_new): Ditto. - * parse.y (expr_no_commas): Ditto. - (primary): Ditto. - * typeck.c (build_x_function_call): Ditto. - (build_static_cast): Ditto. - (build_reinterpret_cast): Ditto. - (build_const_cast): Ditto. - (build_c_cast): Ditto. - (build_ptrmemfunc): Ditto. - * typeck2.c (build_functional_cast): Ditto. - * init.c (expand_aggr_init): Added LOOKUP_ONLYCONVERTING to - expand_aggr_init_1 as inits are converted to the destination type. + * friend.c (do_friend): Warn about non-template friends in templates. -Tue Dec 13 16:18:57 1994 Jason Merrill + * call.c (build_op_delete_call): Fix handling of inherited delete. - * Make-lang.in (cc1plus): Depends on c-pragma.o. + * search.c (dfs_record_inheritance): Ignore template type parms. - * Makefile.in (OBJ{DEP,}S): Add ../c-pragma.o. +Sat Nov 15 00:30:51 1997 Jason Merrill - * lex.c (check_newline): If the #pragma is not recognized by g++, - try machine-specific ones too. - (handle_sysv_pragma): Copied from c-lex.c. + * call.c (build_new_op): Fix copy error. + (build_op_new_call): New fn. + (build_op_delete_call): New fn. + * cp-tree.h: Declare them. + * init.c (build_new): Use them. Support placement delete. + (build_x_delete): Use build_op_delete_call. + (build_delete): Likewise. + * decl2.c (delete_sanity): Likewise. + (coerce_delete_type): Don't complain about placement delete. -Mon Dec 12 23:53:06 1994 Mike Stump +Thu Nov 13 01:52:36 1997 Jason Merrill - * except.c (expand_throw): Fix Dec 6th change, build_new likes a - reference better. + * call.c (build_new_function_call): Remove unused 'obj' parm. + * cp-tree.h, typeck.c: Adjust. -Mon Dec 12 18:01:00 1994 Jason Merrill + * init.c (build_new): Make the cleanup last longer. + (expand_vec_init): Call do_pending_stack_adjust. - * typeck.c (build_binary_op): Lose checks on TYPE_PTRMEMFUNC_P with - IS_AGGR_TYPE, since now they will not both be set on the same type. +Wed Nov 12 11:04:33 1997 Jason Merrill - * pt.c (do_pending_expansions): Don't clear TREE_PUBLIC on - instantiations controlled by -fexternal-templates. + * pt.c (do_type_instantiation): Fix typo. + (mark_class_instantiated): If we support one_only but not weak + symbols, don't mark this as known. - * decl.c (duplicate_decls): Don't complain about different values of - __attribute__ ((const)) and ((noreturn)). + * init.c (build_new): Handle vec delete in EH cleanup. -Fri Dec 9 18:17:37 1994 Doug Evans +Wed Nov 12 08:11:55 1997 Benjamin Kosnik - * Makefile.in (BISONFLAGS): Delete --yacc. - (PARSE_H): Depend on $(PARSE_C), for parallel makes. - (PARSE_C): Undo last patch. + * call.c (build_method_call): Call complete_type before checking + for destructor. -Fri Dec 2 10:44:36 1994 Mike Stump (mrs@wombat.gnu.ai.mit.edu) +Sun Nov 9 01:29:55 1997 Jim Wilson (wilson@cygnus.com) - * Makefile.in (BISONFLAGS): Add --yacc so that output winds up in - y.tab.c. + * decl.c (add_block_current_level): Delete. + * init.c (build_vec_delete_1): Delete build_block and + add_block_current_level calls. -Thu Dec 8 17:39:46 1994 Jason Merrill +Wed Nov 12 00:48:16 1997 Jason Merrill - * decl.c (finish_decl): Don't call obscure_complex_init for decls - of indeterminate size. + * init.c (build_new): Handle freeing allocated memory when the + constructor throws. -Wed Dec 7 16:49:22 1994 Jason Merrill + * call.c (build_new_method_call): Fix flags arg. - * decl.c (obscure_complex_init): Function to tweak the decl to - prevent expand_decl from tring to initialize it. - (finish_decl): Use it rather than writing the same code in three - different places. + * pt.c (do_type_instantiation): Don't try to instantiate + member templates. + (mark_decl_instantiated): If we support one_only but not + weak symbols, mark this one_only. + * decl2.c (import_export_vtable): Don't defer handling of vtables + if MULTIPLE_SYMBOL_SPACES. - * parse.y (bad_parm): Stop trying to support parms without types. +Tue Nov 11 12:02:12 1997 Jason Merrill -Wed Dec 7 12:06:56 1994 Mike Stump + * except.c (expand_end_catch_block): Lose call to __sjpopnthrow. - * decl2.c (grokfield): Make asm specs on static member functions - work. +Tue Nov 11 02:53:44 1997 Jason Merrill -Tue Dec 6 15:43:20 1994 Mike Stump + * except.c (do_pop_exception): Return a value. - * except.c (expand_throw): Make a copy of the thrown object. +Mon Nov 10 20:25:31 1997 Jason Merrill -Tue Dec 6 14:16:34 1994 Jason Merrill + * 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. + * typeck.c (build_x_function_call): Remember the TEMPLATE_ID_EXPR, + 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. - * parse.y: : has lower precedence than =. +Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij -Tue Dec 6 12:46:17 1994 Mike Stump + * 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 + hasn't been done. - * decl.c (pushdecl): Use DECL_NAME of VAR_DECLs to avoid namespace - manglings. - (grokvardecl): Add namespace into variable name. + * 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. -Tue Dec 6 11:26:55 1994 Mike Stump +Mon Nov 10 20:08:38 1997 Jason Merrill - * decl2.c (current_namespace_id): New routine to transform a simple - name into a name in a namespace. - * decl.c (grokdeclarator): Use it. - * decl2.c (get_namespace_id): Find the name of the current - namespace. - (push_namespace, pop_namespace): Complete out missing - functionality. - -Mon Dec 5 17:11:51 1994 Jason Merrill - - * class.c (finish_struct): Don't use LONG_LONG_TYPE_SIZE, as it may - not be defined. Fix warning message for enums and restore warning - for non-enums. - - * decl2.c (push_namespace): Dummy function. - (pop_namespace): Ditto. - (do_namespace_alias): Ditto. - (do_using_decl): Ditto. - (do_using_directive): Ditto. - - * parse.y: New token NSNAME for namespace names. - (extdef): Add namespace, using definitions. - (using_decl): New rule for using declarations. - (any_id): New rule for identifiers with any degree of scoping. - (identifier): Add NSNAME. - (notype_identifier): Ditto. - (component_decl): Add using_decl. - (nested_name_specifier): Add NSNAME SCOPE. - - * typeck.c (convert_for_assignment): Handle conversions between - enums and bool. - - * decl.c (duplicate_decls): Only propagate DECL_MAIN_VARIANT on - FUNCTION_DECLs. + * decl.c (grokdeclarator): Tweak conditions for pedwarn in + previous change. -Mon Dec 5 13:03:16 1994 Mike Stump +Mon Nov 10 20:08:29 1997 Bruno Haible - * class.c (finish_struct): Give an error if one tries to declare a - bit-field's size greater than a long long, as the backend will dump. - It is not an error to declare an enum bit-field greater than its - precision. Warn if an enum bit-field is too small to hold all - its values. + * pt.c (coerce_template_parms): Tweak error message. -Mon Dec 5 11:41:50 1994 Mike Stump + * decl.c (grokdeclarator): If -Wreturn-type, warn everytime a + return type defaults to `int', even if there are storage-class + specifiers. - * typeck.c (convert_for_assignment): Use cp_convert instead of - convert so that we don't get static casts. +Mon Nov 10 03:04:20 1997 Jason Merrill -Sun Dec 4 11:59:01 1994 Mike Stump + Complete nested exception support. + * except.c (do_pop_exception): Split out... + (push_eh_cleanup): From here. Handle the EH region by hand. + (expand_start_catch_block): Add a new level for the catch parm. + Move the rethrow region outside the two cleanup regions. + Protect the initializer for the catch parm with terminate. + (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, + WITH_CLEANUP_EXPR, and UNSAVE_EXPR. + (build_cplus_new): Only wrap CALL_EXPRs. + * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around + the constructor call. - * cvt.c (cp_convert): Don't complain about int->enum conversion if - we are doing static casts. +Sun Nov 9 18:00:26 1997 Richard Kenner -Fri Dec 2 18:32:41 1994 Mike Stump + * Make-lang.in (c++.distdir): Make inc subdirectory. - * error.c (dump_expr): Do something more intelligent with SAVE_EXPRs - when dumping expressions in error messages. +Fri Nov 7 11:57:28 1997 Jason Merrill -Fri Dec 2 17:04:27 1994 Mike Stump + * decl2.c (finish_file): Put back some code. - * gc.c (build_dynamic_cast): Change interface to libg++, ensure that - the return type is the right type, and make references work. +Thu Nov 6 11:28:14 1997 Jason Merrill -Fri Dec 2 16:36:43 1994 Jason Merrill + * decl2.c (finish_file): Remove redundant code. + * method.c (emit_thunk): Don't let the backend defer generic thunks. - * decl.c (poplevel): Don't be confused by function-scope - declarations of non-nested functions. - (duplicate_decls): Propagate DECL_MAIN_VARIANT. - (pushdecl): Use duplicate_decls to copy info from old decl into new - function-scope one rather than doing it here. +Wed Nov 5 23:52:50 1997 Jason Merrill - * decl2.c (mark_inline_for_output): Deal with the DECL_MAIN_VARIANT - of this decl, in case this is a function-scope declaration. + * except.c (call_eh_info): Split out... + (push_eh_info): From here. + (expand_builtin_throw): Use it. + (expand_start_catch_block): Move region start back. - * decl.c (finish_enum): Make sure that the type has the right - precision when we call fixup_*_type. +Tue Nov 4 13:45:10 1997 Doug Evans -Tue Nov 29 19:12:07 1994 Jason Merrill + * lex.c (MULTIBYTE_CHARS): #undef if cross compiling. + (real_yylex): Record wide strings using target endianness, not host. - * cvt.c (build_up_reference): Strip superfluous NOP_EXPRs; we do - want to build up references to rvalues if possible. - (cp_convert): Stick on a NOP_EXPR when converting to the same type. +1997-11-03 Brendan Kehoe -Tue Nov 29 11:28:59 1994 Mike Stump + * repo.c (rindex): Add decl unconditionally. + (get_base_filename, open_repo_file): Don't cast rindex. + * xref.c (rindex): Add decl unconditionally. + (index): Remove unused decl. + (open_xref_file): Don't cast rindex. - * parse.y (maybe_raises): Handle throw (). - * parse.y (ansi_raise_identifier): grok type-ids in exception - specifications. - * tree.c (build_exception_variant): Use list compare to check if - two exception specifications match. - * decl.c (duplicate_decls, bad_specifiers): Enhance wording on error - messages. - * call.c (build_method_call): Remove TREE_RAISES. - * cvt.c (convert_to_aggr): Ditto. - * typeck.c (build_function_call_real, convert_arguments): Ditto. - * init.c (expand_aggr_init_1): Ditto. +Sun Nov 2 15:04:12 1997 Jason Merrill -Tue Nov 29 09:50:39 1994 Mike Stump + * class.c (build_vbase_path): Propagate the result type properly. - * except.c: Add support for m68k and mips exception handling - support. +1997-11-01 Brendan Kehoe -Tue Nov 29 08:48:33 1994 Mike Stump + * except.c (expand_builtin_throw) [!DWARF2_UNWIND_INFO]: Replace + remaining use of saved_throw_type with a call to get_eh_type. - * except.c (expand_end_all_catch): Throw into outer context, if we - fall off end of catch handlers. +1997-10-31 Brendan Kehoe -Mon Nov 28 16:44:41 1994 Mike Stump + * lex.c (FILE_NAME_NONDIRECTORY): Delete macro. + (file_name_nondirectory): New function, doing the same as the macro. + (set_typedecl_interface_info): Use it instead of the macro. + (check_newline): Likewise. + (handle_cp_pragma): Likewise. - * Makefile.in: Make is easier to decide where parse.[ch] will be - built. + * repo.c (get_base_filename): Cast result of rindex to char*. + (open_repo_file): Likewise. + * xref.c (open_xref_file): Likewise. + * error.c (dump_char): Make its arg int, not char. -Thu Nov 17 20:11:24 1994 Doug Evans + * except.c (push_eh_info): Pass the number of fields - 1 down, not + the exact number of fields. - * cp/Make-lang.in (CXX_INSTALL_NAME) Use program_transform_name. - (GXX_INSTALL_NAME) Likewise. - (CXX_CROSS_NAME) Use program_transform_cross_name. - (GXX_CROSS_NAME) Likewise. - (c++.install-man): Use program_transform_name on g++.1. - (c++.uninstall): Likewise. +Fri Oct 31 01:47:57 1997 Jason Merrill -Thu Nov 3 18:48:19 1994 Paul Eggert + Support for nested exceptions. + * tinfo2.cc (__is_pointer): New fn. + * exception.cc (struct cp_eh_info): Define. + (__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. + (init_exception_processing): Likewise. __eh_pc is now external. + (push_eh_info): New fn. + (get_eh_{info,value,type,caught}): New fns. + (push_eh_cleanup): Just call __cp_pop_exception. + (expand_start_catch_block): Use push_eh_info. Start the eh region + sooner. + (expand_end_eh_spec): Use push_eh_info. + (expand_throw): Call __cp_push_exception to set up the exception info. + Just pass the destructor or 0 as the cleanup. Call __uncatch_exception + when we rethrow. + (expand_builtin_throw): Don't refer to empty_fndecl. - * Makefile.in (spew.o, lex.o, pt.o): - Depend on $(srcdir)/parse.h, not parse.h. +Thu Oct 23 02:01:30 1997 Jason Merrill -Mon Nov 28 13:53:03 1994 Mike Stump + * pt.c (instantiate_decl): SET_DECL_IMPLICIT_INSTANTIATION on new decl. - * parse.y (THROW): Fix precedence of throw expressions. +1997-10-22 Brendan Kehoe -Mon Nov 28 13:15:16 1994 Mike Stump + * method.c (build_template_parm_names, build_decl_overload_real): + Add static to definitions. + * pt.c (add_to_template_args, note_template_header, + processing_explicit_specialization, type_unification_real): Likewise. + ({determine,check}_explicit_specialization): Use a single string for + error messages. - * typeck.c (build_unary_op): Allow promotions from bool to int on - unary ~. +Mon Oct 20 12:06:34 1997 Jason Merrill -Sun Nov 27 00:16:21 1994 Jason Merrill + * except.c (expand_exception_blocks): Call do_pending_stack_adust. + (expand_end_catch_block): Likewise. + (expand_end_eh_spec): Likewise. - * method.c (build_overload_name): Use DECL_ASSEMBLER_NAME for - classes when appropriate. - (build_overload_nested_name): When dealing with a function context, - use ASM_FORMAT_PRIVATE_NAME to tweak the name of the function to - avoid conflicts between local classes of the same name. +Mon Oct 20 11:44:20 1997 Mark Mitchell -Wed Nov 23 17:59:42 1994 Mike Stump + * decl.c (duplicate_decls): Handle template specializations + 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 - * gxx.gperf, parse.y, lex.h, hash.h, lex.c (init_lex), delc.c - (duplicate_decls, grokdeclarator), cp-tree.h: Add support for - `explicit'. - * cvt.c (convert_to_reference, cp_convert, build_type_conversion_1, - build_type_conversion): Use LOOKUP_ONLYCONVERTING in - build_method_calls so that non-converting constructors are not used. - * call.c (build_method_call): If we shouldn't use a non-converting - constructor, then don't. + * decl.c (init_decl_processing): Give null_node unknown* type. + * typeck.c (comp_target_types): Handle UNKNOWN_TYPE. + (common_type): Likewise. + * error.c (args_as_string): Recognize null_node. -Wed Nov 23 14:46:56 1994 Jason Merrill +Sun Oct 19 09:13:01 1997 Richard Kenner - * call.c (build_method_call): Don't try to synthesize methods yet. + * typeck.c (rationalize_conditional_expr): Handle {MIN,MAX}_EXPR. + (unary_complex_lvalue): Call it for {MIN,MAX}_EXPR. -Tue Nov 22 12:45:21 1994 Jason Merrill + * decl.c (init_decl_processing): Call using_eh_for_cleanups. - * pt.c (push_template_decls): Create CONST_DECLs for template - constant parameters, not VAR_DECLs. + * Make-lang.in (g++): Include prefix.o. -Sat Nov 19 15:28:31 1994 Jim Wilson (wilson@chestnut.cygnus.com) +Thu Oct 16 15:31:09 1997 Judy Goldberg - * typeck.c (build_binary_op_nodefault): Can shorten shift only if - shift count is less than size in bits of arg0. + * pt.c (determine_explicit_specialization): Initialize "dummy" + to keep Purify quiet. -Thu Nov 17 15:30:50 1994 Mike Stump +Thu Oct 16 00:14:48 1997 Jason Merrill - * gxx.gperf, hash.h, lex.c (init_lex, real_yylex), parse.y: Add new - ANSI keywords and, and_eq, bitand, bitor, explicit, namespace, not, - not_eq, or, or_eq, typename, using, xor, xor_eq to g++. Still need - to add support for explicit, namespace, typename, and using, support - for the rest is already in. + * method.c (build_overload_value): Handle TEMPLATE_CONST_PARMs here. + (build_overload_int): Not here. -Thu Nov 17 10:56:50 1994 Jason Merrill +Wed Oct 15 00:35:28 1997 Mike Stump - * typeck2.c (build_m_component_ref): Check the basetype of the - member pointer against the main variant of the object type. + * class.c (build_type_pathname): Remove. + (prepare_fresh_vtable): Fix problem with complex MI vtable names. -Mon Nov 14 14:21:52 1994 Jason Merrill +1997-10-14 Brendan Kehoe - * cvt.c (convert_to_reference): Make sure that the original expr - gets its type back when converting a reference. + * parse.y (unary_expr): Give a pedwarn if someone tries to use the + &&label GNU extension. - * method.c (build_overload_name): Clear numeric_outputed_need_bar here. - (build_decl_overload): Instead of here. +Tue Oct 14 12:01:00 1997 Mark Mitchell -Tue Nov 8 17:11:24 1994 Jason Merrill + * decl.c (pushtag): Unset DECL_ASSEMBLER_NAME before setting it, + 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 - * cvt.c (cp_convert): Don't build a TARGET_EXPR if we're not in a - function. + * 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, + 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. - * typeck.c (convert_for_initialization): Handle initialization from - a TARGET_EXPR. +Mon Oct 13 17:41:26 1997 Benjamin Kosnik -Sun Nov 6 01:34:24 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * decl.c (store_return_init): Allow classes with explicit ctors to + be used with the named return values extension. - * pt.c (lookup_nested_type_by_name): Fix list-walking logic. - (tsubst): When replacing a TEMPLATE_TYPE_PARM, propagate - TYPE_READONLY and TYPE_VOLATILE from the argument. - (unify): When unifying with a TEMPLATE_TYPE_PARM, remove cv-quals - present in parm from arg. - (type_unification): Strip REFERENCE_TYPE from the argument type. - (unify): Don't strip REFERENCE_TYPE from the argument type. +Fri Oct 10 12:21:11 1997 Jason Merrill -Sat Nov 5 22:42:15 1994 Greg McGary (gkm@magilla.cichlid.com) + * pt.c (instantiate_decl): Fix previous change. - * pt.c (do_type_instantiation): Check to see if there's a - IDENTIFIER_TEMPLATE on a class before calling - instantiate_member_templates(). +Thu Oct 9 12:08:21 1997 Jason Merrill -Fri Nov 4 19:04:18 1994 Mike Stump + * pt.c (tsubst): Fix thinko. + (instantiate_decl): Really use the original template. - * gc.c (get_bad_cast_node): New routine to support compile time - throws of bad_cast. - * gc.c (build_dynamic_cast): Support throwing of bad_cast at compile - time. + * call.c (build_new_method_call): Use simple constructor_name for + error messages. -Fri Nov 4 11:12:00 1994 Mike Stump +Wed Oct 8 22:44:42 1997 Jeffrey A Law (law@cygnus.com) - * except.c: Add hppa support. + * method.c (build_underscore_int): Don't use ANSI specific + features. -Fri Nov 4 10:50:50 1994 Mike Stump +Wed Oct 8 00:18:22 1997 Jason Merrill - * except.c: Add rs6000 support. + * decl2.c (finish_prevtable_vardecl): Check DECL_REALLY_EXTERN + for our key method; it might have been inlined by -O3. -Thu Nov 3 14:24:23 1994 Mike Stump +Tue Oct 7 23:00:12 1997 Mark Mitchell - * except.c (do_unwind): Add i[34]86 support. + * decl.c (make_typename_type): Do not try to call lookup_field for + non-aggregate types. -Thu Nov 3 00:10:46 1994 Jason Merrill (jason@phydeaux.cygnus.com) +Tue Oct 7 22:52:10 1997 Jason Merrill - * pt.c (do_pending_expansions): Unset TREE_PUBLIC on implicit - instantiations. + * typeck.c (build_reinterpret_cast): Tweak. -Wed Nov 2 15:08:24 1994 Kung Hsu (kung@mexican.cygnus.com) +Tue Oct 7 22:45:31 1997 Alexandre Oliva - * decl.c (finish_function): emit types used in method parameters - into symbol table. + * typeck.c (build_reinterpret_cast): converting a void pointer + to function pointer with a reinterpret_cast produces a warning + if -pedantic is issued -Wed Nov 2 15:05:47 1994 Jason Merrill (jason@phydeaux.cygnus.com) +Tue Oct 7 22:43:43 1997 Bruno Haible - * pt.c (process_template_parm): Allow pointer to member function - template parameter types. - (uses_template_parms): Handle pointer to member function - CONSTRUCTORs. + * typeck.c (c_expand_return): Don't warn about returning a + reference-type variable as a reference. - * g++.c (main): Cast first argument of bzero to (char *). - Pass -lstdc++ instead of -lg++ unless we are invoked as 'g++'. +Tue Oct 7 21:11:22 1997 Jason Merrill -Mon Oct 31 14:50:48 1994 Kung Hsu (kung@mexican.cygnus.com) + * method.c (build_static_name): Fix typo. - * gc.c (build_dynamic_cast): rewrite to make it work. - * class.c (finish_vtbls): build more vtables if flag_rtti is on. - * class.c (modify_all_direct_vtables): ditto. - * init.c (expand_direct_vtbls_init): expand more vtables if - flag_rtti is on. - * decl.c (init_type_desc): add default return. +1997-10-07 Brendan Kehoe -Tue Oct 25 17:13:09 1994 Kung Hsu (kung@mexican.cygnus.com) + * decl.c (duplicate_decls): Make sure DECL_LANG_SPECIFIC is set on + OLDDECL before we try to do DECL_USE_TEMPLATE. - * tree.c (debug_binfo): get rid of the initial size entry of - vtable. - * cp-tree.h: change flag_dossier to flag rtti, define type - descriptor type nodes. - * decl.c (init_type_desc): new function to initialize type - descriptor type nodes. - * decl.c (record_builtin_type): change flag_dossier to flag_rtti. - * lex.c (init_lex): ditto. - * decl.c : change variable flag_dossier to flag_rtti. - * decl.c (duplicate_decls): get rid initial size entry of vtable. - * decl.c (hack_incomplete_structures): take out assert 164. - * search.c (get_abstract_virtuals_1): ditto. - * search.c (dfs_init_vbase_pointers): change CLASSTYPE_DOSSIER to - CLASSTYPE_RTTI. - * parse.y: ditto. - * class.c (prepare_fresh_vtable): for virtual bases, get right - offset. - * class.c (add_virtual_function): change flag_dossier to - flag_rtti. - * class.c (modify_one_vtable): modify the right rtti entry. - * class.c (override_one_vtable): get rid of size entry. - * class.c (finish_struct): change flag_dossier to flag_rtti, and - build extra vtables, build type descriptors for polymorphic - classes. - * gc.c (build_headof): make headof() works correctly with new - rtti. - * gc.c (build_typeid): make this function work with new rtti. - * gc.c (get_typeid): make this function work with new rtti. - * gc.c (build_bltn_desc): new function for new rtti. - * gc.c (build_user_desc): ditto. - * gc.c (build_class_desc): ditto. - * gc.c (build_ptr_desc): ditto. - * gc.c (build_attr_desc): ditto. - * gc.c (build_func_desc): ditto. - * gc.c (build_ptmf_desc): ditto. - * gc.c (build_ptmd_desc): ditto. - * gc.c (build_t_desc): ditto. - * gc.c : comment out old build_t_desc, build_i_desc, build_m_desc. +Tue Oct 7 00:48:36 1997 Jason Merrill -Tue Oct 25 13:37:41 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * decl.c (duplicate_decls): Don't warn about template instances. - * call.c (convert_harshness): Check for TREE_UNSIGNED differences - after checking for integral conversions. + * typeck.c (mark_addressable): Lose ancient code that unsets + DECL_EXTERNAL. -Sun Oct 23 13:19:55 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * pt.c (do_decl_instantiation): Lose support for instantiating + non-templates. - * decl2.c: Declare flag_access_control. - (struct lang_f_options): Add access-control. - * expr.c (cplus_expand_expr, NEW_EXPR): Unset flag_access_control - for the call to expand_aggr_init to copy the object out of the - pcc_struct_return slot. - * search.c (compute_access): if (!flag_access_control) return - access_public. + * call.c (build_new_function_call): Fix handling of null explicit + template args. + (build_new_method_call): Likewise. -Fri Oct 21 00:32:54 1994 Jason Merrill (jason@phydeaux.cygnus.com) +Mon Oct 6 23:44:34 1997 Mark Mitchell - * lex.c (cons_up_default_function): Don't try to defer method - synthesis now. + * method.c (build_underscore_int): Fix typo. - * decl.c (init_decl_processing): Use __pure_virtual for abort_fndecl - instead of abort, since the OSF/1 dynamic linker doesn't like to see - relocation entries for abort. +1997-10-06 Brendan Kehoe - * tree.c (array_type_nelts_total): Use sizetype, not - integer_type_node. - (array_type_nelts_top): Ditto. + * tree.c (print_lang_statistics): #if 0 call to + print_inline_obstack_statistics until its definition is checked in. -Thu Oct 20 15:48:27 1994 Mike Stump +Mon Oct 6 09:27:29 1997 Jason Merrill - * decl.c (grokdeclarator): Added handling for catch parameters - (CATCHPARM). - * except.c (expand_start_catch_block): Use the new CATCHPARM context - instead of NORMAL. - * except.c (expand_throw): Don't let convert_to_reference complain - about what we are doing. + * decl2.c (finish_file): Move dump_tree_statistics to end. -Thu Oct 20 12:55:24 1994 Jim Wilson (wilson@cygnus.com) + * pt.c (instantiate_decl): Look for the original template. + (tsubst): Set DECL_IMPLICIT_INSTANTIATION on partial instantiations + of member templates. - * method.c (emit_thunk): Call instantiate_virtual_regs. +Wed Oct 1 08:41:38 1997 Jason Merrill -Wed Oct 19 14:15:33 1994 Mike Stump + * Makefile.in (g++FAQ.*): New rules. + (CONFLICTS): Update. + * g++FAQ.texi: Moved from libg++. - * except.c (expand_exception_blocks): Make sure throw code doesn't - get put in function that won't be output. + * parse.y (PFUNCNAME): Only specify the type once. -Mon Oct 17 18:03:15 1994 Jason Merrill (jason@phydeaux.cygnus.com) +1997-10-01 Brendan Kehoe - * decl.c (init_decl_processing): Make alloca a builtin. + * lex.c (real_yylex): Clean up the code to fully behave the way + the c-lex.c parser does for complex and real numbers. -Thu Oct 27 21:10:25 1994 Craig Burley (craig@burley) +Tue Sep 30 08:51:36 1997 Jason Merrill - * g++.c (main): Only decrement "added" and set "library" to - NULL when "library" != NULL (just like 940829 fix). + * method.c (build_decl_overload_real): Reformat. -Mon Oct 17 15:56:11 1994 Mike Stump +Tue Sep 30 00:18:26 1997 Jason Merrill - * except.c (expand_start_catch_block): Make sure the false label - gets onto the permanent obstack, as it is used for the exception - table. + * method.c (synthesize_method): If at_eof, determine our linkage. -Fri Oct 14 18:54:48 1994 Mike Stump +1997-09-29 Paul Eggert - * class.c (modify_one_vtable): Since the DECL_CONTEXT of fndecl can - be set just below, use current_fndecl instead. + * lex.c (real_yylex): Treat `$' just like `_', except issue a + diagnostic if !dollars_in_ident or if pedantic. -Fri Oct 14 15:12:22 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * lang-specs.h (@c++): -ansi no longer implies -$. - * init.c (expand_aggr_vbase_init_1): Don't call expand_aggr_init_1 - with LOOKUP_SPECULATIVELY. - (expand_default_init): Abort if build_method_call returns NULL_TREE. + * decl2.c (lang_decode_option): + -traditional and -ansi now do not mess with + dollars_in_ident. - * typeck.c (build_modify_expr): Don't just build a MODIFY_EXPR if - the rhs is a TARGET_EXPR. +Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu) - * parse.y (left_curly): Anonymous types are not affected by #pragma - interface/implementation. + * Makefile.in (parse.o, decl.o): Also depend on + $(srcdir)/../except.h $(srcdir)/../output.h. + (decl2.o): Also depend on $(srcdir)/../expr.h ../insn-codes.h + $(srcdir)/../except.h $(srcdir)/../output.h. + (typeck.o, init.o): Also depend on $(srcdir)/../expr.h + ../insn-codes.h. - * method.c (synthesize_method): Don't call setup_vtbl_ptr for the - default constructor if it isn't needed. + * call.c, cp-tree.h, decl.c, tree.c: Finish prototyping. - * lex.c (cons_up_default_function): Do synthesize methods for - anonymous types if necessary. + * expr.c (cplus_expand_expr): Make it static. -Thu Oct 13 17:44:55 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * decl2.c, init.c, typeck.c: Include "expr.h". + (expand_expr): Use proper values when calling the function. - * method.c (build_decl_overload): Set numeric_outputed_need_bar to 0. +Mon Sep 29 11:05:54 1997 Alexandre Oliva -Wed Oct 12 13:27:57 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * 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. - * typeck.c (build_modify_expr): Understand how to copy an aggregate. +Mon Sep 29 09:20:53 1997 Benjamin Kosnik - * init.c (expand_default_init): Ditto. Also remove some of the - crufty code that assumes methods will not be synthesized properly. + * decl.c (cp_finish_decl): Allow expand_aggr_init to set + TREE_USED, reset value based on already_used. - * lex.c (cons_up_default_function): If the containing type has no - name, these functions should never need to be called, so just - declare them. + * init.c (expand_member_init): Revert change. + +Mon Sep 29 08:57:53 1997 Jason Merrill + + * cp-tree.h, decl.c, decl2.c, pt.c: + 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 + + * friend.c (do_friend): Disable injection for all template-derived + decls. + * decl2.c (lang_decode_option): Handle -fguiding-decls. + * parse.y (notype_template_declarator): New nonterminal. + (direct_notype_declarator): Use it. + (complex_direct_notype_declarator): Likewise. + (object_template_id): Accept any kind of identifier after TEMPLATE. + (notype_qualified_id): Don't add template declarators here. + +Sat Sep 27 16:21:58 1997 Mark Mitchell + + * 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. + + * cp-tree.def (TEMPLATE_ID_EXPR): New tree code. + + * 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, + 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. + +1997-09-25 Andreas Schwab + + * decl.c (init_decl_processing): Declare __builtin_constant_p as + accepting any kind of type, not only int. + +Fri Sep 26 00:22:56 1997 Jason Merrill + + * search.c (get_matching_virtual): Notice virtual bases when sorrying + about covariant returns. + + * parse.y (member_init): Also imply typename here. Remove ancient + extension for initializing base members. + +Thu Sep 25 11:11:13 1997 Jason Merrill + + Handle multi-level typenames and implicit typename in base list. + * parse.y (typename_sub{,[0-2]}): New rules. + (structsp, rule TYPENAME_KEYWORD): Use typename_sub. + (nonnested_type): New rule. + (complete_type_name): Use it. + (base_class.1): Use typename_sub and nonnested_type. + (nested_name_specifier): Don't elide std:: here. + * decl.c (make_typename_type): Handle getting a type for NAME. + (lookup_name_real): Turn std:: into :: here. + + 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. + +1997-09-22 Brendan Kehoe + + * decl.c (start_function): Up warning of no return type to be a + pedwarn. + +Mon Sep 22 14:15:34 1997 Benjamin Kosnik + + * init.c (expand_member_init): Don't set TREE_USED. + * decl.c (cp_finish_decl): Mark decls used if type has TREE_USED + set,don't clear TREE_USED wholesale. + +Sat Sep 20 15:31:00 1997 Jason Merrill + + * call.c (build_over_call): Do require_complete_type before + build_cplus_new. - * lex.c (real_yylex): Use HOST_BITS_PER_WIDE_INT to determine the - bitmask for lexing character constants. +Thu Sep 18 16:47:52 1997 Jason Merrill - * call.c (build_method_call): Disable code that tries to do tricky - stuff with a default parameter that is a constructor call, but - actually does other tricky stuff that breaks things. + * search.c (lookup_field): Call complete_type in all cases. -Wed Oct 12 16:14:01 1994 Benoit Belley + * decl.c (finish_function): Just warn about flowing off the end. - * decl.c (finish_enum): Disable code which forces enums to be signed, - since this conflicts with their use as bitfields. type_promotes_to - handles promotion of enums of underlying unsigned types to signed - integer types. +Wed Sep 17 10:31:25 1997 Jason Merrill -Wed Oct 12 13:24:03 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * decl.c (grokparms): Don't bash a permanent list node if we're + in a function. - * cvt.c (type_promotes_to): Also promote enums to long if - appropriate. +1997-09-17 Brendan Kehoe - * typeck.c (default_conversion): Don't expect type_promotes_to to - return a main variant. + * Makefile.in (CONFLICTS): Fix s/r conflict count to 18. -Wed Oct 12 12:19:45 1994 Jason Merrill (jason@phydeaux.cygnus.com) +Tue Sep 16 14:06:56 1997 Jason Merrill - * call.c (build_scoped_method_call): Don't lose side effects in the - object expression when calling a non-existent destructor. + * call.c (build_new_op): Give better error for syntactically + correct, but semantically invalid, use of undeclared template. -Fri Sep 2 19:05:21 1994 Rohan Lenard (rjl@iassf.easams.com.au) + * call.c (compare_qual): Handle pmfs. - * call.c (build_scoped_method_call): Remove erroneous error message - when destructor call is written as a scoped call. + * decl.c (store_parm_decls): last_parm_cleanup_insn is the insn + after the exception spec. -Tue Oct 11 23:48:31 1994 Jason Merrill (jason@phydeaux.cygnus.com) +Mon Sep 15 11:52:13 1997 Jason Merrill - * various: Cast pointer arguments to bzero and bcopy to char *. + * call.c (null_ptr_cst_p): Integer type, not integral type. -Tue Oct 11 19:34:32 1994 Mike Stump + * call.c (joust): Disable warnings until they can be moved to the + right place. - * class.c (get_derived_offset): Added a type parameter to limit how - far up the CLASSTYPE_VFIELD_PARENT chain we search. - * class.c (modify_one_vtable, fixup_vtable_deltas): When forming the - offset to put into the vtable for the this parameter, make sure we - don't offset from a parent of the DECL_CONTEXT of the function. +Fri Sep 12 16:11:13 1997 Per Bothner -Tue Oct 11 16:10:52 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * Makefile.in, config-lang.in: Convert to autoconf. - * pt.c (do_function_instantiation): Set DECL_EXTERNAL and - TREE_STATIC when setting DECL_INTERFACE_KNOWN. - (do_type_instantiation): Ditto. +Thu Sep 11 17:14:55 1997 Jason Merrill - * lex.c (cons_up_default_function): Set DECL_INTERFACE_KNOWN, - DECL_EXTERNAL and TREE_STATIC as appropriate. + * decl.c (lookup_name_real): Add implicit 'typename' to types from + base classes. - * decl2.c (finish_file): Also synthesize methods that don't have - DECL_EXTERNAL set. Set interface_unknown before doing so. + * pt.c (most_specialized_class): Fix typo. + (tsubst): Move constant folding to TREE_VEC case. - * decl.c (start_function): If DECL_INTERFACE_KNOWN is set on the - function decl, don't muck with TREE_PUBLIC and DECL_EXTERNAL. +Thu Sep 11 10:08:45 1997 Mark Mitchell -Mon Oct 10 00:56:53 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * pt.c (do_poplevel): Don't warn about unused local variables + while processing_template_decl since we don't always know whether + or not they will need constructing/destructing. - * lex.c (cons_up_default_function): Mark methods in a template class - as template instances. Store the values of interface_unknown and - interface_only for do_pending_inlines. - (do_pending_inlines): Use them. + * pt.c (uses_template_parms): Check the values of an enumeration + type to make sure they don't depend on template parms. - * decl2.c (finish_file): If we haven't seen a definition of a - function declared static, make the decl non-PUBLIC so compile_file - can give an error. + * decl.c (make_typename_type): Don't lookup the field if the + context uses template parms, even if we're not + processing_template_decl at the moment. -Sun Oct 9 02:42:29 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * pt.c (coerce_template_parms): Avoid looking at the + TYPE_LANG_DECL portion of a typename type, since there won't be + one. + (tsubst): Do constant folding as necessary to make sure that + arguments passed to lookup_template_class really are constants. - * method.c (do_build_copy_constructor): Handle anonymous unions. - (do_build_assign_ref): Ditto. - (largest_union_member): Move from lex.c. +Wed Sep 10 11:21:55 1997 Jason Merrill -Sat Oct 8 14:59:43 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * except.c (expand_builtin_throw): #ifndef DWARF2_UNWIND_INFO. + * decl2.c (finish_file): Only register exception tables if we + need to. - Re-implement g++'s vague linkage independent of TREE_PUBLIC. - * pt.c (instantiate_member_templates): Lose redundant - -fexternal-templates handling. - (tsubst): Set TREE_PUBLIC and DECL_EXTERNAL on new decls. Don't set - TREE_STATIC or DECL_INTERFACE_KNOWN. - (do_pending_expansions): Predicate on DECL_INTERFACE_KNOWN instead - of DECL_EXTERNAL for explicit instantiations. - (do_function_instantiation): Do the new thing. - (do_type_instantiation): Ditto. - (instantiate_template): Deal with member templates defined in a .cc - file with -fexternal-templates. - * except.c (expand_exception_blocks): Use DECL_LINKAGE_KNOWN to - decide whether to stick builtin_throw here. - * decl2.c (import_export_inline): Predicate on DECL_INTERFACE_KNOWN - rather than TREE_PUBLIC. Generally fix rules. - (finish_file): Use DECL_INITIAL to determine whether or not a method - has been synthesized, rather than TREE_ASM_WRITTEN. - * decl.c (warn_extern_redeclared_static): Use DECL_PUBLIC instead of - TREE_PUBLIC. - (pushdecl): Ditto. - (duplicate_decls): Ditto. Deal with DECL_DECLARED_STATIC and - DECL_INTERFACE_KNOWN. - (redeclaration_error_message): Fix checking for conflicting linkage. - (define_function): Set DECL_INTERFACE_KNOWN. - (grokfndecl): Function decls are PUBLIC until we are sure about - their linkage. Set DECL_DECLARED_STATIC as needed. - (start_function): Deal with linkage. Move pushdecl after linkage - magic. - (finish_function): Don't set TREE_ASM_WRITTEN on discarded inlines. - * cp-tree.h (lang_decl_flags): Add interface_known and - declared_static. - (DECL_INTERFACE_KNOWN): New macro. - (DECL_DECLARED_STATIC): New macro. - (DECL_PUBLIC): New macro. + * decl.c (init_decl_processing): Add __builtin_[fs]p. - Clean up bogus use of TREE_PUBLIC. - * class.c (alter_access): Fix mistaken use of TREE_PUBLIC (it - doesn't correspond to TREE_PROTECTED and TREE_PRIVATE). - * init.c (do_friend): Don't arbitrarily set TREE_PUBLIC. +Tue Sep 9 19:49:38 1997 Jason Merrill -Wed Oct 5 13:44:41 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * pt.c (unify): Just return 0 for a TYPENAME_TYPE. - * call.c (build_overload_call_real): Don't immediately do - array->pointer conversion. +Tue Sep 9 17:57:25 1997 Mark Mitchell - * pt.c (type_unification): If not passing to a reference, strip - cv-quals. Also handle array->pointer conversion. + * error.c (dump_decl): Avoid crashing when presented with a + 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. -Tue Oct 4 17:45:37 1994 Jason Merrill (jason@phydeaux.cygnus.com) +1997-09-09 Brendan Kehoe - * decl.c (grokdeclarator): Don't warn about applying const to a - const typedef or template type parameter. + * typeck.c (build_indirect_ref): Heed FLAG_VOLATILE similar to + c-typeck.c. - * decl2.c (finish_file): Also synthesize methods after walking the - vtables. Ugly ugly ugly. +Tue Sep 9 09:36:39 1997 Benjamin Kosnik -Mon Oct 3 15:02:41 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * except.c (expand_throw): Call build_delete for all + exception types, not just objects with destructors. - * various: Remove lingering remnants of old exception handling code. +Mon Sep 8 02:33:20 1997 Jody Goldberg - * decl2.c (finish_file): Synthesize methods before walking the - vtables, so that the vtables get emitted as needed. + * 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. + (tsubst_expr): Likewise. - * decl.c (shadow_tag): Remove obsolete code for pushing tags and - dealing with exceptions. +Mon Sep 8 01:21:43 1997 Mark Mitchell -Mon Oct 3 13:05:27 1994 Ian Lance Taylor + * pt.c (begin_member_template_processing): Take a function as + argument, not a set of template arguments. Use the template + parameters, rather than the arguments. Handle non-type parameters + correctly. Push a binding level for the parameters so that multiple + 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. - * Make-lang.in (g++-cross): Depend upon version.o and $(LIBDEPS). + * lex.c (do_pending_inlines): Pass the function, not its template + arguments, to begin_member_template_processing. + (process_next_inline): Likewise. + (do_pending_defargs): Likewise. -Mon Oct 3 02:59:28 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * error.c (dump_expr): Obtain the correct declaration for a + TEMPLATE_CONST_PARM. - * decl2.c (finish_file): Fix inline handling. + * 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 -Sun Oct 2 00:21:56 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * 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. - * decl.c (grokdeclarator): Handle redundant scope even better. - ({push,pop}_cp_function_context): Take toplev parameter. +Fri Sep 5 17:27:38 1997 Jason Merrill - * method.c (synthesize_method): Pass toplev parameter to - {push,pop}_cp_function_context depending on decl_function_context - (fndecl). + * class.c (grow_method): Remove check for redeclaration. - * typeck.c (build_x_unary_op): Unary & on OFFSET_REFs is always the - built-in version. +Fri Sep 5 01:37:17 1997 Mark Mitchell - * method.c (synthesize_method): Don't be confused by __in_chrg - parameter. + * cp-tree.h (INNERMOST_TEMPLATE_PARMS): New macro. + (DECL_INNERMOST_TEMPLATE_PARMS): Likewise. + (PRIMARY_TEMPLATE_P): Use it. + * call.c (build_overload_call_real): Use it. + * class.c (instantiate_type): Likewise. + * decl.c (decls_match): Likewise. + * method.c (build_overload_identifier): Likewise. + * 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. + (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. + + * error.c (dump_expr): Deal with template constant parameters in + member templates correctly. + + * pt.c (is_member_template): Deal with class specializations + correctly. + (tsubst): Handle "partial instantiation" of member templates + correctly. + +Wed Sep 3 12:30:24 1997 Mark Mitchell + + * pt.c (type_unification): Change calling squence to allow for + multiple levels of template parameters. + (tsubst_expr): Likewise. + (tsubst): Likewise. + (tsubst_copy): Likewise. + (instantiate_template): Likewise. + (unify): Likewise. + * call.c (build_overload_call_real): Use it. + (add_builtin_candidate): Use it. + (build_new_method_call): Use it. + * class.c (instantiate_type): Use it. + * 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. + (build_user_type_conversion_1): Handle member templates. + (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. + (finish_struct): Treat member template functions just like member + functions. + + * cp-tree.h (check_member_template): Add declaration. + (begin_member_template_processing): Likewise. + (end_member_template_processing): Likewise. + (fn_type_unification): Likewise. + (is_member_template): Likewise. + (tsubst): Change prototype. + (tsubst_expr): Likewise. + (tsubst_copy): Likewise. + (instantiate_template): Likewise. + (get_bindings): Likewise. + + * decl.c (decls_match): Handle multiple levels of template + parameters. + (pushdecl): Handle template type params just like other type + 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. - * class.c (popclass): Set C_C_D like start_function does. + * lex.c (do_pending_inlines): Set up template parameter context + for member templates. + (process_next_inline): Likewise. - * decl.c (grokdeclarator): Handle redundant scope better. + * method. (build_overload_identifier): Adjust for multiple levels + of template parameters. + + * parse.y (fn.def2): Add member templates. + (component_decl_1): Likewise. + + * pt.c (begin_member_template_processing): New function. + (end_member_template_processing): Likewise. + (is_member_template): Likewise. + (fn_type_unification): Likewise. + (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. + (lookup_template_class): Likewise. + (uses_template_parms): Likewise. + (tsubst): Modify processing to TEMPLATE_TYPE_PARM and + TEMPLATE_CONST_PARM to deal with multiple levels of template + arguments. Add processing of TEMPLATE_DECL to produce new + TEMPLATE_DECLs from old ones. + (do_decl_instantiation): Handle member templates. + + * search.c (lookup_fnfields_1): Handle member template conversion + operators. + + * tree.c (cp_tree_equal): Check the levels, as well as the + indices, of TEMPLATE_CONST_PARMs. + + * 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. + +Wed Sep 3 11:09:25 1997 Jason Merrill - * parse.y (expr_or_declarator): Add '(' expr_or_declarator ')' rule. - (direct_notype_declarator): Ditto. - (complex_direct_notype_declarator): Remove it here. + * typeck.c (c_expand_return): Always convert_for_initialization + before checking for returning a pointer to local. -Sat Oct 1 21:42:18 1994 Jason Merrill (jason@deneb.cygnus.com) - - * init.c (resolve_offset_ref): Fix types used in resolving .* - expressions. - -Sat Oct 1 15:18:49 1994 Jason Merrill (jason@phydeaux.cygnus.com) + * pt.c (type_unification): If strict and the function parm doesn't + use template parms, just compare types. - Beginnings of work to synthesize methods only when needed. - * call.c (build_method_call): Synthesize methods as necessary - (currently never necessary). - * class.c (popclass): Don't try to set C_C_D here, as it'll end up - on the wrong obstack. - * decl.c (push_cp_function_context): Mostly copied from - push_c_function_context. - (pop_cp_function_context): Similarly. - (finish_function): Reverse order of poplevel and pop_nested_class so - that current_class_decl is restored properly. - (start_function): Ditto. - (finish_function): Add parameter 'nested'. Don't call - permanent_allocation if (nested). - * various: Pass extra parameter to finish_function. - * decl2.c (finish_file): Reorganize end-of-file inline handling, - synthesizing methods as necessary. - * lex.c (cons_up_default_function): Call mark_inline_for_output. - Only synthesize methods immediately if #pragma implementation - (currently disabled). - (do_pending_inlines): Call synthesize_method. - * method.c (synthesize_method): New function; all method synthesis - goes through here. Calls do_build_assign_ref and - do_build_copy_constructor. - (build_default_constructor): Remove. - (build_dtor): Ditto. - (build_assign_ref): Rename to do_build_assign_ref and remove stuff - done by synthesize_method. - (build_copy_constructor): Similarly. +Wed Sep 3 10:35:49 1997 Klaus Espenlaub -Thu Sep 29 16:58:52 1994 Mike Stump + * method.c (build_overloaded_value): Replace direct call + to the floating point emulator with REAL_VALUE_TO_DECIMAL macro. - * typeck.c (c_expand_return): Use magic so the backend can fixup the - assignment into the return register, so cleanups won't clobber it. +Wed Sep 3 00:02:53 1997 Jason Merrill -Thu Sep 29 13:08:50 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (convert_arguments): Don't arbitrarily choose the first + of a set of overloaded functions. - * method.c (hack_identifier): Don't call assemble_external for - template decls. +Tue Sep 2 12:09:13 1997 Jason Merrill - * decl.c (finish_decl): Also end temporary allocation if the decl in - question has a type of error_mark_node. + * lex.c (real_yylex): Don't elide __FUNCTION__. -Wed Sep 28 21:45:00 1994 Mike Stump + * method.c (build_overload_value): Add in_template parm. + (build_overload_int): Likewise. + (build_overload_identifier): Pass it. - * typeck.c (build_modify_expr): When optimizing ?: on lhs, make sure - that if the ?: was a reference type, that the subparts will be also. + * decl.c (duplicate_decls): Don't bash a previous template + definition with a redeclaration. -Wed Sep 28 16:14:04 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * pt.c (unify): float doesn't match double. - * except.c (register_exception_table): Use Pmode, not PTRmode. + * pt.c (do_type_instantiation): Handle getting a _TYPE or a + TYPE_DECL. Handle getting non-template types. + * parse.y (explicit_instantiation): Use typespec instead of + aggr template_type. -Fri Sep 23 13:54:27 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Sep 2 10:27:08 1997 Richard Henderson - * lex.c (do_pending_inlines): Do method synthesis after the - pending_inlines have been reversed. + * typeck.c (build_ptrmemfunc1): Clean up ptr->int cast warnings. -Thu Sep 22 12:53:03 1994 Per Bothner (bothner@kalessin.cygnus.com) +Mon Sep 1 13:19:04 1997 Eugene Mamchits - * decl2.c (finish_file): Fix Brendan's fix: Only call - register_exception_table if there is a non-empty exception table. + * call.c (add_builtin_candidate): Add missing TREE_TYPE. + (compare_ics): Likewise. -Thu Sep 22 12:03:46 1994 Brendan Kehoe (brendan@lisa.cygnus.com) +Mon Sep 1 13:19:04 1997 Jason Merrill - * decl2.c (finish_file): Only do register_exception_table if - -fhandle-exceptions is being used. + * call.c (joust): Warn about choosing one conversion op over + another because of 'this' argument when the other return type is + better. + (source_type): New fn. -Wed Sep 21 19:01:51 1994 Per Bothner (bothner@kalessin.cygnus.com) + * call.c (build_new_op): Strip leading REF_BIND from first operand + to builtin operator. - * except.c (output_exception_table_entry): Simplify - by using assemble_integer. - (build_exception_table): Change to return a count. - Cleanup to use standard macros, instead of hard-wired - sparc asm format. Don't make __EXCEPTION_TABLE__ global. - (register_exception_table): New function. Generate call to builtin. - * decl2.c (finish_file): Call register_exception_table. - * cp-tree.h (build_exception_table): Fix prototype. + * decl2.c (mark_vtable_entries): Mark abort_fndecl as used when we + use its RTL. -Wed Sep 21 13:20:42 1994 Brendan Kehoe (brendan@lisa.cygnus.com) +Thu Aug 28 09:45:23 1997 Jason Merrill - * tree.c (break_out_calls): Don't try to duplicate the DECL_INITIAL. + * call.c (null_ptr_cst_p): Remove support for (void*)0. - * decl2.c (delete_sanity): Give an error at trying to delete a - function. +Wed Aug 27 02:03:34 1997 Jeffrey A Law (law@cygnus.com) -Wed Sep 21 11:47:10 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (expand_target_expr): Make definition match declaration. - * lex.c (cons_up_default_function): Mark synthesized destructors - inline. + * class.c (get_basefndecls): Make definition match declaration. - * decl.c (duplicate_decls): Ignore redeclarations of wchar_t as - something other than __wchar_t, complaining if -pedantic and not in - a system header. +Mon Aug 25 14:30:02 1997 Jason Merrill -Tue Sep 20 09:43:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * input.c (sub_getch): Eventually give up and release the input file. - * decl.c (xref_tag): Set up BINFO_INHERITANCE_CHAIN on base binfos - here. + * decl.c (cp_finish_decl): If #p i/i, put inline statics in the + right place. - * typeck.c (build_modify_expr): Require complete type after checking - for error_mark_node. + * call.c (joust): Tweak message. - * call.c (build_method_call): Print parmtypes when complaining of - ambiguous call. +Sat Aug 23 18:02:59 1997 Mark Mitchell - * typeck.c (build_modify_expr): Handle assignment to array from - non-array. + * error.c (type_as_string): Put const/volatile on template type + parameters where appropriate. - * decl.c (lookup_name_real): Deal with got_scope == error_mark_node. +Sat Aug 23 17:47:22 1997 Jeffrey A Law (law@cygnus.com) - * call.c (build_method_call): Don't bother with the exact match. + * call.c (strictly_better): Make arguments unsigned ints. -Mon Sep 19 00:51:39 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Aug 21 18:48:44 1997 Jason Merrill - * init.c (expand_aggr_init): If we munge the type of the variable, - also munge the type of the initializer. + * lex.c (real_yylex): Refer to __complex instead of complex. - * decl.c (grokdeclarator): Use <= when comparing to RID_LAST_MODIFIER. - (init_decl_processing): Push artificial declaration of wchar_t so - people don't have to declare it before they can use it. +Thu Aug 21 22:25:46 1997 J"orn Rennecke - * error.c (cp_line_of): return lineno in lieu of 0. + * lex.c (real_yylex): Don't use getc directly. - * typeck.c (convert_for_assignment): Handle conversion of pmfs to - int and bool. - (build_component_ref): Fold the COMPONENT_REF in case it can be - reduced. +Wed Aug 20 17:25:08 1997 Jason Merrill - * typeck2.c (store_init_value): Don't pedwarn about non-constant - bracketed initializers for automatic variables. + * call.c (is_subseq): Don't try to be clever. -Sun Sep 18 10:12:12 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Aug 20 03:13:36 1997 H.J. Lu (hjl@gnu.ai.mit.edu) - * error.c (dump_decl): Don't say `typedef enum foo foo'. + * 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. - * decl.c (start_decl): Don't set TREE_PUBLIC on template decls just - because they're affected by #pragma i/i. We'll deal with that when - they get instantiated. +Wed Aug 20 01:34:40 1997 Jason Merrill - * typeck.c (build_unary_op): Clean up cruft in ADDR_EXPR case. + * decl2.c (mark_vtable_entries): Instead of replacing pure + virtuals with a reference to __pure_virtual, copy the decl and + change the RTL. - * class.c (instantiate_type): Set TREE_CONSTANT on instantiated - ADDR_EXPRs if appropriate. +Tue Aug 19 02:26:07 1997 Jason Merrill - * decl.c (build_ptrmemfunc_type): Unset IS_AGGR_TYPE on pmf types. + * pt.c (lookup_nested_type_by_name): Handle typedef wierdness. - * typeck.c (build_ptrmemfunc): Handle &overloaded_method as an - initializer properly. - * typeck2.c (digest_init): Ditto. + * typeck2.c (my_friendly_abort): Report bugs to egcs-bugs@cygnus.com. - * tree.c (cp_build_type_variant): Like c_build_type_variant, except - it uses build_cplus_array_type. - * *.c: Use cp_build_type_variant instead of c_build_type_variant. + * pt.c (instantiate_class_template): Call repo_template_used + before finish_prevtable_vardecl. - * pt.c (do_type_instantiation): Don't try to instantiate nested - enums. + * call.c (is_subseq): New fn. + (compare_ics): Use it. -Tue Sep 13 10:56:58 1994 Jason Merrill (jason@deneb.cygnus.com) + * repo.c (finish_repo): Don't crash on no args. - * cvt.c (build_up_reference): Handle preincrement and predecrement - properly. + * parse.y (named_complex_class_head_sans_basetype): Handle + explicit global scope. + * decl2.c (handle_class_head): New fn. -Tue Sep 13 09:51:59 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * pt.c (unify): Add CONST_DECL case. - * decl.c (finish_decl): Only lay out the rtl for DECL if it is, in - fact, static. +Thu Aug 14 10:05:13 1997 Brendan Kehoe -Mon Sep 12 14:40:30 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * rtti.c (permanent_obstack): Fix decl to not be a pointer. - * decl.c (finish_decl): Lay out the rtl for DECL before doing - grok_reference_init, in case it's static. + * cp-tree.h (report_type_mismatch): Add prototype. + * call.c (build_overload_call_real): Remove erroneous fourth + argument to report_type_mismatch. + (build_user_type_conversion_1): Remove erroneous second arg to + tourney. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_op): Likewise. + (build_new_method_call): Likewise. -Mon Sep 12 12:45:38 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Aug 13 19:19:25 1997 Jason Merrill - * class.c (finish_struct): Don't synthesize constructors if the - class has a field with the same name as the class. Don't die on - classes with no constructors or destructors. Don't die if the head - and tail of the class are in different files. + * error.c (dump_decl): Don't bother processing a function with no + DECL_LANG_SPECIFIC. - * decl.c (grokdeclarator): Don't treat a function pointer field - with the same name as the class as a constructor. + * method.c (emit_thunk): Call init_function_start in the macro case. -Fri Sep 9 13:17:00 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Aug 13 10:46:19 1997 H.J. Lu (hjl@gnu.ai.mit.edu) - * typeck.c (build_c_cast): Pull constant values out of their - variables here. + * decl2.c (DEFAULT_VTABLE_THUNKS): Define to be 0 if not + defined and used to set flag_vtable_thunks. - * decl.c (duplicate_decls): Only propagate DECL_CHAIN in - FUNCTION_DECLs and TEMPLATE_DECLs. +Tue Aug 12 20:13:57 1997 Jason Merrill -Thu Sep 8 10:07:48 1994 Jason Merrill (jason@deneb.cygnus.com) + * parse.y: Don't clear the inlines from their obstack until they've + all been processed. - * decl.c (duplicate_decls): Propagate DECL_CHAIN in all DECLs that - have it. + * decl.c (duplicate_decls): Don't complain about exception + specification mismatch if flag_exceptions is off. - * pt.c (unify): REALs and INTEGERs only unify with their own genus. - (instantiate_member_templates): Don't muck with DECL_EXTERNAL and - TREE_PUBLIC unless -fexternal-templates. +Mon Aug 11 15:01:56 1997 Marc Lehmann -Wed Sep 7 13:17:10 1994 Jason Merrill (jason@deneb.cygnus.com) + * Make-lang.in (c++.distclean): Remove g++.c on make distclean. - * pt.c (do_type_instantiation): Call instantiate_member_templates. - Deal with specializations. - (tsubst): Don't stick the mangled name in DECL_NAME for function - instantiations. Don't push them, either. +Sun Aug 10 12:06:09 1997 Paul Eggert - * decl2.c (grokfield): Move code for generating the - DECL_ASSEMBLER_NAME for static members from here. - * method.c (build_static_name): To here. - * decl.c (grokvardecl): Call build_static_name. - (duplicate_decls): Keep old DECL_ASSEMBLER_NAME. + * 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 before include files that formerly used STDIO_PROTO. -Mon Sep 5 12:49:18 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c, g++spec.c, lex.c, method.c, repo.c: + Include "config.h" first, as per autoconf manual. - * call.c (build_method_call): if -Wsynth, warn when selecting - synthesized op= over user-supplied one cfront would select. - * decl2.c (lang_decode_option): Handle -Wsynth. +Fri Aug 8 11:47:48 1997 Jason Merrill -Fri Sep 2 15:11:59 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (duplicate_decls): Tweak wording. + * lex.c (do_pending_defargs): Don't die if we see a default arg + that isn't a DEFAULT_ARG. + * error.c (dump_expr): Handle DEFAULT_ARG. - * decl.c (finish_enum): Overhaul to fix several bugs. - (start_enum): Disable useless code. + * decl2.c (lang_decode_option): Handle -fhandle-exceptions. + * lang-options.h: Add -fhandle-exceptions. -Thu Sep 1 16:04:54 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (build_vtable): vtables are artificial. + (prepare_fresh_vtable): Likewise. - * typeck.c (c_expand_return): Warn about returning a reference to a - temporary. - (convert_arguments): Increment argument counter when using default - arguments, too. +Wed Aug 6 11:02:36 1997 Jason Merrill -Wed Aug 31 14:29:22 1994 Jason Merrill (jason@deneb.cygnus.com) + * cvt.c (ocp_convert): After converting to the target type, set + LOOKUP_NO_CONVERSION. - * decl.c (finish_decl): If the type of decl is error_mark_node, - don't bother trying to do anything. + * call.c (joust): Warn about potentially confusing promotion rules + with -Wsign-promo. + * cp-tree.h, lang-options.h, decl2.c: Support -Wsign-promo. - * typeck.c (convert_for_initialization): If the rhs contains a - constructor call, pretend the lhs type needs to be constructed. +Tue Aug 5 15:15:07 1997 Michael Meissner - * init.c (expand_default_init): If we stick the object inside the - initializer, mark the initializer used. + * exception.cc: Declare __terminate_func with noreturn attribute. -Tue Aug 30 13:50:18 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Aug 1 03:18:15 1997 Jason Merrill - * method.c (build_assign_ref): return *this; - (build_assign_ref): Fix base assignment order. - (build_copy_constructor): Fix member init order. + * parse.y: Break out eat_saved_input, handle errors. + (function_try_block): Use compstmt instead of compstmt_or_error. -Mon Aug 29 13:54:39 1994 Brendan Kehoe (brendan@lisa.cygnus.com) +Thu Jul 31 17:14:04 1997 Jason Merrill - * g++.c (main): Remember to clear out SAW_SPECLANG after we see - its argument. + * tree.c (build_cplus_new): Don't set TREE_ADDRESSABLE. -Sat Aug 27 09:36:03 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Jul 4 01:45:16 1997 Andreas Schwab - * method.c (build_copy_constructor): Also copy virtual bases. + * Make-lang.in (cplib2.txt, cplib2.ready): Instead of checking for + existence of cc1plus check whether $(LANGUAGES) contains C++. -Fri Aug 26 17:05:15 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Jul 30 13:04:21 1997 Andreas Schwab - * lex.c (do_pending_inlines): Clear out pending_inlines before doing - any synthesis. Also first set deja_vu on all pending_inlines. + * method.c (do_build_copy_constructor): When copying an anonymous + union member loop around to handle nested anonymous unions. Use + the offset of the member relative to the outer structure, not the + union. - * method.c (build_assign_ref): Use build_member_call to invoke base - operator=, rather than build_modify_expr. And use - build_reference_type instead of TYPE_REFERENCE_TO. - (build_copy_constructor): Use TYPE_NESTED_NAME to identify the - basetype. +Tue Jul 29 21:17:29 1997 Jason Merrill - * decl2.c (grokfield): Don't complain about undefined local class - methods. + * call.c (resolve_args): New fn. + (build_new_function_call): Use it. + (build_object_call): Likewise. + (build_new_method_call): Likewise. - * class.c (finish_struct): Don't try to synthesize methods here. - * lex.c (do_pending_inlines): Instead, synthesize them here. - (init_lex): Initialize synth_obstack. - (cons_up_default_function): Stick synthesis request on - pending_inlines. +Mon Jul 28 16:02:36 1997 Jason Merrill -Fri Aug 26 12:24:14 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * call.c (build_over_call): tsubst all default parms from templates. - * call.c (build_method_call) [PCC_STATIC_STRUCT_RETURN]: Also - accept an RTL_EXPR in what we're about to use for the instance, - since anything which would end up with pcc_struct_return set - inside cplus_expand_expr. +Wed Jul 23 13:36:25 1997 Jason Merrill - * cp-tree.h (cons_up_default_function): Note change of prototype. + * decl.c (struct cp_function): Add static_labelno. + (push_cp_function_context): Save it. + (pop_cp_function_context): Restore it. -Thu Aug 25 23:05:30 1994 Gerald Baumgartner (gb@cs.purdue.edu) +Tue Jul 22 14:43:29 1997 Jason Merrill - * class.c (finish_struct): Undid change from Aug 21 testing - CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING. - * parse.y (left_curly): Ditto, undid change from Aug 21. - * decl.c (xref_tag): Undid change from Aug 21, set - CLASSTYPE_INTERFACE correctly, and added comments. + * typeck.c (build_component_ref_1): Convert from reference. -Thu Aug 25 00:36:31 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Jul 22 11:06:23 1997 Brendan Kehoe - Rework approach to synthesized methods; don't go through the parser - anymore. - * class.c (finish_struct): Use new synthesis approach. - * lex.c (cons_up_default_function): Now just creates declaration, - not code. - (largest_union_member): #if 0 out. - (default_assign_ref_body): Ditto. - (default_copy_constructor_body): Ditto. - * method.c (build_default_constructor): New function to synthesize X(). - (build_copy_constructor): Synthesize X(X&). - (build_assign_ref): Synthesize X::operator=(X&). - (build_dtor): Synthesize ~X(). + * parse.y (current_declspecs, prefix_attributes): Initialize to + NULL_TREE. - * error.c (cp_line_of): If we're dealing with an artificial - TYPE_DECL, look at the type instead. + * parse.y (initdcl0): Make sure CURRENT_DECLSPECS is non-nil + before we try to force it to be a TREE_LIST. + (decl): Make sure $1.t is non-nil. -Wed Aug 24 11:11:50 1994 Jason Merrill (jason@deneb.cygnus.com) +Sun Jul 20 11:53:07 1997 Jason Merrill - * init.c (sort_member_init): Check warn_reorder. - * decl2.c (lang_decode_option): Handle -W{no-,}reorder. + * pt.c (uses_template_parms): Handle template first-parse codes. - * cp-tree.h (CLASSTYPE_SOURCE_LINE): New macro. - * error.c (cp_line_of): Use CLASSTYPE_SOURCE_LINE for aggregates. - * class.c (finish_struct): Set CLASSTYPE_SOURCE_LINE. + * decl.c (cp_finish_decl): Only warn about user-defined statics. -Tue Aug 23 09:28:35 1994 Mike Stump +Fri Jul 18 17:56:08 1997 Jason Merrill - * error.c (dump_decl): Improve wording, so that error messages - dont't read template<, class foo>... + * pt.c (unify): Handle BOOLEAN_TYPE. -Mon Aug 22 15:30:51 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * cp-tree.h: Lose PARM_DEFAULT_FROM_TEMPLATE. + * pt.c (tsubst): Don't set it. + * call.c (build_over_call): Use uses_template_parms. - * parse.y (label_colon): Also match a TYPENAME as a label name, - since they may have declared a class by that name but have also - tried to have a local label under the same name. +Thu Jul 17 18:06:30 1997 Jason Merrill - * pt.c (coerce_template_parms): Call cp_error, not cp_error_at, - for the message so they know at what point it was instantiated. + * method.c (build_overload_nested_name): Use static_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 + have comdat linkage. + (start_function): Initialize static_labelno. -Sun Aug 21 23:07:35 1994 Gerald Baumgartner (gb@cs.purdue.edu) +Thu Jul 17 11:20:17 1997 Benjamin Kosnik - * class.c (finish_struct): Move setting of CLASSTYPE_INTERFACE and - CLASSTYPE_VTABLE_NEEDS_WRITING for signatures up to left_curly time. - * decl.c (xref_tag): Move setting of CLASSTYPE_INTERFACE and - CLASSTYPE_VTABLE_NEEDS_WRITING for signatures down to left_curly time. - * parse.y (left_curly): New final resting place for setting - CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING for signatures. + * class.c (finish_struct_methods): add check of warn_ctor_dtor_privacy + before "all member functions in class [] are private" - * class.c (finish_struct): Don't test for function/field name - conflicts in signatures, since all the fields are compiler-constructed. +Wed Jul 16 23:47:08 1997 Jason Merrill -Fri Aug 19 14:04:47 1994 Kung Hsu (kung@mexican.cygnus.com) + * lex.c (do_scoped_id): convert_from_reference. + * init.c (build_offset_ref): Likewise. - * method.c (build_overload_nested_name): in qualified name - mangling, the template with value instantiation will have numeric - at end and may mixed with the name length of next nested level. - Add a '_' in between. - * method.c (build_overload_name): ditto. - * method.c (build_overload_identifier): ditto. +Wed Jul 16 12:34:29 1997 Benjamin Kosnik -Thu Aug 18 16:24:43 1994 Mike Stump + * error.c (dump_expr): Check TREE_OPERAND before dump_expr_list. - * error.c (dump_decl): Handle NULL args. +Mon Jul 14 03:23:46 1997 Jason Merrill -Thu Sep 29 16:15:36 1994 Michael I Bushnell + * typeck.c (get_member_function_from_ptrfunc): Promote index + before saving it. - * g++.c: Rework last change so it's done like collect.c (and - gcc.c). +Sun Jul 13 00:11:52 1997 Jason Merrill -Wed Sep 14 10:17:27 1994 Michael I Bushnell + * tree.c (layout_basetypes): Move non-virtual destructor warning. + * decl.c (xref_basetypes): Remove non-virtual destructor warning. - * g++.c: Include in case `errno' is a macro - as permitted by ANSI C. +Sat Jul 12 12:47:12 1997 Jason Merrill -Thu Aug 18 12:48:09 1994 Mike Stump + * decl.c (grokdeclarator): Call add_defarg_fn for the function + type, too. + * lex.c (add_defarg_fn): Adjust. + (do_pending_defargs): Adjust. Don't skip the first parm. - * class.c (finish_struct): Move setting of CLASSTYPE_INTERFACE and - CLASSTYPE_VTABLE_NEEDS_WRITING up to left_curly time. - * decl.c (xref_tag): Move setting of CLASSTYPE_INTERFACE and - CLASSTYPE_VTABLE_NEEDS_WRITING down to left_curly time. - * parse.y (left_curly): New final resting place for setting - CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING. +Fri Jul 11 01:39:50 1997 Jason Merrill -Thu Aug 11 11:32:42 1994 H.J. Lu (hjl@nynexst.com) + * decl.c (build_enumerator): Global enumerators are also readonly. - * g++.c (main): Only decrement "added" and set "library" to - NULL when "library" != NULL. + * rtti.c (build_dynamic_cast_1): Renamed from build_dynamic_cast. + (build_dynamic_cast): Call it and convert_from_reference. -Sat Aug 13 00:14:52 1994 Jason Merrill (jason@deneb.cygnus.com) + * lex.c (add_defarg_fn): New fn. + (snarf_defarg): Don't add to defarg_types. + (do_pending_defargs): Lose defarg_types. All fns we process now + have defargs. + * decl.c (grokfndecl): Call add_defarg_fn. - * decl.c (grokdeclarator): Don't set TREE_PUBLIC on a function decl - just because its class has a known interface. - (decls_match): Deal with new format of template parms. + * Makefile.in (CONFLICTS): Expect 18 s/r conflicts. + * cp-tree.def: Add DEFAULT_ARG. + * spew.c (yylex): Call snarf_defarg as appropriate. + * parse.y: New tokens DEFARG and DEFARG_MARKER. + (defarg_again, pending_defargs, defarg, defarg1): New rules. + (structsp): Use pending_defargs. + (parms, full_parm): Use defarg. + * lex.c (init_lex): Initialize inline_text_firstobj. + (do_pending_inlines): Never pass the obstack to feed_input. + (process_next_inline): Call end_input instead of restore_pending_input. + (clear_inline_text_obstack, reinit_parse_for_expr, do_pending_defargs, + finish_defarg, feed_defarg, snarf_defarg, maybe_snarf_defarg): New fns. + * input.c (end_input): New fn. + (sub_getch): At the end of some fed input, just keep returning EOF + until someone calls end_input. + Remove 'obstack' field from struct input_source. + * decl.c (grokparms): Handle DEFAULT_ARG. + (replace_defarg): New fn. + * cp-tree.h (DEFARG_LENGTH, DEFARG_POINTER): New macros. - * lex.c (cons_up_default_function): Don't play with TREE_PUBLIC and - DECL_EXTERNAL here. +Wed Jul 9 13:44:12 1997 Jason Merrill -Fri Aug 12 01:55:15 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (implicit_conversion): If nothing else works, try binding + an rvalue to a reference. - * decl.c (pushtag): SET_DECL_ARTIFICIAL on gratuitous typedefs. - (xref_defn_tag): Ditto. - (pushdecl): Only allow artificial typedefs to be shadowed. +Wed Jul 9 13:04:38 1997 Geoffrey Noer - * init.c (emit_base_init): Pass the right binfos to - expand_aggr_init_1. + * decl.c (init_decl_processing): fix Jun 30 patch -- move + ifndef for Cygwin32 to include SIGSEGV. - * class.c (delete_duplicate_fields_1): Make it work right. - (finish_struct): Catch function/field name conflict. +Thu Jul 3 01:44:05 1997 Jason Merrill - * decl2.c (check_classfn): Pass the function to cp_error, not just - the name. + * class.c (finish_struct_1): Only complain about pointers without + copy stuff if there are any constructors. - * init.c (sort_member_init): Warn when order of member initializers - does not match order of member declarations. - (emit_base_init): Call expand_aggr_init_1 with LOOKUP_PROTECT. + * rtti.c (build_dynamic_cast): Call complete_type on the types. - * error.c (dump_expr): Handle lists of functions. + * decl.c (grokfndecl): If the function we chose doesn't actually + match, die. - * decl.c (start_function): #pragma interface only affects functions - that would otherwise be static. - (finish_decl): Don't warn about an unused variable if it has both - constructor and destructor, since the 'resource allocation is - initialization' idiom is relatively common. + * decl2.c (grokclassfn): Don't specify 'const int' for the + artificial destructor parm. - * typeck.c (comp_target_types): Don't handle TEMPLATE_TYPE_PARMs. - (comp_target_parms): Ditto. - (compparms): Never consider default parms. - (common_base_type): Don't choose a virtual baseclass if there is a - more derived class in common. - (build_conditional_expr): If pedantic, pedwarn about conversion to - common base in conditional expr. + * pt.c (type_unification): If we are called recursively, nothing + decays. - * class.c (instantiate_type): Handle template instantiation better. +Mon Jun 30 17:53:21 1997 Geoffrey Noer - * typeck.c (convert_arguments): Don't try to get tricky and convert - to int directly when PROMOTE_PROTOTYPES is set, as it breaks - user-defined conversions. + * 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 + tools. - * lex.c (check_for_missing_semicolon): Also give error at end of - file. +Mon Jun 30 14:50:01 1997 Jason Merrill - * call.c (build_method_call): Don't promote arrays to pointers here. + * tree.c (mapcar, case CALL_EXPR): Handle all the parse node data. - * typeck.c (convert_arguments): Don't require the actual parameter - to be of a complete type if the formal parameter is a reference. +Fri Jun 27 15:18:49 1997 Jason Merrill -Thu Aug 11 15:21:40 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck2.c (store_init_value): Always return the value if our + type needs constructing. - * decl.c (grokdeclarator): Soften 'static' on member function error - to pedwarn. + * method.c (hack_identifier): Convert class statics from + reference, too. - * init.c (build_new): Don't automatically save rval. - (build_offset_ref): Do field lookup with proper basetype_path. +Thu Jun 26 11:44:46 1997 Jason Merrill -Thu Aug 11 12:46:54 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * Make-lang.in (cplib2.ready): Add $(LANGUAGES) dependency. - * errfn.c (cp_silent): Declare to mark when we should avoid - emitting warnings and errors. - (cp_error): Check it. - (cp_warning): Likewise. - (cp_pedwarn): Likewise. - (cp_compiler_error): Likewise. - (cp_error_at): Likewise. - (cp_warning_at): Likewise. - (cp_pedwarn_at): Likewise. - * call.c (compute_conversion_costs): Set CP_SILENT when we start - out, and make sure we turn it off before we leave. +Thu Jun 19 16:49:28 1997 Mike Stump -Thu Aug 11 00:02:54 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (c_expand_return): Make sure we clean up temporaries at + the end of return x; - * decl2.c (grok_array_decl): Try computing *(A+B) if neither - argument is obviously an array. +Thu Jun 19 12:28:43 1997 Brendan Kehoe -Wed Aug 10 15:32:04 1994 Jason Merrill (jason@deneb.cygnus.com) + * lex.c (check_for_missing_semicolon): Also check for CV_QUALIFIER. - * typeck.c (c_expand_start_case): Do cleanups here. +Tue Jun 17 18:35:57 1997 Mike Stump - * parse.y (xcond): Do bool conversion here, too. - (simple_stmt, SWITCH case): Don't do cleanups here. + * except.c (expand_builtin_throw): Add support + -fno-sjlj-exceptions -fPIC exception handling on the SPARC. - * decl.c (duplicate_decls): Don't treat builtins that have been - explicitly declared specially. +Mon Jun 16 01:24:37 1997 Jason Merrill -Tue Aug 9 01:16:09 1994 Jason Merrill (jason@deneb.cygnus.com) + * repo.c (extract_string): Null-terminate. - * tree.c (make_deep_copy): Support copying pointer, reference, - function, array, offset and method types. + * cp-tree.h (TI_SPEC_INFO): New macro. + (CLASSTYPE_TI_SPEC_INFO): New macro. + * pt.c (push_template_decl): Correctly determine # of template parms + for partial specs. - * decl.c (init_decl_processing): Mark exit and abort as - BUILT_IN_NONANSI so that duplicate_decls is kinder about - redeclaration. - (duplicate_decls): Don't give two errors for redeclaring a C - function with the same parms but a different return type. + * call.c (compare_ics): Really fix 'this' conversions. - * parse.y (paren_cond_or_null): Do cleanup and bool conversion here. - (condition): Instead of here. - (simple_stmt, SWITCH case): Also do cleanup here. + * pt.c (do_decl_instantiation): Don't crash on explicit inst of + non-template fn. - * decl2.c (finish_anon_union): Only break out FIELD_DECLs. + * pt.c (push_template_decl): Complain about mismatch in # of + template parms between a class template and a member template. - * call.c (build_method_call): Don't throw away the side effects of - the object in a call to a non-existent constructor. - * parse.y (primary): Ditto. +Sun Jun 15 02:38:20 1997 Jason Merrill - * method.c (build_decl_overload): Oop. + * method.c (synthesize_method): You can't call + 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. - * decl2.c (lang_decode_option): Deal with flag_no_nonansi_builtin, - warn about uselessness of specifying -fansi-overloading. +Thu Jun 12 17:35:28 1997 Jason Merrill - * method.c (build_decl_overload): Treat any non-member new with one - parameter as __builtin_new. + * method.c (synthesize_method): Remove July 30 change to never set + DECL_INLINE if at_eof. - * decl.c (init_decl_processing): Setup built-in meanings of exit, - _exit and abort. +Thu Jun 12 15:25:08 1997 Mike Stump -Mon Aug 8 15:03:30 1994 Jason Merrill (jason@deneb.cygnus.com) + * xref.c (GNU_xref_member): Ensure that the node has a + decl_lang_specific part before checking DECL_FRIEND_P. - * error.c (dump_readonly_or_volatile): Put a space between const and - volatile if both apply. +Thu Jun 12 12:36:05 1997 Jason Merrill - * init.c (perform_member_init): Clean up after this initialization. - (emit_base_init): Clean up after each base init, not after all have - been done. - (expand_aggr_vbase_init_1): Clean up after this init. + * pt.c (instantiate_class_template): Diagnose non-class types used + as bases. -Sun Aug 7 14:55:05 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Jun 11 17:33:40 1997 Jason Merrill - * call.c (build_method_call): Deal with destroying references. + * typeck.c (build_conditional_expr): Use convert_for_initialization + instead of convert_and_check. - * parse.y (condition): Do bool_truthvalue_conversion here. - (paren_expr_or_null): And here. - (simple_if): Not here. - (simple_stmt): Or here. +Wed Jun 11 12:31:33 1997 Brendan Kehoe -Sat Aug 6 22:29:45 1994 Jason Merrill (jason@deneb.cygnus.com) + * parse.y (typespec): Don't pedwarn for typeof. - * parse.y (paren_expr_or_null): Wrap the expression in a - CLEANUP_POINT_EXPR. - (condition): Ditto. +Tue Jun 10 00:22:09 1997 Jason Merrill -Sat Aug 6 19:46:37 1994 Rohan Lenard (rjl@easams.com.au) + * repo.c (finish_repo): Only check changes if we would write a + repo file. - * call.c (build_scoped_method_call): Fix error message when - destructor call refers to a nonexistent type. + * call.c (compare_ics): Fix handling of 'this' conversions. -Sat Apr 16 22:43:30 1993 Gerald Baumgartner (gb@cs.purdue.edu) + * pt.c (do_decl_instantiation): Support static data too. Rename + from do_function_instantiation. + * cp-tree.h: Adjust. + * parse.y: Adjust. - * lex.h (rid): Deleted RID_RAISES, it's never used. - Moved RID_PUBLIC, RID_PRIVATE, RID_PROTECTED, RID_EXCEPTION, - RID_TEMPLATE and RID_SIGNATURE to the end of the enumeration, - they don't need to be touched in `grokdeclarator.' - (RID_LAST_MODIFIER): Defined macro to be RID_MUTABLE. + * repo.c (extract_string): New fn. + (get_base_filename): Use it. + (init_repo): Compare old args with current args. - * decl.c (grokdeclarator): Use RID_LAST_MODIFIER instead of - RID_MAX as loop limit for finding declaration specifiers. +Mon Jun 9 14:25:30 1997 Mike Stump -Sat Apr 3 21:59:07 1993 Gerald Baumgartner (gb@cs.purdue.edu) + * Makefile.in, Make-lang.in: Protect C-ls with a comment + character, idea from Paul Eggert . - * lex.c (debug_yytranslate): Moved to parse.y since it needs to - access `yytname,' which is static in parse.c. +Mon Jun 9 01:52:03 1997 Jason Merrill -Fri Apr 2 23:36:57 1993 Gerald Baumgarnter (gb@cs.purdue.edu) + * typeck.c (c_expand_return): Be more persistent in looking for + returned temps. - * cp-tree.h (GNU_xref_ref): Fixed typo in extern declaration, it - was `GNU_xref_def' instead of `GNU_xref_ref.' + * cvt.c (build_up_reference): Use NOP_EXPR for switching from + pointer to reference. -Fri Aug 5 14:20:16 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (build_vbase_path): Don't do anything if PATH has no steps. - * pt.c (do_function_instantiation): Don't set TREE_PUBLIC and - DECL_EXTERNAL on 'extern' instantiations; wait until EOF to do that. - (do_type_instantiation): Ditto. +Sun Jun 8 03:07:05 1997 Jason Merrill - * decl2.c (import_export_inline): Decides at EOF what an inline's - linkage should be. - (finish_file): Call it. + * init.c (build_member_call, build_offset_ref): + Use do_scoped_id instead of do_identifier. - * decl.c (start_function): Don't rely on the settings of TREE_PUBLIC - and DECL_EXTERNAL from do_*_instantiation. Only set - DECL_DEFER_OUTPUT on inlines whose linkage might actually change. - (finish_function): Use DECL_DEFER_OUTPUT to decide which inlines to - mark for later consideration, rather than DECL_FUNCTION_MEMBER_P. + * cvt.c (convert): Remove bogosity. -Fri Aug 5 01:12:20 1994 Mike Stump +Sat Jun 7 20:50:17 1997 Brendan Kehoe - * class.c (get_class_offset_1, get_class_offset): New routine to - find the offset of the class where a virtual function is defined, - from the complete type. - * class.c (modify_one_vtable, fixup_vtable_deltas): Use - get_class_offset instead of virtual_offset as get_class_offset will - always provide the right answer. - * tree.c (virtual_offset): Remove. It only ever worked some of the - time. + * cvt.c (build_up_reference): Do checks of ARGTYPE and + TARGET_TYPE before trying to use get_binfo. -Tue Aug 2 12:44:21 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Jun 6 17:36:39 1997 Jason Merrill - * call.c (build_method_call): Put back unary_complex_lvalue call - that I thought was redundant. + * cvt.c (build_up_reference): Call get_binfo to get access control. - * typeck.c (c_expand_return): Fix a case I missed before. + * decl2.c (import_export_decl): If we don't support weaks, leave + statics undefined. -Sun Jul 31 17:54:02 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Jun 6 15:55:49 1997 Mike Stump - * pt.c (unify): Strip cv-quals from template type arguments (when - 'const T*' is matched to 'const char*', that does not mean that T is - 'const char'). + * except.c (expand_builtin_throw): Add support for machines that + cannot access globals after throw's epilogue when + -fno-sjlj-exceptions is used. -Fri Jul 29 01:03:06 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Jun 5 16:28:43 1997 Jason Merrill - * pt.c (do_type_instantiation): Instantiate nested TAGS, not - typedefs. Third time's the charm? + * parse.y: 'std::' becomes '::'. + * lex.c (real_yylex): Remove 'namespace' warning. + * init.c (build_member_call): Ignore 'std::'. + (build_offset_ref): Likewise. + * decl2.c (do_using_directive): Ignore 'using namespace std;'. + (do_toplevel_using_decl): Ignore 'using std::whatever'. + * decl.c (push_namespace): Just sorry. + (pop_namespace): Nop. + (init_decl_processing): Declare std namespace. - * parse.y (template_parm): Support default template parms. - * pt.c (process_template_parm): Ditto. - (end_template_parm_list): Ditto. - (coerce_template_parms): Ditto. - (mangle_class_name_for_template): Ditto. - (push_template_decls): Ditto. - (unify): Ditto. - * method.c (build_overload_identifier): Ditto. - * error.c (dump_decl): Ditto. +Tue Jun 3 18:08:23 1997 Jason Merrill -Wed Jul 27 17:47:00 1994 Jason Merrill (jason@deneb.cygnus.com) + * search.c (push_class_decls): A name which ambiguously refers to + several instantiations of the same template just refers to the + template. - * pt.c (do_type_instantiation): Only instantiate nested *classes*. +Tue Jun 3 12:30:40 1997 Benjamin Kosnik -Tue Jul 26 13:22:40 1994 Jason Merrill (jason@deneb.cygnus.com) + * 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 + MAX_VAL). - * search.c (note_debug_info_needed): Also emit debugging information - for the types of fields. +Mon Jun 2 17:40:56 1997 Jason Merrill -Mon Jul 25 00:34:44 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (build_component_ref): Only call mark_used on a decl. - * pt.c (lookup_template_class): Pass 'template' to - coerce_template_parms instead of 'in_decl', since it's a more - meaningful context. +Thu May 29 15:54:17 1997 Brendan Kehoe - * typeck.c (c_expand_return): Make sure any cleanups for the return - expression get run. - (build_c_cast): Use CONVERT_EXPR for conversion to void. + * typeck.c (build_c_cast): Make the check for a ptr to function + more specific before possible default_conversion call. - * pt.c (do_type_instantiation): Also instantiate nested types. +Thu May 29 13:02:06 1997 Mike Stump - * typeck.c (convert_for_assignment): Don't die when comparing - pointers with different levels of indirection. + * except.c (expand_exception_blocks): Simplify and fix and make + sure we don't end a region in a sequence, as expand_end_bindings + doesn't like it. - * decl.c (grokdeclarator): The sub-call to grokdeclarator for - class-local typedefs sets DECL_ARGUMENTS, so we need to clear it - out. +Wed May 28 17:08:03 1997 Mike Stump - * decl2.c (finish_anon_union): Don't die if the union has no - members. + * except.c (init_exception_processing): Mark terminate as not + returning so that the optimizer can optimize better. - * decl.c (grokdeclarator): Undo changes to declspecs when we're done - so that 'typedef int foo, bar;' will work. +Tue May 27 19:49:19 1997 Mike Stump - * decl2.c (finish_file): Don't call expand_aggr_init for - non-aggregates. + * cvt.c (convert): Don't do any extra work, if we can avoid it + easily. -Mon Jul 25 00:03:10 1994 Teemu Torma (tot@trema.fi) +Tue May 27 18:21:47 1997 Mike Stump - * decl.c (finish_function): We can't inline constructors and - destructors under some conditions with -fpic, but don't unset - DECL_INLINE. + * *.[chy]: Change cp_convert to ocp_convert, change convert to + cp_convert. convert is now reserved for the backend, and doesn't + have the semantics a frontend person should ever want. -Mon Jul 25 00:03:10 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri May 23 10:58:31 1997 Jason Merrill - * typeck.c (build_object_ref): Make sure 'datum' is a valid object. + * lang-specs.h: Define __EXCEPTIONS if exceptions are enabled. + Lose -traditional support. -Sun Jul 24 14:19:31 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu May 22 15:41:28 1997 Jason Merrill - * class.c (finish_struct): Don't set DECL_FIELD_BITPOS on - non-fields. - (finish_struct_methods): Use copy_assignment_arg_p. + * rtti.c (get_tinfo_var): Use TYPE_PRECISION (sizetype). - * cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead - of giving an error. + * parse.y (self_reference): Do it for templates, too. + * class.c (pushclass): Don't overload_template_name; the alias + generated by build_self_reference serves the same purpose. - * typeck.c (build_binary_op_nodefault): Don't set result_type if we - don't know how to compare the operands. + * tree.c (list_hash): Make static, take more args. + (list_hash_lookup): Likewise. + (list_hash_add): Make static. + (list_hash_canon): Lose. + (hash_tree_cons): Only build a new node if one isn't already in the + hashtable. + (hash_tree_chain): Use hash_tree_cons. + * cp-tree.h: Adjust. + * decl.c (grokfndecl): Just check IDENTIFIER_GLOBAL_VALUE instead + of calling lookup_name. - * decl.c (grokdeclarator): Avoid seg fault when someone uses '__op' - as a declarator-id in their program. Like the Linux headers do. - Arrgh. +Wed May 21 18:24:19 1997 Jason Merrill - * tree.c (lvalue_p): Treat calls to functions returning objects by - value as lvalues again. + * pt.c (instantiate_class_template): TYPE_VALUES for an enum + doesn't refer to the CONST_DECLs. - * typeck.c (build_component_addr): Use convert_force to convert the - pointer in case the component type is also a private base class. +Tue May 20 21:09:32 1997 Bob Manson - * search.c (get_matching_virtual): Fix bogus warning of overloaded - virtual. + * rtti.c (get_tinfo_var): Either INT_TYPE_SIZE or 32, whichever + is bigger. + (expand_class_desc): Convert the last argument to a sizetype. - * pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created - TYPE_DECL to fix bogus shadowing warnings. +Tue May 20 13:55:57 1997 Brendan Kehoe -Fri Jul 22 01:15:32 1994 Jason Merrill (jason@deneb.cygnus.com) + * gxx.gperf (__complex, __complex__, __imag, __imag__, __real, + __real__): Add reswords. + * hash.h: Regenerate. + * lex.h (rid): Add RID_COMPLEX. + (RID_LAST_MODIFIER): Set to RID_COMPLEX. + * lex.c (init_lex): Add building of RID_COMPLEX. + (real_yylex): General cleanup in line with what c-lex.c also has, + sans the cruft for traditional; add handling of SPEC_IMAG, complex + types, and imaginary numeric constants. + * parse.y (REALPART, IMAGPART): Add tokens. + (unary_expr): Add REALPART and IMAGPART rules. + * cp-tree.h (complex_{integer,float,double,long}_type_node): Declare. + * decl.c (complex_{integer,float,double,long}_type_node): Define + types. + (init_decl_processing): Set up the types. + (grokdeclarator): Add handling of RID_COMPLEX. Set and use + DEFAULTED_INT instead of EXPLICIT_INT when we default to int type. + * call.c (build_new_op): Add REALPART_EXPR and IMAGPART_EXPR cases. + * cvt.c (cp_convert): Handle COMPLEX_TYPE. + * error.c (dump_type_prefix, dump_type, dump_type_suffix): Add + COMPLEX_TYPE case. + * method.c (build_overload_name): Add handling of the different + COMPLEX_TYPEs, prefixing them with `J'. + * pt.c (process_template_parm): Don't let them use a COMPLEX_TYPE + as a template parm. + (uses_template_parms, tsubst, unify): Add COMPLEX_TYPE case. + * tree.c (lvalue_p): Add REALPART_EXPR and IMAGPART_EXPR cases. + (mapcar): Handle COMPLEX_CST. + * typeck.c (build_binary_op_nodefault): Handle COMPLEX_TYPE. + (common_type): Add code for complex types. + (build_unary_op): Add REALPART_EXPR and IMAGPART_EXPR cases. + (convert_for_assignment): Likewise. + (mark_addressable): Add REALPART_EXPR and IMAGPART_EXPR cases. + +Mon May 19 12:26:27 1997 Jason Merrill + + * pt.c (tsubst): Don't pass the MINUS_EXPR for an array domain to + tsubst_expr, as it might try to do overload resolution. + +Sat May 17 10:48:31 1997 Jason Merrill + + * pt.c (instantiate_class_template): Oops. + +Fri May 16 14:23:57 1997 Jason Merrill + + * cp-tree.def: Add TAG_DEFN. + * pt.c (tsubst_enum): New fn. + (instantiate_class_template): Use it. + (tsubst_expr): Support TAG_DEFN. + (tsubst): Support local enums. + (tsubst_copy): Likewise. + * decl.c (finish_enum): Likewise. + (start_enum): If this is a local enum, switch to permanent_obstack. + +Wed May 14 19:08:28 1997 Mike Stump + + * decl.c (store_parm_decls): Set last_parm_cleanup_insn here. + (finish_function): Put the base init code for constructors just + after the parm cleanup insns. + (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 - * init.c (expand_aggr_init_1): const and volatile mismatches do not - prevent a TARGET_EXPR from initializing an object directly. + * pt.c (tsubst_copy): Handle BIT_NOT_EXPR. -Tue Jul 19 17:55:37 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed May 7 11:17:59 1997 Brendan Kehoe - * cvt.c (build_up_reference): Allow building up references to - `this', don't warn about making references to artificial variables - (like `this'). + * method.c (emit_thunk) [ASM_OUTPUT_MI_THUNK]: Build up the RTL + for THUNK_FNDECL before we switch to temporary allocation. - * tree.c (lvalue_p): `this' is not an lvalue. +Mon May 5 14:46:53 1997 Jason Merrill - * call.c (build_method_call): Accept using a typedef name (or - template type parameter) for explicit destructor calls. + * call.c (build_new_op): Handle null arg2 for ?:. -Wed Jul 13 03:57:54 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu May 1 18:26:37 1997 Mike Stump - * method.c (hack_identifier): Put back old code so lists of - non-functions will be handled properly. + * except.c (expand_exception_blocks): Ensure that we flow through + the end of the exception region for the exception specification. + Move exception region for the exception specification in, so that + it doesn't protect the parm cleanup. Remove some obsolete code. + * decl.c (store_parm_decls): Likewise. + (finish_function): Likewise. - * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now - defined in the language-independent tree.h. +Tue Apr 29 15:38:54 1997 Jason Merrill - * tree.c (count_functions): Avoid bogus warning when compiling this - function. + * init.c (build_new): Fix nothrow handling. -Mon Jul 11 18:37:20 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Apr 29 14:29:50 1997 Brendan Kehoe - * decl.c (grok_reference_init): Always save the initializer of a - reference. + * init.c (emit_base_init): Don't warn about the initialization + list for an artificial member. -Fri Jul 8 17:41:46 1994 Mike Stump +Fri Apr 25 17:47:59 1997 Brendan Kehoe - * decl.c (cplus_expand_expr_stmt): Wrap statement expressions inside - CLEANUP_POINT_EXPRs so that the stack slots can be reused. - (disabled for now) + * expr.c (do_case): Handle !START case for the error msg. -Fri Jul 8 12:59:38 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Apr 25 11:55:23 1997 Jason Merrill - * method.c (hack_identifier): Fix for new overloading. + * decl2.c, lang-options.h: New option -Weffc++. + * class.c, decl.c, init.c, typeck.c: Move Effective C++ warnings + to -Weffc++. - * typeck.c (build_binary_op_nodefault): Don't mess with division by - zero. + * decl2.c (finish_prevtable_vardecl): Change NO_LINKAGE_HEURISTICS + to MULTIPLE_SYMBOL_SPACES. -Fri Jul 8 13:20:28 1994 Gerald Baumgartner (gb@cs.purdue.edu) +Wed Apr 23 18:06:50 1997 Jason Merrill - * decl2.c (finish_file): Only call walk_sigtables, if - flag_handle_signatures is turned on, don't waste time otherwise. + * method.c (emit_thunk, generic case): Set current_function_is_thunk. -Fri Jul 8 02:27:41 1994 Jason Merrill (jason@deneb.cygnus.com) + * method.c (emit_thunk, macro case): Set up DECL_RESULT. - * decl.c (push_overloaded_decl): Don't create overloads of one when - shadowing a class type. - * typeck.c (build_x_function_call): Complain about overloads of one. + * 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, + don't set DECL_RESULT, set DECL_ARTIFICIAL. + (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC. - * decl.c (grokdeclarator): Don't try to treat a char* as a tree. - (grokdeclarator): Fix setting of TREE_STATIC. - (start_decl): Clear DECL_IN_AGGR_P after calling duplicate_decls. +Wed Apr 23 14:43:06 1997 Mike Stump -Thu Jul 7 22:20:46 1994 Gerald Baumgartner (gb@andros.cygnus.com) + * init.c (init_decl_processing): Add supoprt for setjmp/longjmp based + exception handling. + * except.c (init_exception_processing): Likewise. + (expand_end_catch_block): Likewise. + (expand_exception_blocks): Likewise. + (expand_throw): Likewise. + * exception.cc (__default_terminate): Likewise. - * cp-tree.h (walk_sigtables): Created extern declaration. - * decl2.c (walk_sigtables): Created function, patterned after - walk_vtables, even though we only need it to write out sigtables. - (finish_sigtable_vardecl): Created function. - (finish_vtable_vardecl): Changed 0 to NULL_PTR. - (finish_file): Call walk_sigtables. + * init.c (perform_member_init): Use new method of expr level + cleanups, instead of cleanups_this_call and friends. + (emit_base_init): Likewise. + (expand_aggr_vbase_init_1): Likewise. + (expand_vec_init): Likewise. + * decl.c (cp_finish_decl): Likewise. + (expand_static_init): Likewise. + (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. - * sig.c (build_signature_table_constructor): Mark class member - function pointed to from signature table entry as addressable. + * decl.c (maybe_build_cleanup_1): We no longer have to unsave, as + we know it will be done later by the backend. -Thu Jul 7 13:39:37 1994 Jason Merrill (jason@deneb.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 - * decl.c (start_decl): Check new decl of static member variable - against the declaration in the class here. - (grokvardecl): Instead of here. + * tree.c (varargs_function_p): New fn. + * method.c (emit_thunk): Replace broken generic code with code to + generate a heavyweight thunk function. - * class.c (prepare_fresh_vtable): Call import_export_vtable if not - -fvtable-thunks. - (build_vtable): Ditto. +Tue Apr 22 02:45:18 1997 Jason Merrill - * decl2.c (import_export_vtable): Move logic for deciding the - interface of a template class from here. - (import_export_template): To here. - (finish_vtable_vardecl): Call import_export_template before - import_export_vtable. + * pt.c (process_template_parm): pedwarn about floating-point parms. -Wed Jul 6 20:25:48 1994 Mike Stump + * decl.c (grokdeclarator): inline no longer implies static. - * except.c (init_exception_processing): Setup interim_eh_hook to - call lang_interim_eh. - * except.c (do_unwind): Propagate throw object value across - stack unwinding. - * except.c (saved_throw_value): Used to hold the value of the object - being thrown. It is always a reference to the real value. - * except.c (expand_start_catch_block): Add handling for the - value of the exception object. - * except.c (expand_start_catch_block): Add handler for the handler, - so that throws inside the handler go to the outer block. - * except.c (expand_end_catch_block): Ditto. - * parse.y (handler_args): Use parm instead, as the other doesn't yet - handle references correctly. + * spew.c (yylex): Always return the TYPE_DECL if we got a scope. -Wed Jul 6 17:55:32 1994 Per Bothner (bothner@kalessin.cygnus.com) +Mon Apr 21 15:42:27 1997 Jason Merrill - * decl2.c (mark_vtable_entries): If -ftable-thunks, set the - vtable entry properly to abort. + * class.c (check_for_override): The signature of an overriding + function is not changed. -Tue Jul 5 14:07:54 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_over_call): Move setting of conv into the loop. + Note: this change, along with the related changes of the 18th thru + the 20th of April, fix an infinite loop problem in conversions. - * typeck.c (build_binary_op_nodefault): Downgrade division by zero - errors to warnings. +Sun Apr 20 16:24:29 1997 Jason Merrill - * call.c (build_overload_call_real): Handle fnname being a list of - functions. - * typeck.c (build_x_function_call): Pass list of functions to - build_overload_call, not just the name. - * tree.c (count_functions): Complain when called for invalid - argument. + * call.c (build_user_type_conversion_1): Really ignore rvalue + conversions when looking for a REFERENCE_TYPE. - * decl.c (grokdeclarator): Fix settings of TREE_STATIC, TREE_PUBLIC - and DECL_EXTERNAL on static members and initialized const members. - * decl2.c (grokfield): Reflect this change. + * cvt.c (build_up_reference): Eviscerate, use build_unary_op. + * cp-tree.h (TREE_REFERENCE_EXPR): #if 0. + * typeck.c (decay_conversion): Don't set TREE_REFERENCE_EXPR. + (build_unary_op): Likewise. + * call.c (build_over_call): See through a CONVERT_EXPR around the + ADDR_EXPR for on a temporary. + * typeck.c (c_expand_return): See through a CONVERT_EXPR around + the ADDR_EXPR for a local variable. -Fri Jul 1 09:35:51 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Apr 18 12:11:33 1997 Jason Merrill - * parse.y (init): ANSI C++ does not forbid { }. + * call.c (build_user_type_conversion_1): If we're trying to + convert to a REFERENCE_TYPE, only consider lvalue conversions. + (build_new_function_call): Print candidates. + (implicit_conversion): Try a temp binding if the lvalue conv is BAD. + (reference_binding): Binding a temporary of a reference-related type + is BAD. -Thu Jun 30 00:35:22 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Apr 17 14:37:22 1997 Brendan Kehoe - * decl2.c (lang_decode_option): Set warn_nonvdtor along with -Wall. - warn_nonvdtor defaults to off. + * inc/typeinfo (type_info::before): Add cv-qualifier-seq. + * tinfo2.cc (type_info::before): Likewise. - * class.c (instantiate_type): Use comptypes rather than relying on - types to satisfy ==. +Mon Apr 14 12:38:17 1997 Jason Merrill - * decl.c (start_function): Set DECL_DEFER_OUTPUT on all inlines that - might be static. + * call.c (implicit_conversion): Oops. - * tree.c (build_cplus_new): Never build WITH_CLEANUP_EXPRs. +Fri Apr 11 02:18:30 1997 Jason Merrill - * decl.c (grok_reference_init): Deal with ADDR_EXPRs of TARGET_EXPRs. + * call.c (implicit_conversion): Try to find a reference conversion + before binding a const reference to a temporary. - * cvt.c (cp_convert): Pass 0 to with_cleanup_p arg of - build_cplus_new. +Wed Apr 2 12:51:36 1997 Mike Stump -Wed Jun 29 22:31:09 1994 Jason Merrill (jason@deneb.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 - * decl2.c (finish_file): Maybe consider static inlines multiple - times, in case they reference each other. + * parse.y (left_curly): Avoid trying to use any fields of + error_mark_node, as there aren't any. -Tue Jun 28 11:58:38 1994 Gerald Baumgartner (gb@cs.purdue.edu) +Thu Mar 13 16:33:22 1997 Jason Merrill - * class.c (finish_struct): Don't `cons_up_default_function's - for signatures. - (finish_struct): Handle an empty method_vec correctly. + * lex.c (do_identifier): Avoid breaking on overloaded methods + as default arguments. - * decl.c (grokdeclarator): Don't warn about a signature being - empty in a signature pointer declaration if we only saw a - forward declaration of the signature. Changed `warning's into - `cp_warning's. +Wed Mar 12 13:55:10 1997 Hans-Peter Nilsson - * sig.c (build_sigtable): Don't die if a null signature table - constructor is returned. - (build_signature_pointer_constructor): If the signature table - constructor is null, the _sptr field is set to a null pointer - and cast to the appropriate type. Make copies of all null - pointers so that the type null_pointer_node doesn't get changed. - (build_signature_table_constructor): Added comments. + * call.c (add_template_candidate): Initialize the variable "dummy". - * sig.c (build_signature_pointer_constructor): Complain if we - try to assign to/initialize a signature pointer/reference of - an undefined signature. +Mon Mar 10 15:13:14 1997 Brendan Kehoe -Mon Jun 27 14:05:16 1994 Gerald Baumgartner (gb@cs.purdue.edu) + * decl.c (start_decl): Make sure TYPE isn't an error_mark_node + before we try to use TYPE_SIZE and TREE_CONSTANT on it. - * typeck2.c (store_init_value): Don't be pedantic about - non-constant initializers of signature tables/pointers/references. +Fri Mar 7 13:19:36 1997 Brendan Kehoe -Fri Jun 24 16:49:41 1994 Gerald Baumgartner (gb@cs.purdue.edu) + * cp-tree.h (comp_ptr_ttypes, more_specialized): Add decl. + (debug_binfo): Delete decl, not needed. - * decl.c (grokdeclarator): If we are grokking an opaque typedef - in a signature, don't complain about it begin static. + * tree.c (fnaddr_from_vtable_entry, function_arg_chain, + promotes_to_aggr_type): Delete fns. + * cp-tree.h (FNADDR_FROM_VTABLE_ENTRY, + SET_FNADDR_FROM_VTABLE_ENTRY, FUNCTION_ARG_CHAIN, + PROMOTES_TO_AGGR_TYPE): Delete alternates to #if 1. -Wed Jun 29 16:44:45 1994 Mike Stump + * decl.c (pending_invalid_xref{,_file,_line}): Delete unused vars. - Fixes a problem of the this pointer being wrong in virtual calls to - methods that are not overridden in more derived classes. + * friend.c (is_friend_type): Delete fn. + * cp-tree.h (is_friend_type): Delete decl. - * class.c (fixup_vtable_delta): New routine. It will fixup the - delta entries in vtables, wheever they need updating. - * class.c (finish_struct): Call the new routine for all virtual - bases, as they can have different offsets, than those used in base - classes that we derive our vtable from. + * decl.c (original_result_rtx, double_ftype_double, + double_ftype_double_double, int_ftype_int, long_ftype_long, + float_ftype_float, ldouble_ftype_ldouble, last_dtor_insn): Make static. + * typeck.c (original_result_rtx, warn_synth): Delete extern decls. -Tue Jun 28 23:49:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (push_overloaded_decl{,_top_level}): Make static, adding + fwd decls. + * cp-tree.h (push_overloaded_decl{,_top_level}): Delete decls. - * typeck.c (build_binary_op): Use the types before default - conversions in the error message. + * decl.c (pushdecl_nonclass_level): #if 0, unused. + * cp-tree.h (pushdecl_nonclass_level): #if 0 decl. - * *.c: Use c_build_type_variant instead of build_type_variant where - the type might be an array. + * lex.c (reinit_lang_specific): #if 0, unused. + * cp-tree.h (reinit_lang_specific): #if 0 decl. - * call.c (build_method_call): Call build_type_variant and - build_reference_type in the right order. - * decl.c (record_builtin_type): Ditto. + * decl.c (revert_static_member_fn): Make static, adding fwd decl. + * cp-tree.h (revert_static_member_fn): Delete decl. -Wed Jun 29 16:58:53 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (root_lang_context_p): Delete fn. + * cp-tree.h (root_lang_context_p): Delete decl. - * call.c (build_method_call): Call build_type_variant and - build_reference_type in the right order. - * decl.c (record_builtin_type): Ditto. + * decl.c (set_current_level_tags_transparency): #if 0, unused. + * cp-tree.h (set_current_level_tags_transparency): #if 0 decl. -Tue Jun 28 23:49:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * lex.c (set_vardecl_interface_info): Make static. + * cp-tree.h (set_vardecl_interface_info): Delete decl. - * typeck.c (build_binary_op): Use the types before default - conversions in the error message. + * call.c (find_scoped_type): Make static. + * cp-tree.h (find_scoped_type): Delete decl. - * *.c: Use c_build_type_variant instead of build_type_variant where - the type might be an array. + * search.c (convert_pointer_to_vbase): Make static. + * cp-tree.h (convert_pointer_to_vbase): Delete decl. -Sat Jun 25 11:50:54 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (const_ptr_type_node): Likewise. + * cp-tree.h (const_ptr_type_node): Delete decl. - * cvt.c (convert_to_reference): Try UDC's before doing the - reinterpret_cast thang, though. + * typeck.c (common_base_type): Make static. + * cp-tree.h (common_base_types): Delete erroneous decl. -Fri Jun 24 01:24:01 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (classtype_mangled_name): Make static. + * cp-tree.h (classtype_mangled_name): Delete decl. - * typeck.c (c_expand_return): Don't USE the return value location - after we've expanded the jump. + * lex.c (check_newline): Make static. + * cp-tree.h (check_newline): Delete decl. - * decl2.c (finish_file): Make sure DECL_SAVED_INSNS is not 0 before - trying to write out an inline. + * typeck.c (build_x_array_ref): Delete fn, same idea as + grok_array_decl. + * cp-tree.h (build_x_array_ref): Delete decl. - * cvt.c (build_up_reference): Also do address adjustment when the - target type uses MI. - (convert_to_reference): Try UDCs only after built-in conversions. - (build_type_conversion_1): Don't play games with the argument to the - method. - (build_type_conversion): #if 0 out code for binding to reference. + * lex.c (copy_decl_lang_specific): Delete fn, same idea as + copy_lang_decl. + * cp-tree.h (copy_decl_lang_specific): #if 0 decl. -Thu Jun 23 00:22:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (build_vtable_entry): Make static. + * cp-tree.h (build_vtable_entry): Delete decl. - * decl2.c (finish_file): Use TREE_SYMBOL_REFERENCED to decide - whether to emit inlines. + * class.c (build_vbase_pointer): Make static. + * cp-tree.h (build_vbase_pointer): Delete decl. - * decl.c (grokdeclarator): Set explicit_int for decls that just - specify, say, 'long'. + * sig.c (build_sptr_ref): Add forward decl and make static. + * cp-tree.h (build_sptr_ref): Delete decl. - * init.c (do_friend): Do overload C functions (or call pushdecl, - anyaway). + * call.c (build_new_method_call): Add forward decl and make static. + * cp-tree.h (build_new_method_call): Delete decl. -Wed Jun 22 13:40:49 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_object_call): Make static. + * class.c (check_for_override, complete_type_p, mark_overriders): + Likewise. + * decl.c (cp_function_chain): Likewise. + * lex.c (set_typedecl_interface_info, reinit_parse_for_block): + Likewise. + * pt.c (comp_template_args, get_class_bindings, push_tinst_level): + Likewise. + * tree.c (build_cplus_array_type_1): Likewise. + * typeck.c (comp_ptr_ttypes_{const,real,reinterpret}): Likewise. + (comp_target_parms): Likewise. - * cvt.c (build_up_reference): Don't call readonly_error. - (convert_to_reference): Propagate const and volatile from expr to - its type. + * init.c (build_builtin_call): Make static. + * cp-tree.h (build_builtin_call): Delete decl. - * tree.c (lvalue_p): Random CALL_EXPRs are not lvalues. + * typeck.c (binary_op_error): Delete decl. + * cp-tree.h (binary_op_error): Likewise. - * cvt.c (build_up_reference): Break out WITH_CLEANUP_EXPR when - creating a temporary. - (convert_to_reference): Lose excessive and incorrect trickiness. - (cp_convert): Call build_cplus_new with with_cleanup_p set. +Thu Mar 6 16:13:52 1997 Brendan Kehoe - * typeck2.c (build_functional_cast): Ditto. + * call.c (build_method_call): Compare against error_mark_node + directly, rather than the ERROR_MARK tree code. + * cvt.c (cp_convert): Likewise. + * decl.c (print_binding_level): Likewise. + (duplicate_decls): Likewise. + (grokdeclarator): Likewise. + (grokdeclarator): Likewise. + * init.c (expand_aggr_init_1): Likewise. + (decl_constant_value): Likewise. + * method.c (build_opfncall): Likewise. + (hack_identifier): Likewise. + * typeck.c (build_modify_expr): Likewise. -Tue Jun 21 17:38:38 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (build_c_cast): Don't decl TYPE as register tree. - * decl.c (grokdeclarator): signed, unsigned, long and short all - imply 'int'. +Sun Mar 2 02:54:36 1997 Bruno Haible - * decl.c (grokdeclarator): Allow "this is a type" syntax. - (grok_reference_init): Simplify and fix. + * pt.c (unify): Strip NOP_EXPR wrappers before unifying integer values. -Sun Jun 19 17:08:48 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (coerce_template_parms): Add new error message. - * decl.c (grokdeclarator): pedwarn about a typedef that specifies no - type. + * method.c (build_overload_value): Implement name mangling for + floating-point template arguments. -Sat Jun 18 04:16:50 1994 Jason Merrill (jason@deneb.cygnus.com) + * method.c (build_overload_int, icat, dicat): Fix mangling of template + arguments whose absolute value doesn't fit in a signed word. - * decl.c (start_function): Move TREE_PUBLIC and DECL_EXTERNAL - tinkering to after call to pushdecl. +Mon Mar 3 12:14:54 1997 Brendan Kehoe -Fri Jun 17 14:48:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * friend.c: New file; put all of the friend stuff in here. + * init.c: Instead of here. + * Makefile.in (CXX_OBJS): Add friend.o. + (friend.o): Add dependencies. + * Make-lang.in (CXX_SRCS): Add $(srcdir)/cp/friend.c. - * call.c (build_method_call): Handle destructors for non-aggregate - types properly. +Sun Mar 2 11:04:43 1997 Jason Merrill -Thu Jun 16 16:48:05 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_scoped_method_call): Complain if the scope isn't a + base. - * call.c (build_method_call): Make sure that the name given for the - destructor matches the constructor_name of the instance. +Wed Feb 26 11:31:06 1997 Jason Merrill - * pt.c (do_function_instantiation): A non-extern instantiation - overrides a later extern one. - (do_type_instantiation): Ditto. + * parse.y (left_curly): Don't crash on erroneous type. -Wed Jun 15 19:34:54 1994 Jason Merrill (jason@deneb.cygnus.com) + * init.c (build_delete): Fix type of ref. - * init.c (expand_aggr_init): Use TYPE_MAIN_VARIANT to get the - unqualified array type. +Tue Feb 25 12:41:48 1997 Jason Merrill - * cp-tree.h (EMPTY_CONSTRUCTOR_P): Tests whether NODE is a - CONSTRUCTOR with no elements. + * search.c (get_vbase_1): Renamed from get_vbase. + (get_vbase): Wrapper, now non-static. + (convert_pointer_to_vbase): Now static. - * decl.c (various): Lose empty_init_node. - (finish_decl): Use EMPTY_CONSTRUCTOR_P, do the empty CONSTRUCTOR - thing depending on the value of DECL_COMMON instead of - flag_conserve_space, do the empty CONSTRUCTOR thing for types that - don't have constructors, don't treat a real empty CONSTRUCTOR - specially. + * call.c (build_scoped_method_call): Accept a binfo for BASETYPE. + * init.c (build_delete): Pass one. + (build_partial_cleanup_for): Use build_scoped_method_call. + * decl.c (finish_function): Pass a binfo. - * typeck2.c (process_init_constructor): Don't treat empty_init_node - specially. +Mon Feb 24 15:00:12 1997 Jason Merrill -Wed Jun 15 19:05:25 1994 Mike Stump + * call.c (build_over_call): Only synthesize non-trivial copy ctors. - * class.c (override_one_vtable): Don't forget to merge in an old - overrider when we wanted to reuse a vtable, but couldn't. + * typeck.c (build_c_cast): Lose other reference to flag. -Wed Jun 15 15:03:16 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_field_call): Don't look for [cd]tor_identifier. + * decl2.c (delete_sanity): Remove meaningless use of + LOOKUP_HAS_IN_CHARGE. + * decl.c (finish_function): Use build_scoped_method_call instead + of build_delete for running vbase dtors. + * init.c (build_delete): Call overload resolution code instead of + duplicating it badly. - * decl.c (start_decl): Put statics in common again. +Thu Feb 20 15:12:15 1997 Jason Merrill - * decl.c (grokdeclarator): Return NULL_TREE for an error rather than - setting the type to error_mark_node. + * call.c (build_over_call): Call mark_used before trying to elide + the call. - * typeck.c (build_modify_expr): Build up a COMPOUND_EXPR for enum - bitfield assignments. + * decl.c (implicitly_declare): Don't set DECL_ARTIFICIAL. -Tue Jun 14 12:23:38 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Feb 19 11:18:53 1997 Brendan Kehoe - * decl.c (grok_op_properties): Const objects can be passed by value. + * typeck.c (build_modify_expr): Always pedwarn for a cast to + non-reference used as an lvalue. -Mon Jun 13 03:10:59 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Feb 19 10:35:37 1997 Jason Merrill - * decl2.c (import_export_vtable): Force implicit instantiations to - be interface_only when -fno-implicit-templates. + * cvt.c (cp_convert_to_pointer): Convert from 0 to a pmf properly. - * decl.c (duplicate_decls): Redeclaring a class template name is an - error. +Tue Feb 18 15:40:57 1997 Jason Merrill - * pt.c (end_template_decl): Call GNU_xref_decl for class templates. - * xref.c (GNU_xref_decl): Support templates. + * parse.y (handler): Fix template typo. -Sat Jun 11 17:09:05 1994 Jason Merrill (jason@deneb.cygnus.com) +Sun Feb 16 02:12:28 1997 Jason Merrill - * decl.c (grok_op_properties): Split out checking for whether this - function should suppress the default assignment operator. - * decl2.c (grok_function_init): Ditto. - (copy_assignment_arg_p): New function do do just that. - Now considers virtual assignment operators that take a base as an - argument to count as copy assignment operators. + * error.c (lang_decl_name): New fn. + * tree.c (lang_printable_name): Use it. - * search.c (dfs_debug_mark): Lose checks for DWARF_DEBUG and - TREE_ASM_WRITTEN, as they are redundant. +Fri Feb 14 16:57:05 1997 Mike Stump - * pt.c (end_template_decl): Don't try to set DECL_CLASS_CONTEXT on a - decl that has no LANG_SPECIFIC part. - (do_type_instantiation): Force the debugging information for this - type to be emitted. + * g++spec.c: Include config.h so that we can catch bzero #defines + from the config file. - * decl.c (start_decl): Clear up uses of various types of templates - (say sorry for static data members, rather than "invalid template"). - (expand_static_init): Fix initialization of static data members of - template classes. +Tue Feb 11 13:50:48 1997 Mike Stump -Fri Jun 10 00:41:19 1994 Jason Merrill (jason@deneb.cygnus.com) + * new1.cc: Include a declaration for malloc, to avoid warning, and + avoid lossing on systems that require one (ones that define malloc + in xm.h). - * decl.c (grokdeclarator): Set DECL_CONTEXT on static data members. +Mon Feb 10 22:51:13 1997 Bruno Haible - * g++.c (main): Use -xc++-cpp-output for .i files. + * decl2.c (max_tinst_depth): New variable. + (lang_decode_option): Parse "-ftemplate-depth-NN" command line + option. + * pt.c (max_tinst_depth): Variable moved. + * lang-options.h: Declare "-ftemplate-depth-NN" command line option + as legal. - * pt.c (tsubst): Give meaningful error about declaring template for - a copy constructor which was not declared in the class template. - (do_type_instantiation): Explicit instantiation before the class - template is an error. - (instantiate_template): Don't die if tsubst returns error_mark_node. +Fri Feb 7 15:43:34 1997 Jason Merrill -Thu Jun 9 19:04:59 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (xref_basetypes): Allow a base class that depends on + template parms to be incomplete. - Don't synthesize the copy assignment operator if the one in a base - class is pure virtual. - * cp-tree.h (TYPE_HAS_ABSTRACT_ASSIGN_REF): New macro to indicate - whether the type has a pure virtual copy assignment operator. - * class.c (finish_base_struct): Don't generate the copy assignment - operator if a base class has a pure virtual one. - * decl.c (grok_op_properties): Add disabled code to set - TYPE_HAS_ABSTRACT_ASSIGN_REF with comment pointing to where it is - actually set. - * decl2.c (grok_function_init): Set TYPE_HAS_ABSTRACT_ASSIGN_REF. + * decl2.c (build_expr_from_tree): Support typeid(type). + * rtti.c (get_typeid): Support templates. + (expand_si_desc, expand_class_desc): Fix string length. + (expand_ptr_desc, expand_attr_desc, expand_generic_desc): Likewise. - * decl2.c (import_export_vtable): Always treat template - instantiations as if write_virtuals >= 2, and treat implicit - instantiations as external if -fno-implicit-templates. - (finish_file): Output all pending inlines if - flag_keep_inline_functions. +Tue Feb 4 11:28:24 1997 Jason Merrill -Wed Jun 8 20:48:02 1994 Mike Stump + * pt.c (unify, case TEMPLATE_CONST_PARM): Use cp_tree_equal. - * tree.c (layout_vbasetypes): Align virtual base classes inside - complete objects, so that we don't core dump on machines such as - SPARCs when we access members that require larger than normal - alignments, such as a double. Also, we bump up the total alignment - on the complete type, as necessary. + * pt.c (tsubst): Put it back for -fno-ansi-overloading. -Wed Jun 8 16:18:14 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Feb 3 18:41:12 1997 Jason Merrill - * gxxint.texi (Free Store): New section with code for examining - cookie. - (Limitations of g++): Remove operator delete entry, since it is no - longer accurate. Fix access control entry. + * pt.c (tsubst, case FUNCTION_DECL): Lose obsolete code that + smashes together template and non-template decls of the same + signature. - * typeck.c (build_unary_op): Pedwarn about taking the address of or - incrementing a cast to non-reference type. - (build_modify_expr): Use convert instead of convert_force again. +Thu Jan 30 19:18:00 1997 Jason Merrill - * search.c (get_base_distance): Use IS_AGGR_TYPE_CODE to check for - class type, not == RECORD_TYPE. + * pt.c (tsubst): Don't recurse for the type of a TYPENAME_TYPE. - * decl.c (grokdeclarator): Cope with grokfndecl returning NULL_TREE. +Wed Jan 29 11:40:35 1997 Brendan Kehoe - * typeck2.c (report_case_error): #if 0 out. - * lex.c (real_yylex): Lose RANGE. - * parse.y: Ditto. + * decl.c (duplicate_decls): Next route, pedwarn about different + exceptions if -pedantic *or* olddecl !DECL_IN_SYSTEM_HEADER. -Tue Jun 7 18:17:35 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Jan 28 20:43:29 1997 Brendan Kehoe - * parse.y (simple_stmt, case ranges): Use ELLIPSIS instead of RANGE. + * cp-tree.h (HAS_DEFAULT_IMPLEMENTATION): Delete macro. + (struct lang_type): Delete has_default_implementation member. + Increase dummy to 21. + * decl.c (start_method): Delete usage. -Mon Jun 6 19:39:57 1994 Jason Merrill (jason@deneb.cygnus.com) + * cp-tree.h (build_call, null_ptr_cst_p, in_function_p, + store_after_parms, start_decl_1, auto_function): Add decls. + (get_arglist_len_in_bytes, declare_implicit_exception, + have_exceptions_p, make_type_decl, typedecl_for_tag, + store_in_parms, pop_implicit_try_blocks, push_exception_cleanup, + build_component_type_expr, cplus_exception_name, + {make,clear}_anon_parm_name, dont_see_typename): Removed decls. + * call.c (build_this): Make static. + (is_complete): Likewise. + (implicit_conversion): Likewise. + (reference_binding): Likewise. + (standard_conversion): Likewise. + (strip_top_quals): Likewise. + (non_reference): Likewise. + (build_conv): Likewise. + (user_harshness): Likewise. + (rank_for_ideal): Likewise. + * decl.c (start_decl_1): Delete forward decl. + (push_decl_level): Make static. + (resume_binding_level): Make static. + (namespace_bindings_p): Make static. + (declare_namespace_level): Make static. + (lookup_name_real): Make static. + (duplicate_decls): Make static. Take register off NEWDECL and + OLDDECL parm decls. + * decl2.c (get_sentry): Make static. + (temp_name_p): Delete fn. + * except.c (auto_function): Delete decl. + * lex.c (handle_{cp,sysv}_pragma): Make static. + (handle_sysv_pragma) [HANDLE_SYSV_PRAGMA]: Add forward decl. + * method.c (do_build_{copy_constructor,assign_ref}): Make static. + * pt.c (tsubst_expr_values): Make static. + * rtti.c (combine_strings): Delete decl. - * typeck.c (build_c_cast): Don't shortcut conversions to the same - type. Don't replace consts with their values here, since that's now - done in cp_convert. +Tue Jan 28 16:40:40 1997 Jason Merrill - * cvt.c (cp_convert): When converting to bool, take - integer_zero_node to false_node and all other INTEGER_CSTs to - true_node. - (build_type_conversion): Don't complain about multiple conversions - to float if we're not really converting. + * pt.c (push_template_decl): Handle getting a typedef. -Fri Jun 3 02:10:56 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_new_function_call): Complain about void arg. - Implement 'extern template class A;' syntax for suppressing - specific implicit instantiations. - * cp-tree.h: Update prototypes for do_*_instantiation. - * pt.c (do_pending_expansions): Don't compile 'extern' explicit - instantiations. - (do_function_instantiation): Set DECL_EXTERNAL on 'extern' explicit - instantiations. - (do_type_instantiation): Ditto. - * parse.y (explicit_instantiation): Support 'extern template class - A;' syntax. - * decl.c (start_function): Don't modify the settings of TREE_PUBLIC - and DECL_EXTERNAL on explicit instantiations. +Tue Jan 28 15:25:09 1997 Brendan Kehoe - * cvt.c (cp_convert): Replace constants with their values before - converting. - (cp_convert): Consistently use 'e' instead of 'expr'. + * decl.c (duplicate_decls): Give pedwarn of different exceptions + if -pedantic, instead of olddecl !DECL_IN_SYSTEM_HEADER. -Thu Jun 2 03:53:30 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Jan 27 19:21:29 1997 Mike Stump - * typeck2.c (build_x_arrow): Resolve OFFSET_REFs first. + * except.c (expand_throw): Don't expand the cleanup tree here, + since we are not going to write the rtl out. Fixes problem with + -g -O on SPARC. -Wed Jun 1 18:57:35 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Jan 27 16:24:35 1997 Sean McNeil - * typeck2.c (digest_init): Handle initializing a pmf with an - overloaded method. - * typeck.c (build_ptrmemfunc): Handle overloaded methods. + * Make-lang.in: Add $(exeext) as necessary. - * decl.c (pushtag): Use build_decl to make TYPE_DECLs. - (xref_defn_tag): Ditto. - * pt.c (process_template_parm): Ditto. - (lookup_template_class): Ditto. - (push_template_decls): Ditto. - (instantiate_class_template): Ditto. - (create_nested_upt): Ditto. - * class.c (finish_struct): Don't try to set DECL_CLASS_CONTEXT on - TYPE_DECLs. +Mon Jan 27 13:20:39 1997 Mike Stump - * typeck.c (convert_arguments): Make sure type is not NULL before - checking its TREE_CODE. + * parse.y (handler_seq): Must have at least one catch clause. -Wed Jun 1 17:40:39 1994 Mike Stump +Sat Jan 25 12:00:05 1997 Jason Merrill - * class.c (get_derived_offset): New routine. - * class.c (finish_base_struct): Make sure we set BINFO_VTABLE and - BINFO_VIRTUALS when we choose a new base class to inherit from. - * class.c (modify_one_vtable): Use get_derived_offset to get the - offset to the most base class subobject that we derived this binfo - from. - * class.c (finish_struct): Move code to calculate the - DECL_FIELD_BITPOS of the vfield up, as we need might need it for - new calls to get_derived_offset in modify_one_vtable. - -Wed Jun 1 16:50:59 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (add_builtin_candidate): Restore ?: hack. - * init.c (build_member_call): Use build_pointer_type instead of - TYPE_POINTER_TO. - -Wed Jun 1 11:11:15 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (grok_op_properties): More warnings. - * decl.c (grokdeclarator): Make sure we have a DNAME set before we - try to use it in an error. +Sat Jan 25 08:50:03 1997 Brendan Kehoe -Wed Jun 1 09:48:49 1994 Mike Stump + * decl.c (duplicate_decls): On second thought, do it as a pedwarn + still but only if !DECL_IN_SYSTEM_HEADER (olddecl). - * typeck.c (convert_arguments, convert_for_initialization): Don't - strip NOP_EXPRs, when we are converting to a reference. + * decl.c (duplicate_decls): Scale back to a warning, and only do + 'em if -pedantic. -Wed Jun 1 01:11:38 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Jan 24 17:52:54 1997 Mike Stump - * typeck.c (build_modify_expr): Don't dereference references when - initializing them. + * decl.c (duplicate_decls): pedwarn mismatched exception + specifications. - * decl2.c (grokfield): Don't check for grokdeclarator returning - error_mark_node any more. +Thu Jan 23 18:18:54 1997 Mike Stump - * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node. - (start_method): Return void_type_node instead of error_mark_node. + * call.c (build_new_method_call): Don't display the invisible + argument for controlling virtual bases. - * typeck.c (build_modify_expr): Resolve offset refs earlier. +Thu Jan 23 16:48:10 1997 Mike Stump -Tue May 31 16:06:58 1994 Jason Merrill (jason@deneb.cygnus.com) + * new: Add nothrow new and delete, bad_alloc and throw specifications + for delete. + * decl.c (init_decl_processing): Add throw specification for delete. + * new.cc (nothrow): Define. + * lex.c (real_yylex): Removing warning that throw and friends are + keywords. + * new1.cc (operator new (size_t sz, const nothrow_t&)): Define. + * new2.cc (operator new[] (size_t sz, const nothrow_t&): Define. + * Make-lang.in: Add new{1,2}.{cc,o}. - * call.c (build_method_call): Resolve OFFSET_REFs in the object. +Thu Jan 23 16:39:06 1997 Jason Merrill - * typeck.c (build_modify_expr): Dereference references before trying - to assign to them. - - * call.c (build_method_call): Don't confuse type conversion - operators with constructors. - * typeck2.c (build_functional_cast): Just call build_c_cast if there - was only one parameter. - * method.c (build_typename_overload): Don't set - IDENTIFIER_GLOBAL_VALUE on these identifiers. - * decl.c (grok_op_properties): Warn about defining a type conversion - operator that converts to a base class (or reference to it). - * cvt.c (cp_convert): Don't try to use a type conversion operator - when converting to a base class. - (build_type_conversion_1): Don't call constructor_name_full on an - identifier. - * cp-tree.h (DERIVED_FROM_P): Should be self-explanatory. - - * decl.c (start_decl): Don't complain that error_mark_node is an - incomplete type. - (finish_decl): Check for type == error_mark_node. + * lex.c (cons_up_default_function): Fix return type of synth op=. -Mon May 30 23:38:55 1994 Jason Merrill (jason@deneb.cygnus.com) + * init.c (emit_base_init): Add warnings for uninitialized members + and bases. - * decl.c (start_function): Set DECL_DEFER_OUTPUT on implicit - instantiations and inline members. + * decl.c (xref_basetypes): Add warning for non-polymorphic type + with destructor used as base type. - * spew.c (yylex): Set looking_for_template if the next token is a '<'. + * decl.c (grok_op_properties): Add warning for op= returning void. + * typeck.c (c_expand_return): Add warning for op= returning anything + other than *this. - * lex.h: Declare looking_for_template. + * class.c (finish_struct_1): Add warning for class with pointers + but not copy ctor or copy op=. - * decl.c (lookup_name_real): Use looking_for_template to arbitrate - between type and template interpretations of an identifier. + * cp-tree.h (TI_PENDING_TEMPLATE_FLAG): New macro. + * pt.c (add_pending_template): Use it instead of LANG_FLAG_0. + (instantiate_template): If -fexternal-templates, add this + instantiation to pending_templates. -Sat May 28 04:07:40 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (copy_assignment_arg_p): Disable old hack to support + Booch components. - * pt.c (instantiate_template): Zero out p if we found a - specialization. +Tue Jan 21 18:32:04 1997 Mike Stump - * decl.c (grokdeclarator): Elucidate warning. - (grokdeclarator): If pedantic AND -ansi, complain about long long. + * cvt.c (cp_convert): Pedwarn enum to pointer conversions. - Make explicit instantiation work reasonably. It is now appropriate - to deprecate the use of -fexternal-templates. - * pt.c (instantiate_template): Set DECL_TEMPLATE_SPECIALIZATION or - DECL_IMPLICIT_INSTANTIATION on fndecl as appropriate. - (end_template_instantiation): Reflect changes in USE_TEMPLATE - semantics. - (do_pending_expansions): if (!flag_implicit_templates) DECIDE(0); - (do_function_instantiation): Don't set EXPLICIT_INST if - flag_external_templates is set. Do set TREE_PUBLIC and DECL_EXTERN - appropriately otherwise. - (do_type_instantiation): Set interface info for class. Set - TREE_PUBLIC and DECL_EXTERN for methods. Do none of this if - flag_external_templates is set. - * parse.y: Reflect changes in USE_TEMPLATE semantics. - * decl2.c: New flag flag_implicit_templates determines whether or - not implicit instantiations get emitted. This flag currently - defaults to true, and must be true for -fexternal-templates to work. - (finish_file): Consider flag_implement_inlines when - setting DECL_EXTERNAL. Consider flag_implicit_templates when - deciding whether or not to emit a static copy. - * decl.c (start_function): Set TREE_PUBLIC and DECL_EXTERNAL - properly for template instantiations. - (start_method): Set DECL_IMPLICIT_INSTANTIATION on methods of a - template class. - * cp-tree.h (CLASSTYPE_USE_TEMPLATE): Change semantics. - (DECL_USE_TEMPLATE): Parallel macro for FUNCTION and VAR_DECLs. - (various others): Accessor macros for the above. +Mon Jan 20 17:59:51 1997 Jason Merrill -Fri May 27 13:57:40 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (standard_conversion): Handle getting references. Tack + on RVALUE_CONV here. Do it for non-class types, too. + (reference_binding): Pass references to standard_conversion. + (implicit_conversion): Likewise. + (add_builtin_candidate): Disable one ?: kludge. + (convert_like): Handle RVALUE_CONVs for non-class types. + (joust): Disable the other ?: kludge. - * typeck.c (build_binary_op_nodefault): Division by constant zero is - an error. +Mon Jan 20 14:53:13 1997 Brendan Kehoe -Fri May 27 13:50:15 1994 Mike Stump + * decl.c (init_decl_processing): Add code to build up common + function types beforehand, to avoid creation then removal of + things already in the hash table. - * class.c (override_one_vtable): Don't modify things we don't own. +Mon Jan 20 14:43:49 1997 Jason Merrill -Fri May 27 01:42:58 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (finish_function): Also zero out DECL_INCOMING_RTL for + the arguments. - * decl.c (finish_decl): Don't postpone processing the initializer of - a decl with DECL_EXTERNAL set, and do call rest_of_compilation for a - PUBLIC const at toplevel. - (grokdeclarator): pedwarn about initializing non-const or - non-integral statics in the class body. - - * decl.c (pushtag): Don't try to set DECL_CLASS_CONTEXT on a - TYPE_DECL. + * error.c (dump_expr, TEMPLATE_CONST_PARM): Don't require + current_template_parms. - * call.c (convert_harshness): Dereference reference on rhs before - proceeding, properly grok passing const things to non-const - references. +Fri Jan 17 10:25:42 1997 Jason Merrill - * typeck.c (build_unary_op): Soften error about taking the address - of main() to a pedwarn. + * search.c (lookup_field): Don't return a function, check want_type. - * lex.c (default_copy_constructor_body): Unambiguously specify base - classes (i.e. A((const class ::A&)_ctor_arg) ). - (default_assign_ref_body): Ditto. +Thu Jan 16 18:14:35 1997 Brendan Kehoe -Thu May 26 13:13:55 1994 Gerald Baumgartner (gb@mexican.cygnus.com) + * init.c (build_new): Make sure PLACEMENT has a type. - * decl2.c (grokfield): Don't complain about local signature - method declaration without definition. +Thu Jan 16 17:40:28 1997 Jason Merrill - * call.c (convert_harshness): If `type' is a signature pointer - and `parmtype' is a pointer to a signature, just return 0. We - don't really convert in this case; it's a result of making the - `this' parameter of a signature method a signature pointer. + * init.c (build_new): Support new (nothrow). - * call.c (build_method_call): Distinguish calling the default copy - constructor of a signature pointer/reference from a signature - member function call. +Wed Jan 15 12:38:14 1997 Jason Merrill -Thu May 26 12:56:25 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (instantiate_decl): Also do push_to_top_level before setting + up DECL_INITIAL. - * decl2.c (grokfield): Don't set TREE_PUBLIC on member function - declarations. + * cp-tree.h (PARM_DEFAULT_FROM_TEMPLATE): New macro. + * pt.c (tsubst): Defer instantiation of default args. + * call.c (build_over_call): Until here. - * decl.c (duplicate_decls): A previous function declaration as - static overrides a subsequent non-static definition. - (grokdeclarator): Don't set TREE_PUBLIC on inline method - declarations. +Wed Jan 15 10:08:10 1997 Brendan Kehoe -Wed May 25 14:36:38 1994 Jason Merrill (jason@deneb.cygnus.com) + * search.c (lookup_field): Make sure we have an + IDENTIFIER_CLASS_VALUE before we try to return it. - * decl.c (grokdeclarator): Handle initialization of static const - members. - (finish_decl): Ditto. +Thu Jan 9 07:19:01 1997 Brendan Kehoe - * decl2.c (grokfield): Allow initialization of static const members - even when pedantic. + * call.c (build_method_call): Delete unused var PARM. + (build_overload_call_real): Likewise. + (build_object_call): Delete unused var P. + (build_new_op): Likewise. + * decl.c (builtin_type_tdescs_{arr, len, max}): #if 0 out static + var definitions, which are never used. + (shadow_tag): Delete unused var FN. + * expr.c (cplus_expand_expr): Delete unused var ORIGINAL_TARGET. + * init.c (build_new): Delete unused var ALLOC_TEMP. + * method.c (hack_identifier): Delete unused var CONTEXT. + (do_build_copy_constructor): Delete unused var NAME. + (synthesize_method): Delete unused var BASE. + * pt.c (lookup_template_class): Delete unused var CODE_TYPE_NODE. + * rtti.c (build_headof): Delete unused var VPTR. + (get_typeid): Delete unused var T. + * typeck.c (build_conditional_expr): Delete unused vars ORIG_OP1 + and ORIG_OP2. + (build_ptrmemfunc): Delete unused vars U and NINDEX. + * typeck2.c (build_functional_cast): Delete unused var BINFO. - * decl2.c (grokfield): Deal with grokdeclarator returning - error_mark_node. +Wed Jan 8 13:09:54 1997 Jason Merrill - * decl.c (grok_ctor_properties): Return 0 for A(A) constructor. - (grokfndecl): Check the return value of grok_ctor_properties. - (start_method): Ditto. + * search.c (lookup_field): Use IDENTIFIER_CLASS_VALUE to look up + things in a type being defined. + * decl.c (finish_enum): Reverse the values so that they are in + the correct order. - * parse.y (absdcl): Expand type_quals inline. + * pt.c (instantiate_class_template): Don't initialize + BINFO_BASETYPES until the vector is filled out. + (unify): Don't abort on conflicting bindings, just fail. + (instantiate_decl): Do push_tinst_level before any tsubsting. -Tue May 24 19:10:32 1994 Jason Merrill (jason@deneb.cygnus.com) + * method.c (build_overload_value): Handle getting a + TEMPLATE_CONST_PARM for a pointer. - * decl.c (pushtag): Use IS_AGGR_TYPE rather than checking for a - RECORD_TYPE. +Tue Jan 7 14:00:58 1997 Jason Merrill -Tue May 24 18:09:16 1994 Per Bothner (bothner@kalessin.cygnus.com) + * init.c (expand_member_init): Don't give 'not a base' error for + templates. - * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks, - always use "__vt_%s". - * decl2.c (finish_vtable_vardecl): Don't consider abstract virtuals - when looking for a "sentinal" method (to decide on emitting vtables). - * decl2.c (finish_file): Scan all decls for thunks that need - to be emitted. - * decl2.c (finish_vtable_vardecl): Don't bother calling emit_thunk. - * method.c (make_thunk): Use a more meaningful label. If there - exists a matching top-level THUNK_DECL re-use it; otherwise - create a new THUNK_DECL (and declare it). - * method.c (emit_thunk): Make thunk external/public depending - on the underlying method. + * pt.c (instantiate_decl): Call import_export_decl later. -Tue May 24 00:22:04 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (instantiate_class_template): Return a value. - * pt.c (tsubst): Use lookup_name_nonclass to find guiding decls, not - lookup_name. + * parse.y (extension): New rule for __extension__. + (extdef, unary_expr, decl, component_decl): Use it. - * call.c (build_overload_call_real): Don't immediately pick a - function which matches perfectly. +Tue Jan 7 09:20:28 1997 Mike Stump - * decl.c (grokdeclarator): Use c_build_type_variant for arrays. - (grokdeclarator): Warn about, and throw away, cv-quals attached to a - reference (like 'int &const j'). + * class.c (base_binfo): Remove unused base_has_virtual member. + (finish_base_struct): Likewise. + (finish_struct_1): Likewise. - * typeck.c (convert_arguments): Don't mess with i for methods. - * call.c (build_method_call): Pass the function decl to - convert_arguments. +Tue Dec 31 20:25:50 1996 Mike Stump - * typeck.c (comp_ptr_ttypes_real): New function. Implements the - checking for which multi-level pointer conversions are allowed. - (comp_target_types): Call it. - (convert_for_assignment): Check const parity on the ultimate target - type, too. And make those warnings pedwarns. + * search.c (expand_upcast_fixups): Fix bogus code generation + problem where the generated code uses the wrong index into the + runtime built vtable on the stack. Old code could clobber random + stack values. -Mon May 23 14:11:24 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Dec 31 15:16:56 1996 Mike Stump - * error.c (dump_char): Use TARGET_* for character constants. + * init.c (perform_member_init): Make sure the partial EH cleanups + live on the function_obstack. -Mon May 23 13:03:03 1994 Brendan Kehoe (brendan@lisa.cygnus.com) +Fri Dec 27 10:31:40 1996 Paul Eggert - * tree.c (debug_no_list_hash): Make static. + * 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). - * decl.c (decls_match): Say the types don't match if newdecl ends up - with a null type, after we've checked if olddecl does. - (pushdecl): Check if the decls themselves match before looking for - an extern redeclared as static, to avoid inappropriate and incorrect - warnings. +Tue Dec 24 10:24:03 1996 Jeffrey A Law (law@cygnus.com) -Fri May 20 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (grokvardecl): Avoid ANSI style initialization. - * decl.c (grokdeclarator): Make warning about duplicate short, etc. - a pedwarn. +Sun Dec 22 04:22:06 1996 Jason Merrill - * typeck.c (build_c_cast): Casting to function or method type is an - error. + * pt.c (tsubst): Tweak arg types for a FUNCTION_TYPE. - * class.c (finish_struct): Make warning for anonymous class with no - instances a pedwarn. +Fri Dec 20 17:09:25 1996 Jason Merrill - * Makefile.in (stamp-parse): Expect a s/r conflict. + * pt.c (instantiate_class_template): Call grok_{ctor,op}_properties. - * typeck.c (build_modify_expr): pedwarn about using a non-lvalue - cast as an lvalue. +Fri Dec 20 12:17:12 1996 Brendan Kehoe -Thu May 19 12:08:48 1994 Jason Merrill (jason@deneb.cygnus.com) + * g++spec.c (lang_specific_driver): Put missing hyphen in front of + arguments we compare against. Start the count of I at 1, not 0, + since argv[0] is still the command. - * cvt.c (type_promotes_to): Make sure bool promotes to int rather - than unsigned on platforms where sizeof(char)==sizeof(int). +Thu Dec 19 11:53:57 1996 Stan Shebs -Wed May 18 14:27:06 1994 Jason Merrill (jason@deneb.cygnus.com) + * lang-specs.h: Accept .cp as an C++ extension. - * typeck.c (build_c_cast): Tack on a NOP_EXPR when casting to - another variant. - (build_modify_expr): Don't strip NOP_EXPRs, and don't get tricky - and treat them as lvalues. +Mon Dec 16 22:43:31 1996 Brendan Kehoe - * decl.c (shadow_tag): Do complain about forward declarations of - enums and empty declarations. - * parse.y: Don't complain about forward declarations of enums and - empty declarations. + * cp-tree.h (ptr_reasonably_similar): Add decl. - * typeck.c (convert_for_assignment): Complain about changing - the signedness of a pointer's target type. +Thu Dec 12 15:00:35 1996 Brendan Kehoe - * parse.y (stmt): Move duplicated code for checking case values from - here. - * decl2.c (check_cp_case_value): To here. And add a call to - constant_expression_warning. + * decl.c (grokvardecl): Change SPECBITS parm to be the SPECBITS_IN + pointer. New local SPECBITS with the parm's value. + (grokdeclarator): Pass &specbits down. - * typeck.c (convert_for_assignment): Don't complain about assigning - a negative value to bool. + * parse.y (expr_no_commas): Make sure $$ is not an error_mark_node + before we try to do C_SET_EXP_ORIGINAL_CODE on it. - * decl.c (init_decl_processing): Make bool unsigned. + * search.c (envelope_add_decl): Check that the CLASSTYPE_CID of + CONTEXT is not 0 before we try to use TYPE_DERIVES_FROM. - * class.c (finish_struct): Allow bool bitfields. + * decl.c (cplus_expand_expr_stmt): Only expand the expr if EXP is + not an error_mark_node. -Wed May 18 12:35:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) +Sat Dec 7 17:20:22 1996 Jason Merrill - * Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp. + * 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 -Wed May 18 03:28:35 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (grokdeclarator): When giving an anonymous struct a name, + replace TYPE_NAME instead of TYPE_IDENTIFIER (so TYPE_STUB_DECL is + not affected). - * cvt.c (build_type_conversion): Lose special handling of - truthvalues. + * typeck2.c (build_m_component_ref): If component is a pointer + to data member, resolve the OFFSET_REF now. - * search.c (dfs_pushdecls): Improve shadowing warning. + * call.c (convert_like): Don't go into infinite recursion. -Tue May 17 13:34:46 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (coerce_template_parms): Use tsubst_expr for non-type args. - * init.c (build_delete): Throw away const and volatile on `this'. + * class.c (finish_struct_1): Set DECL_ARTIFICIAL on the vptr. + * tree.c (layout_basetypes): And on the vbase ptr. - * decl.c (finish_enum): Put the constants in TYPE_VALUES again, - rather than the enumerators. - (pushtag): s/cdecl/c_decl/g +Thu Dec 5 02:11:28 1996 Jason Merrill -Mon May 16 23:04:01 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) + * decl.c (BOOL_TYPE_SIZE): Define in terms of POINTER_SIZE or + CHAR_TYPE_SIZE so bool is always the same size as another type. - * cp/typeck.c (common_type): Attribute merging. - (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro. + * decl.c (pushtag): Set DECL_IGNORED_P for DWARF, too. - * cp/parse.y: Revamp attribute parsing. +Tue Dec 3 23:18:37 1996 Jason Merrill -Mon May 16 01:40:34 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (grok_x_components): Remove synthesized methods from + TYPE_METHODS of an anonymous union, complain about member + functions. + * decl.c (shadow_tag): Wipe out memory of synthesized methods in + anonymous unions. + (finish_function): Just clear the DECL_RTL of our arguments. - * decl.c (shadow_tag): Also check for inappropriate use of auto and - register. +Fri Nov 29 21:54:17 1996 Jason Merrill - * method.c (build_overload_name): Clarify that the illegal case is a - pointer or reference to array of unknown bound. + * decl2.c (finish_file): Emit DWARF debugging info for static data + members. - * error.c (dump_type_prefix): Print references to arrays properly. + * pt.c (tsubst): If t is a stub decl, return the stub decl for type. - * typeck.c (various): Be more helpful in pointer - comparison diagnostics. +Wed Nov 27 14:47:15 1996 Bob Manson - * tree.c (lvalue_p): MODIFY_EXPRs are lvalues again. Isn't this - fun? + * typeck.c (build_component_ref): Don't die if COMPONENT isn't a + IDENTIFIER_NODE. - * parse.y: Also catch an error after valid stmts. +Wed Nov 27 16:05:19 1996 Michael Meissner - * search.c (dfs_init_vbase_pointers): Don't abort because `this' is - const. + * Make-lang.in (g++-cross$(exeext)): Fix typo. - * typeck.c (convert_for_initialization): If call to - convert_to_reference generated a diagnostic, print out the parm - number and function decl if any. +Wed Nov 27 08:14:00 1996 Brendan Kehoe - * errfn.c (cp_thing): Check atarg1 to determine whether or not we're - specifying a line, not atarg. + Make the g++ driver now be a standalone program, rather than one + that tries to run the gcc driver after munging up the options. + * Make-lang.in (g++.c, g++spec.o): New rules. + (g++.o): New rule, based on gcc.o with -DLANG_SPECIFIC_DRIVER + added. + (g++$(exeext)): New rule, based on xgcc rule. + (g++-cross$(exeext)): Now just copies g++$(exeext) over. + * g++spec.c: New file. + * g++.c: Removed file. - * tree.c (build_cplus_method_type): Always make `this' const. +Tue Nov 26 19:01:09 1996 Mike Stump - * decl2.c (grokclassfn): If -fthis-is-variable and this function is - a constructor or destructor, make `this' non-const. + * cvt.c (build_up_reference): Arrange for any temporary values + that have been keep in registers until now to be put into memory. - * typeck.c (build_modify_expr): Don't warn specially about - assignment to `this' here anymore, since it will be caught by the - usual machinery. +Mon Nov 25 15:16:41 1996 Kaveh R. Ghazi - * various: Disallow specific GNU extensions (variable-size arrays, - etc.) when flag_ansi is set, not necessarily when pedantic is set, - so that people can compile with -pedantic-errors for tighter const - checking and such without losing desirable extensions. + * Make-lang.in (c++.stage[1234]): Depend upon stage[1-4]-start, so + that make -j3 bootstrap works better. - * typeck2.c (build_functional_cast): Call build_method_call with - LOOKUP_PROTECT. - (process_init_constructor): Only process FIELD_DECLs. +Sun Nov 24 02:09:39 1996 Jason Merrill - * decl.c (finish_decl): Also force static consts with no explicit - initializer that need constructing into the data segment. + * decl.c (pushtag): Do pushdecl for anon tags. - * init.c (build_delete): Undo last patch, as it interferes with - automatic cleanups. +Thu Nov 21 16:30:24 1996 Jason Merrill -Sat May 14 01:59:31 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (c_expand_return): Fix logic. + (unary_complex_lvalue): Avoid unused warning on address of INIT_EXPR. - * call.c, class.h, cp-tree.h, cvt.c, decl2.c: Lose old overloading - code. +Wed Nov 20 18:47:31 1996 Bob Manson - * init.c (build_delete): pedwarn about using plain delete to delete - an array. + * g++.c (main): Make sure arglist has a final NULL entry. Add + PEXECUTE_LAST to the flags passed to pexecute, as otherwise + stdin/stdout of the invoked program are redirected to + nowheresville. -Fri May 13 16:45:07 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Nov 19 16:12:44 1996 Jason Merrill - * typeck.c (comp_target_types): Be more helpful in contravariance - warnings, and make them pedwarns. + * decl.c (implicitly_declare): Set DECL_ARTIFICIAL. - * decl.c (grokdeclarator): Use decl_context to decide whether or not - this is an access declaration. +Tue Nov 19 15:48:19 1996 Mike Stump - * class.c (finish_struct_bits): Set TYPE_HAS_INT_CONVERSION if it - has a conversion to enum or bool, too. + * init.c (resolve_offset_ref): Handle obj.vfn better. + * typeck.c (build_component_ref): Set TREE_TYPE on result from + build_vfn_ref. -Fri May 13 16:31:27 1994 Mike Stump +Tue Nov 19 13:14:33 1996 Mike Stump - * method.c (emit_thunk): Make declaration for - current_call_is_indirect local (needed for hppa). + * typeck.c (convert_for_assignment): Also handle anachronistic + implicit conversions from (::*)() to cv void*. + * cvt.c (cp_convert_to_pointer): Likewise. -Fri May 13 16:16:37 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Nov 18 17:05:26 1996 Jason Merrill - * pt.c (uses_template_parms): Grok BOOLEAN_TYPE. - (tsubst): Ditto. + * lex.c (handle_cp_pragma): Fix bogus warning. -Fri May 13 16:23:32 1994 Mike Stump +Mon Nov 18 16:10:43 1996 Mike Stump - * pt.c (tsubst): If there is already a function for this expansion, - use it. - * pt.c (instantiate_template): Ditto. - -Fri May 13 10:30:42 1994 Brendan Kehoe (brendan@lisa.cygnus.com) - - * parse.y (implicitly_scoped_stmt, simple_stmt case): Use - kept_level_p for MARK_ENDS argument to expand_end_bindings, to avoid - generating debug info for unemitted symbols on some systems. - - * cp-tree.h (build_static_cast, build_reinterpret_cast, - build_const_cast): Add declarations. - -Fri May 13 09:50:31 1994 Mike Stump - - * search.c (expand_indirect_vtbls_init): Fix breakage from Apr 27 - fix. We now try get_binfo, and if that doesn't find what we want, - we go back to the old method, which still sometimes fails. - -Fri May 13 01:43:18 1994 Jason Merrill (jason@deneb.cygnus.com) - - * parse.y (initdcl): Call cplus_decl_attributes on the right - variable. - * decl2.c (cplus_decl_attributes): Don't call decl_attributes for - void_type_node. - - * typeck.c (build_binary_op_nodefault): Change result_type for - comparison ops to bool. - (build_binary_op): Convert args of && and || to bool. - * cvt.c (build_default_binary_type_conversion): Convert args of && - and || to bool. - (build_default_unary_type_conversion): Convert arg of ! to bool. - (type_promotes_to): bool promotes to int. - -Fri May 13 01:43:18 1994 Mike Stump - - Implement the new builtin `bool' type. - * typeck.c (build_binary_op_nodefault): Convert args of && and || to - bool. - (build_unary_op): Convert arg of ! to bool. - * parse.y: Know true and false. Use bool_truthvalue_conversion. - * method.c (build_overload_value): Know bool. - (build_overload_name): Ditto. - * lex.c (init_lex): Set up RID_BOOL. - * gxx.gperf: Add bool, true, false. - * error.c (*): Know bool. - * decl.c (init_decl_processing): Set up bool, true, false. - * cvt.c (cp_convert): Handle conversion to bool. - (build_type_conversion): Ditto. - * *.c: Accept bool where integers and enums are accepted (use - INTEGRAL_CODE_P macro). - -Thu May 12 19:13:54 1994 Richard Earnshaw (rwe11@cl.cam.ac.uk) - - * g++.c: Use #ifdef for __MSDOS__, not #if. - -Thu May 12 18:05:18 1994 Mike Stump - - * decl2.c (lang_f_options): Handle -fshort-temps. -fshort-temps - gives old behavior , and destroys temporaries earlier. Default - behavior now conforms to the ANSI working paper. - -Thu May 12 14:45:35 1994 Jason Merrill (jason@deneb.cygnus.com) - - * typeck.c (build_modify_expr): Understand MODIFY_EXPR as an lvalue. - Use convert_force to convert the result of a recursive call when we - are dealing with a NOP_EXPR. Don't automatically wrap MODIFY_EXPRs - in COMPOUND_EXPRs any more. - (various): Lose pedantic_lvalue_warning. - (unary_complex_lvalue): Understand MODIFY_EXPR. - - * cvt.c (convert_to_reference): Allow DECL to be error_mark_node if - we don't know what we're initializing. - -Wed May 11 01:59:36 1994 Jason Merrill (jason@deneb.cygnus.com) - - * cvt.c (convert_to_reference): Modify to use convtype parameter. - Only create temporaries when initializing a reference, not when - casting. - (cp_convert): New main function. - (convert): Call cp_convert. - * cvt.c, decl.c, typeck.c: Fix calls to convert_to_reference. - * cp-tree.h (CONV_*): New constants used by conversion code for - selecting conversions to perform. - - * tree.c (lvalue_p): MODIFY_EXPRs are no longer lvalues. - - * typeck.c (build_{static,reinterpret,const_cast): Stubs that just - call build_c_cast. - * parse.y: Add {static,reinterpret,const}_cast. - * gxx.gperf: Ditto. - - * typeck.c (common_type): Allow methods with basetypes of different - UPTs. - (comptypes): Deal with UPTs. - (build_modify_expr): Wrap all MODIFY_EXPRs in a COMPOUND_EXPR. - - * pt.c (end_template_decl): Check for multiple definitions of member - templates. + * cvt.c (cp_convert_to_pointer): Avoid thinking a POINTER_TYPE + (METHOD_TYPE) is a TYPE_PTRMEMFUNC_P. - * call.c (build_method_call): Complain about calling an abstract - virtual from a constructor. +Thu Nov 14 23:18:17 1996 Jason Merrill - * typeck.c (pointer_int_sum): Check for the integer operand being 0 - after checking the validity of the pointer operand. + * class.c (finish_struct_1): Support DWARF2_DEBUG. + * search.c (dfs_debug_mark): Likewise. + * decl2.c (finish_vtable_vardecl): Likewise. + * decl.c (pushtag, finish_enum): Likewise. + * lex.c (check_newline): Use debug_* instead of calling *out + functions directly. - * typeck2.c (digest_init): Pedwarn about string initializer being - too long. +Thu Nov 14 15:21:46 1996 Brendan Kehoe -Tue May 10 12:10:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * Make-lang.in (cplib2.ready): Add else clause to avoid problems + on some picky hosts. - * decl.c (push_overloaded_decl): Only throw away a builtin if the - decl in question is the artificial one. +Wed Nov 13 12:32:07 1996 Jason Merrill - * parse.y (simple_stmt, switch): Use implicitly_scoped_stmt because - expand_{start,end}_case cannot happen in the middle of a block. + * class.c (finish_struct_1): A class has a non-trivial copy + constructor if it has virtual functions. - * cvt.c (build_type_conversion_1): Use convert again. + * cvt.c (cp_convert): Always call a constructor. -Tue May 10 11:52:04 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * call.c (reference_binding): Still tack on a REF_BIND + for bad conversions. + (build_user_type_conversion_1): Propagate ICS_BAD_FLAG. - * typeck2.c (digest_init): Make sure we check for signed and - unsigned chars as well when warning about string initializers. + * typeck.c (convert_arguments): Pass LOOKUP_ONLYCONVERTING. + (c_expand_return): Likewise. + * typeck2.c (digest_init): Likewise for { }. + * init.c (expand_aggr_init_1): Keep the CONSTRUCTOR handling. + * cvt.c (cp_convert): Handle failure better. - * init.c (emit_base_init): Check if there's a DECL_NAME on the - member before trying to do an initialization for it. +Wed Nov 13 11:51:20 1996 Brendan Kehoe -Tue May 10 11:34:37 1994 Mike Stump + * g++.c (main): Also set PEXECUTE_SEARCH, to make the invocation + of GCC be path-relative. - * except.c: Don't do anything useful when cross compiling. +Wed Nov 13 11:27:16 1996 Michael Meissner -Tue May 10 03:04:13 1994 Jason Merrill (jason@deneb.cygnus.com) + * Make-lang.in (g++-cross): G++-cross doesn't need version.o, but + it does need choose-temp.o and pexecute.o. - * decl.c (duplicate_decls): Fix up handling of builtins yet again. - (push_overloaded_decl): Ditto. +Wed Nov 13 07:53:38 1996 Brendan Kehoe - * cvt.c (convert): Don't look for void type conversion. + * g++.c (error) [!HAVE_VPRINTF]: Put error back for the only time + that we still use it. + (P_tmpdir, R_OK, W_OK, X_OK) [__MSDOS__]: Delete unnecessary macros. -Mon May 9 18:05:41 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Nov 13 02:00:26 1996 Jason Merrill - * init.c (do_friend): Only do a pushdecl for friends, not - pushdecl_top_level. + * init.c (expand_default_init): Avoid calling constructors to + initialize reference temps. -Mon May 9 13:36:34 1994 Jim Wilson (wilson@sphagnum.cygnus.com) + * cvt.c (convert_to_reference): Fix. - * decl.c (lookup_name_current_level): Put empty statement after - the label OUT to make the code valid C. +Tue Nov 12 19:10:07 1996 Jason Merrill -Mon May 9 12:20:57 1994 Jason Merrill (jason@deneb.cygnus.com) + * cvt.c (cp_convert): Simplify for flag_ansi_overloading. + (convert_to_reference): Likewise. + * typeck.c (convert_for_initialization): Likewise. + * init.c (expand_default_init): Likewise. + (expand_aggr_init_1): Likewise. + * cp-tree.h (CONV_NONCONVERTING): Lose. + * typeck.c (build_c_cast): Lose allow_nonconverting parm. + * *.c: Adjust. + * call.c (build_user_type_conversion_1): Assume LOOKUP_ONLYCONVERTING. - * typeck.c (build_binary_op_nodefault): Only complain about - comparing void * and a function pointer if void * is smaller. +Tue Nov 12 16:29:04 1996 Brendan Kehoe -Sun May 8 01:29:13 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (tsubst_expr): Reverse args to expand_start_catch_block. - * decl.c (lookup_name_current_level): Move through temporary binding - levels. +Tue Nov 12 15:26:17 1996 Jason Merrill - * parse.y (already_scoped_stmt): Revive. - (simple_stmt): Use it again. + * init.c (expand_aggr_init_1): Don't crash on non-constructor + TARGET_EXPR. - * decl.c (poplevel): Always call poplevel recursively if we're - dealing with a temporary binding level. +Tue Nov 12 14:00:50 1996 Brendan Kehoe -Sat May 7 10:52:28 1994 Mike Stump + * g++.c: Include gansidecl.h. + (VPROTO, PVPROTO, VA_START): Delete. + (choose_temp_base_try, choose_temp_base, perror_exec, + run_dos) [__MSDOS__]: Delete fns. + (pfatal_with_name): Delete fn. + (temp_filename): Declare like in gcc.c. + (pexecute, pwait, choose_temp_base): Declare from gcc.c. + (error_count, signal_count): Define. + (error): Delete both definitions. + (PEXECUTE_{FIRST,LAST,SEARCH,VERBOSE}): Define from gcc.c. + (pfatal_pexecute): Add fn from gcc.c. + (main): Rename local VERBOSE var to VERBOSE_FLAG. Rewrite the + code to use the pexecute stuff also used by gcc.c. + (MIN_FATAL_STATUS): Define. + * Make-lang.in (g++): Add dependency on and linking with + choose-temp.o and pexecute.o. - * decl.c (finish_decl): Make sure we run cleanups for initial values - of decls. Cures memory leak. - * decl.c (expand_static_init): Ditto for static variables. - * decl2.c (finish_file): Ditto for globals. + * cp-tree.h: Include gansidecl.h. + (STDIO_PROTO): Delete #undef/#define. + * cvt.c (NULL): Delete #undef/#define. + * expr.c (NULL): Likewise. + * init.c (NULL): Likewise. + * rtti.c (NULL): Likewise. + * xref.c (NULL): Likewise. -Sat May 7 03:57:44 1994 Jason Merrill (jason@deneb.cygnus.com) + * cp-tree.h (build_user_type_conversion): Add prototype. + * call.c (build_user_type_conversion): Delete prototype. Correct + decl of FLAGS arg to be an int. + * cvt.c (build_user_type_conversion): Likewise. - * typeck.c (commonparms): Don't complain about redefining default - args. +Tue Nov 12 12:16:20 1996 Jason Merrill - * decl.c (duplicate_decls): Don't complain twice about conflicting - function decls. - (decls_match): Don't look at default args. - (redeclaration_error_message): Complain about redefining default - args. + * cp-tree.def: Add TRY_BLOCK and HANDLER. + * except.c (expand_start_catch_block): Support templates. + * parse.y (try_block, handler_seq): Likewise. + * pt.c (tsubst_expr): Support TRY_BLOCK and HANDLER. - * call.c (build_overload_call_real): Also deal with guiding - declarations coming BEFORE the template decl. +Mon Nov 11 13:57:31 1996 Jason Merrill - * pt.c (unify): Allow different parms to have different - cv-qualifiers. - (unify): Allow trivial conversions on non-template parms. + * pt.c (current_template_args): New fn. + (push_template_decl): Use it. + * decl.c (grokdeclarator): Use it. -Fri May 6 03:53:23 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (build_expr_from_tree): Dereference ref vars. - * pt.c (tsubst): Support OFFSET_TYPEs. - (unify): Ditto. + * decl.c (grokdeclarator): Generalize handling of TYPENAME_TYPEs in + the decl-specifier-seq. - * decl2.c (finish_decl_parsing): Call push_nested_class with a type. + * decl.c (grok_op_properties): Don't force the type of a conversion + op to be complete. Don't warn about converting to the same type + for template instantiations. - * init.c (build_offset_ref): Fix error message. - * search.c (lookup_field): Ditto. + * decl2.c (finish_file): Don't call instantiate_decl on synthesized + methods. - * call.c (build_scoped_method_call): Pass binfo to - build_method_call. - * typeck.c (build_object_ref): Ditto. +Mon Nov 11 13:20:34 1996 Bob Manson - * typeck2.c (binfo_or_else): Don't return a _TYPE. + * typeck.c (get_delta_difference): Remove previous bogusness. + Don't give errors if force is set. - * class.c (finish_struct): Don't complain about re-use of inherited - names or shadowing of type decls. - * decl.c (pushdecl_class_level): Ditto. +Fri Nov 8 17:38:44 1996 Jason Merrill - * decl.c (finish_enum): Set the type of all the enums. + * 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 + template. + * method.c (synthesize_method): For non-local classes, + push_to_top_level first. - * class.c (finish_struct): Don't get confused by access decls. +Fri Nov 8 11:52:28 1996 Bob Manson - * cp-tree.h (TYPE_MAIN_DECL): New macro to get the _DECL for a - _TYPE. You can stop using TYPE_NAME for that now. + * typeck.c (get_delta_difference): Add no_error parameter. + (build_ptrmemfunc): Call get_delta_difference with no_error set; + we don't want error messages when converting unrelated + pointer-to-member functions. - * parse.y: Lose doing_explicit (check $0 instead). - * gxx.gperf: 'template' now has a RID. - * lex.h (rid): Ditto. - * lex.c (init_lex): Set up the RID for 'template'. +Thu Nov 7 11:16:24 1996 Mike Stump - * parse.y (type_specifier_seq): typed_typespecs or - nonempty_type_quals. Use it. - (handler_args): Fix bogus syntax. - (raise_identifier{,s}, optional_identifier): Lose. - * except.c (expand_start_catch_block): Use grokdeclarator to parse - the catch variable. - (init_exception_processing): The second argument to - __throw_type_match is ptr_type_node. + * error.c (dump_expr): Improve the wording on error messages that + involve pointer to member functions. - Fri May 6 07:18:54 1994 Chip Salzenberg (chip@fin) +Tue Nov 5 17:12:05 1996 Mike Stump - [ change propagated from c-decl.c of snapshot 940429 ] - * cp/decl.c (finish_decl): Setting asmspec_tree should not - zero out the old RTL. + * cvt.c (cp_convert_to_pointer): Move code for conversions from + (::*)() to void* or (*)() up a bit, so that we can convert from + METHOD_TYPEs as well. -Fri May 6 01:25:38 1994 Mike Stump +Tue Nov 5 14:54:17 1996 Jason Merrill - Add alpha exception handling support to the compiler. - Quick and dirty backend in except.c. + * rtti.c (get_tinfo_fn): Make sure 'type' is permanent. + There are no 'member' types. + (get_tinfo_fn_dynamic): Diagnose typeid of overloaded fn. + (build_x_typeid): Handle errors. - * cp/*: Remove most remnants of old exception handling support. - * decl.c (finish_function): Call expand_exception_blocks to put - the exception hanlding blocks at the end of the function. - * dec.c (hack_incomplete_structures): Make sure expand_decl_cleanup - comes after expand_decl_init. - * except.c: Reimplementation. - * expr.c (cplus_expand_expr): Handle THROW_EXPRs. - * lex.c (init_lex): Always have catch, try and throw be reserved - words, so that we may always parse exception handling. - * parse.y: Cleanup to support new interface into exception handling. - * tree.def (THROW_EXPR): Add. +Mon Nov 4 17:43:12 1996 Mike Stump -Thu May 5 17:35:37 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (convert_for_assignment): Handle anachronistic implicit + conversions from (::*)() to void* or (*)(). + * cvt.c (cp_convert_to_pointer): Likewise. + (cp_convert_to_pointer_force): Remove cp_convert_to_pointer + conversions from here. + * decl2.c (lang_decode_option): Add -W{no-,}pmf-conversions. + * lang-options.h: Likewise. + * decl2.c (warn_pmf2ptr): Define. + * cp-tree.h: Declare it. + * typeck2.c (digest_init): Allow pmfs down into + convert_for_initialization. - * parse.y (simple_stmt, for loops): Use implicitly_scoped_stmt. - (various): Lose .kindof_pushlevel and partially_scoped_stmt. +Sun Nov 3 09:43:00 1996 Jason Merrill -Thu May 5 16:17:27 1994 Kung Hsu (kung@mexican.cygnus.com) + * typeck.c (c_expand_return): Fix for returning overloaded fn. - * parse.y (already_scoped_stmt): move expand_end_binding() to - fix the unmatched LBB/LBE in stabs. +Fri Nov 1 08:53:17 1996 Jason Merrill -Thu May 5 14:36:17 1994 Jason Merrill (jason@deneb.cygnus.com) + * cp-tree.h (DIRECT_BIND): Change from INDIRECT_BIND. + * decl.c (grok_reference_init): Pass DIRECT_BIND. + * cvt.c (build_up_reference): Don't mark 'this' addressable. Use + DIRECT_BIND. + * call.c (convert_like): Don't pass INDIRECT_BIND. + * typeck.c (convert_arguments): Likewise. + * typeck.c (mark_addressable): Allow &this if flag_this_is_variable. - * decl.c (set_nested_typename): Set TREE_MANGLED on the new - identifiers. - (pushdecl): Check TREE_MANGLED. - (xref_tag): Ditto. - * cp-tree.h (TREE_MANGLED): This identifier is a - DECL_NESTED_TYPENAME (named to allow for future use to denote - mangled function names as well). +Thu Oct 31 17:08:49 1996 Jason Merrill - Implement inconsistency checking specified in [class.scope0]. - * decl.c (lookup_name_real): Don't set ICV here after all. - (finish_enum): Also set the type of the enumerators themselves. - (build_enumerator): Put the CONST_DECL in the list instead of its - initial value. - (pushdecl_class_level): Check inconsistent use of a name in the - class body. - * class.c (finish_struct): Check inconsistent use of a name in the - class body. Don't set DECL_CONTEXT on types here anymore. - * parse.y (qualified_type_name): Note that the identifier has now - been used (as a type) in the class body. - * lex.c (do_identifier): Note that the identifier has now been used - (as a constant) in the class body. - * error.c (dump_decl): Print type and enum decls better. + * typeck.c (mark_addressable): Support TARGET_EXPR, unify with + similar code in build_up_ref. + * cvt.c (build_up_reference): Drastically simplify. -Thu May 5 09:35:35 1994 Brendan Kehoe (brendan@lisa.cygnus.com) +Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com) - * typeck.c (build_modify_expr): Warn about assignment to `this'. + * typeck.c (signed_or_unsigned_type): If the given type already + as the correct signedness, then just return it. -Wed May 4 15:55:49 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c ({un,}signed_type): If can't do anything, call + signed_or_unsigned_type. - * init.c (build_delete): Use the global operator delete when - requested. +Thu Oct 24 14:21:59 1996 Bob Manson - * decl.c (lookup_name_real): If we find the type we're looking in a - base class while defining a class, set IDENTIFIER_CLASS_VALUE for - the type. + * decl2.c (copy_assignment_arg_p): Don't buy the farm if + current_class_type is NULL. - * class.c (finish_struct): Remove a couple of dependencies on - language linkage. +Wed Oct 23 00:43:10 1996 Jason Merrill - * decl.c (pushtag): Classes do nest in extern "C" blocks. - (pushdecl): Only set DECL_NESTED_TYPENAME on the canonical one for - the type. - (pushtag): Remove another dependency on the language linkage. + * class.c (finish_struct_1): Avoid empty structs by adding a field + so layout_type gets the mode right. - * lex.c (cons_up_default_function): Don't set DECL_CLASS_CONTEXT to - a const-qualified type. + * typeck.c (c_expand_return): Drastically simplify. - * decl.c (push_overloaded_decl): Throw away built-in decls here. - (duplicate_decls): Instead of here. +Mon Oct 21 22:34:02 1996 Jason Merrill -Wed May 4 15:27:40 1994 Per Bothner (bothner@kalessin.cygnus.com) + * typeck.c (decay_conversion): Handle overloaded methods. - * typeck.c (get_member_function_from_ptrfunc): Do The Right - Thing (I hope) if we're using thunks. +Fri Oct 18 16:03:48 1996 Jason Merrill -Wed May 4 13:52:38 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_over_call): A TARGET_EXPR has side-effects. - * parse.y (specialization): aggr template_type_name ';'. - (named_class_head_sans_basetype): Use it. - (explicit_instantiation): Ditto. - (tmpl.2): Revert. +Thu Oct 17 11:31:59 1996 Mike Stump - * cvt.c (build_type_conversion_1): Use convert_for_initialization, - rather than convert, to do conversions after the UDC. + * cvt.c (convert_to_pointer_force): Add code to support pointer to + member function to pointer to function conversions. + * init.c (resolve_offset_ref): Add code to allow faked up objects, + ignoring them if they are not used, and giving an error, if they + are needed. + * typeck.c (get_member_function_from_ptrfunc): Fold e1 to improve + code, and so that we can give an error, if we needed an object, + and one was not provided. + (build_c_cast): Don't call default_conversion when we want to + convert to pointer to function from a METHOD_TYPE. - * cp-tree.h (SHARED_MEMBER_P): This member is shared between all - instances of the class. +Mon Oct 14 00:28:51 1996 Jason Merrill - * search.c (lookup_field): If the entity found by two routes is the - same, it's not ambiguous. + * Make-lang.in (cplib2.ready): Fix logic. -Wed May 4 12:10:00 1994 Per Bothner (bothner@kalessin.cygnus.com) + * decl.c (shadow_tag): Only complain about non-artificial function + members. - * decl.c (lookup_name_real): Check for a NULL TREE_VALUE, - to prevent the compiler from crashing ... + * class.c (finish_struct_1): Add synthesized methods to TYPE_METHODS. -Wed May 4 11:19:45 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Oct 11 16:12:40 1996 Jason Merrill - * call.c (build_method_call): If we don't have an object, check - basetype_path to figure out where to look up the function. + * expr.c (cplus_expand_expr): Pre-tweak call_target like + expand_inline_function would. - * typeck.c (convert_for_initialization): Pass TYPE_BINFO (type) to - build_method_call in case exp is NULL_TREE. + * pt.c (mark_decl_instantiated): If extern_p, call + mark_inline_for_output. -Tue May 3 16:02:53 1994 Per Bothner (bothner@kalessin.cygnus.com) +Thu Oct 10 15:58:08 1996 Mike Stump - Give a vtable entries a unique named type, for the sake of gdb. - * class.c (build_vtable_entry): The addres of a thunk now has - type vtable_entry_type, not ptr_type_node. - * method.c (make_thunk): Fix type of THUNK_DECL. - * class.c (add_virtual_function, override_one_vtable): Use - vfunc_ptr_type_node, instead of ptr_type_node. - * cp-tree.h (vfunc_ptr_type_node): New macro. - * decl.c (init_decl_processing): Make vtable_entry_type - be a unique type of pointer to a unique function type. + * typeck.c (unary_complex_lvalue): Add code to handle intermediate + pmd conversions. -Tue May 3 09:20:44 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (get_delta_difference): Fix wording, as we can be used + for pointer to data members. - * parse.y (do_explicit): Sets doing_explicit to 1. - (explicit_instantiation): Use do_explicit rather than TEMPLATE - directly, add "do_explicit error" rule. - (datadef): Set doing_explicit to 0 after an explicit instantiation. - (tmpl.2): Don't instantiate if we see a ';' unless we're doing an - explicit instantiation. - (named_class_head_sans_basetype): Remove aggr template_type_name - ';' again. +Tue Oct 8 12:43:51 1996 Bob Manson -Mon May 2 23:17:21 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (tsubst): If the function decl isn't a member of this + template, return a copy of the decl (including copying the + lang-specific part) so we don't hose ourselves later. - * search.c (lookup_nested_tag): Lose. +Thu Oct 3 16:24:28 1996 Jason Merrill - * decl2.c (grokfield): Set DECL_CONTEXT on TYPE_DECLs. - (lookup_name_nonclass): Lose. + * class.c (finish_struct): Remove DWARF-specific tag handling. + * decl.c (pushtag): Likewise. + (finish_function): Always clear DECL_ARGUMENTS on function decls with + no saved RTX. + * decl2.c (finish_file): Emit DWARF debugging info for static data + members. - * decl.c (poplevel_class): Add force parameter. - (lookup_name_real): Fix handling of explicit scoping which specifies - a class currently being defined. Add 'nonclass' argument. - (lookup_name, lookup_name_nonclass): Shells for lookup_name_real. +Wed Oct 2 21:58:01 1996 Bob Manson - * class.c (finish_struct): Don't unset IDENTIFIER_CLASS_VALUEs here. - (popclass): Force clearing of IDENTIFIER_CLASS_VALUEs if we're being - called from finish_struct. + * decl.c (duplicate_decls): Make sure the old DECL_LANG_SPECIFIC + isn't the same as the new one before we whack it. -Mon May 2 19:06:21 1994 Per Bothner (bothner@kalessin.cygnus.com) +Mon Sep 30 13:38:24 1996 Jason Merrill - * decl.c (init_decl_processing), cp-tree.h: Removed memptr_type. - (It seeems redundant, given build_ptrmemfunc_type.) - * typeck.c (get_member_function_from_ptrfunc), gc.c (build_headof, - build_classof): Use vtable_entry_type instead of memptr_type. - * method.c (emit_thunk): Call poplevel with functionbody==0 - to prevent DECL_INITIAL being set to a BLOCK. + * class.c, cp-tree.h, cvt.c, decl.c, decl2.c, gxx.gperf, hash.h, + lex.c, method.c, parse.y, typeck.c, typeck2.c: Remove + warn_traditional and warn_strict_prototypes; remove ancient + 'overload' code; remove references to flag_traditional. -Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Sep 30 12:58:40 1996 Mike Stump - * parse.y (named_class_head_sans_basetype): Add "aggr - template_type_name ';'" rule for forward declaration of - specializations. + * input.c (sub_getch): Handle 8-bit characters in string literals. -Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com) +Sun Sep 29 03:12:01 1996 Jason Merrill - * class.c (instantiate_type): Deal with pmf's. + * tree.c (mapcar): Handle CONSTRUCTORs. + (copy_to_permanent): Handle expression_obstack properly. - * Make-lang.in (cc1plus): Don't depend on OBJS or BC_OBJS, since - stamp-objlist does. + * Make-lang.in (cplib2.txt): Also depend on the headers. - * Makefile.in (../cc1plus): Depend on OBJDEPS. - (OBJDEPS): Dependency version of OBJS. + * rtti.c (get_tinfo_var): Don't assume that POINTER_SIZE == + INT_TYPE_SIZE. + (expand_class_desc): Use USItype for offset field. + * tinfo.h (struct __class_type_info): Likewise. -Mon May 2 12:51:31 1994 Kung Hsu (kung@mexican.cygnus.com) + * method.c (build_overload_int): TYPE_PRECISION should be applied + to types. - * search.c (dfs_debug_mark): unmark TYPE_DECL_SUPPRESS_DEBUG, not - DECL_IGNORED_P. +Sat Sep 28 14:44:50 1996 Jason Merrill -Fri Apr 29 12:29:56 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_new_op): A COND_EXPR involving void must be a + builtin. - * class.c (finish_struct): Clear out memory of local tags. And - typedefs. +Fri Sep 27 16:40:30 1996 Jason Merrill - * decl2.c (grokclassfn): Don't set DECL_CONTEXT to a cv-qualified - type. - * search.c (get_matching_virtual): Be more helpful in error message. + * typeck.c (build_x_component_ref): New fn. + (build_object_ref): Use it. + * parse.y (primary): Use it. + * decl2.c (build_expr_from_tree): Use it. + * cp-tree.h: Declare it. - * *: Use DECL_ARTIFICIAL (renamed from DECL_SYNTHESIZED). + * decl.c (start_decl): variable-sized arrays cannot be initialized. + * error.c (dump_type_suffix): Handle variable arrays. - * lex.c (default_assign_ref_body): Expect TYPE_NESTED_NAME to work. - (default_copy_constructor_body): Ditto. +Fri Sep 27 13:14:05 1996 Brendan Kehoe - * class.c (finish_struct): Don't gratuitously create multiple decls - for nested classes. + * Make-lang.in (exception.o): Put back compiling it with -fPIC. -Thu Apr 28 23:39:38 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Sep 27 03:00:09 1996 Jason Merrill - Avoid clobbering the arg types of other functions when reverting - static member functions. - * decl.c (revert_static_member_fn): Rearrange arguments, don't - require values for 'fn' and 'argtypes', add warning to comment - above. - (decls_match): Rearrange arguments in call to rsmf. - (grok_op_properties): Don't pass values for fn and argtypes. - * pt.c (instantiate_template): Don't pass values for fn and argtypes. + * decl.c (lookup_name_real): Don't try to look up anything in a + TYPENAME_TYPE. -Thu Apr 28 16:29:11 1994 Doug Evans (dje@canuck.cygnus.com) + * tinfo2.cc (__throw_type_match_rtti): Oops. - * Make-lang.in (cc1plus): Depend on stamp-objlist. - * Makefile.in (BC_OBJS): Delete. - (OBJS): Cat ../stamp-objlist to get language independent files. - Include ../c-common.o. - (../cc1plus): Delete reference to BC_OBJS. +Thu Sep 26 22:11:05 1996 Brendan Kehoe -Thu Apr 28 02:12:08 1994 Jason Merrill (jason@deneb.cygnus.com) + * Make-lang.in (exception.o): Use -fno-PIC for now. - * search.c (compute_access): No really, deal with static members - properly. Would I lie to you? +Thu Sep 26 10:59:00 1996 Jason Merrill - Implement lexical hiding of function declarations. - * pt.c (tsubst): Use lookup_name to look for function decls to guide - instantiation. - * method.c (build_opfncall): Use lookup_name_nonclass to look for - non-member functions. - * init.c (do_friend): Use lookup_name_nonclass to look for - functions. - * error.c (ident_fndecl): Use lookup_name to look for functions. - * decl2.c (lookup_name_nonclass): New function, skips over - CLASS_VALUE. - * decl.c (struct binding_level): Lose overloads_shadowed field. - (poplevel): Don't deal with overloads_shadowed. - (push_overloaded_decl): Do lexical hiding for functions. - * class.c (instantiate_type): Don't check non-members if we have - members with the same name. - * call.c (build_method_call): Use lookup_name_nonclass instead of - IDENTIFIER_GLOBAL_VALUE to check for non-member functions. - (build_overload_call_real): Ditto. - - * decl.c (duplicate_decls): Check for ambiguous overloads here. - (push_overloaded_decl): Instead of here. + * rtti.c (build_dynamic_cast): Pass tinfo fns rather than + calling them. + (get_tinfo_fn_dynamic): Extracted from build_typeid. + * tinfo2.cc (__dynamic_cast): Adjust. - * decl.c (pushdecl): Back out Chip's last change. + * rtti.c (build_typeid): Use resolves_to_fixed_type_p. + (build_x_typeid): Likewise. - * decl.c (grok_op_properties): operators cannot be static members. + * parse.y: Call build_x_typeid instead of build_typeid. + * cp-tree.def: Add TYPEID_EXPR. + * pt.c (tsubst_copy): Handle typeid. + * decl2.c (build_expr_from_tree): Likewise. + * rtti.c (build_x_typeid): Throw bad_typeid from here. + (build_typeid): Not here. + * cp-tree.h: Declare build_x_typeid. - * cp-tree.h (DECL_SYNTHESIZED): DECL_SOURCE_LINE == 0 - (SET_DECL_SYNTHESIZED): DECL_SOURCE_LINE = 0 - * lex.c (cons_up_default_function): Use SET_DECL_SYNTHESIZED. +Wed Sep 25 17:26:16 1996 Jason Merrill - * method.c (do_inline_function_hair): Don't put friends of local - classes into global scope, either. + * call.c (convert_like): Pull out constant values. - * typeck2.c (build_functional_cast): Don't look for a function call - interpretation. + * tree.c (mapcar): Use build_cplus_array_type, not build_array_type. -Thu Apr 28 15:19:46 1994 Mike Stump +Wed Sep 25 17:28:53 1996 Michael Meissner - * cp-tree.h: disable use of backend EH. + * decl.c (init_decl_processing): Create short int types before + creating size_t in case a machine description needs to use + unsigned short for size_t. -Wed Apr 27 21:01:24 1994 Doug Evans (dje@canuck.cygnus.com) +Tue Sep 24 18:18:44 1996 Jason Merrill - * Make-lang.in (c++.distdir): mkdir tmp/cp first. - * Makefile.in (INCLUDES): Move definition to same place as - parent makefile. - (ALLOCA): Define. - (OLDAR_FLAGS): Delete. - (OLDCC): Define. - (DIR): Delete. - (CLIB): Define. - (####site): Delete. - (SUBDIR_USE_ALLOCA): Don't use ALLOCA if compiling with gcc. + * Make-lang.in (exception.o): Turn off pic. -Wed Apr 27 19:10:04 1994 Kung Hsu (kung@mexican.cygnus.com) + * tinfo2.cc (__throw_type_match_rtti): Fix cv-variants of the same + type, multi-level ptr conversions. - * decl.c (xref_tag): not to use strstr(), it's not available on - all platforms. + * rtti.c (call_void_fn): Renamed and genericized from throw_bad_cast. + (throw_bad_cast): Use it. + (throw_bad_typeid): New fn. + (build_typeid): Throw bad_typeid as needed. + Use build_call. + (synthesize_tinfo_fn): Handle functions and arrays before checking + for cv-quals. -Wed Apr 27 18:10:12 1994 Jason Merrill (jason@deneb.cygnus.com) + * Remove .h from standard C++ headers, add new.h, move into inc + subdirectory. - * class.c (finish_struct): Resolve yet another class/pmf confusion. + * exception*: Remove pointer from object, constructors. Add + default exception::what that uses type_info::name. Add + __throw_bad_typeid. - * call.c (build_overload_call_real): Don't take the single-function - shortcut if we're dealing with an overloaded operator. + * init.c (build_new): Don't add a cookie to new (void *) T[2]. -Wed Apr 27 17:35:37 1994 Mike Stump +Mon Sep 23 15:21:53 1996 Jason Merrill - * search.c (get_base_distance): Search the virtual base class - binfos, incase someone wants to convert to a real virtual base - class. - * search.c (expand_indirect_vtbls_init): Use convert_pointer_to_real - instead of convert_pointer_to, as it now will work. + * Make-lang.in: Building C++ code depends on cc1plus. -Wed Apr 27 15:36:49 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Sep 23 12:38:40 1996 Brendan Kehoe - * cvt.c (convert_to_reference): Don't complain about casting away - const and volatile. + * decl.c (struct saved_scope): Declare PROCESSING_TEMPLATE_DECL as + a HOST_WIDE_INT, not a tree. - * typeck.c (build_unary_op): References are too lvalues. +Mon Sep 23 12:36:02 1996 Jason Merrill -Wed Apr 27 13:58:05 1994 Mike Stump + * exception.cc: Don't include . - * class.c (override_one_vtable): We have to prepare_fresh_vtable - before we modify it, not after, also, we cannot reuse an old vtable, - once we commit to a new vtable. Implement ambiguous overrides in - virtual bases as abstract. Hack until we make the class - ill-formed. + * Make-lang.in (c++.clean): Remove cplib2.*. -Wed Apr 27 01:17:08 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Sep 23 09:42:19 1996 Doug Evans - * parse.y (unary_expr): Expand new_placement[opt] and - new_initializer[opt] inline. + * parse.y (component_decl_1, component_costructor_declarator case): + Pass attributes/prefix_attributes in tree list. - * search.c (lookup_fnfields): Don't throw away the inheritance - information here, either. - (compute_access): Handle static members properly. +Mon Sep 23 01:18:50 1996 Jason Merrill - * init.c (build_member_call): Always set basetype_path, and pass it - to lookup_fnfields. + * tinfo{,2}.cc: #include instead of . - * search.c (lookup_field): Deal properly with the case where - xbasetype is a chain of binfos; don't throw away the inheritance - information. - (compute_access): protected_ok always starts out at 0. +Sun Sep 22 05:31:22 1996 Jason Merrill - * init.c (resolve_offset_ref): Don't cast `this' to the base type - until we've got our basetype_path. + * lex.c (do_identifier): Don't do deferred lookup in a template + header. - * cp-tree.h (IS_OVERLOAD_TYPE): aggregate or enum. + * typeck2.c (store_init_value): Oops. - * cvt.c (build_up_reference): Use build_pointer_type rather than - TYPE_POINTER_TO. + * 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. + And rules for building the C++ lang-support code. + * config-lang.in (headers): Define. + (lib2funcs): Define. - * call.c (convert_harshness_ansi): Call type_promotes_to for reals - as well. +Sat Sep 21 19:17:28 1996 Jason Merrill - * cvt.c (type_promotes_to): Retain const and volatile, add - float->double promotion. - - * decl.c (grokdeclarator): Don't bash references to arrays into - references to pointers in function parms. Use type_promotes_to. + * decl2.c (build_expr_from_tree): If CONSTRUCTOR has a type, call + digest_init. + * pt.c (tsubst_copy): Compute type for CONSTRUCTOR. + * typeck2.c (store_init_value): Check for initializing pmf with { } + here. + (process_init_constructor): Not here. -Tue Apr 26 23:44:36 1994 Mike Stump +Thu Sep 19 16:41:07 1996 Jason Merrill - Finish off Apr 19th work. + * pt.c (begin_template_parm_list): Increment + processing_template_decl here. + (end_template_parm_list): Not here. + (process_template_parm): No need to add 1 to it now. + * *.c: Use processing_template_decl instead of current_template_parms + to check for being in a template. - * class.c (finish_struct_bits): Rename has_abstract_virtuals to - might_have_abstract_virtuals. - * class.c (strictly_overrides, override_one_vtable, - merge_overrides): New routines to handle virtual base overrides. - * class.c (finish_struct): Call merge_overrides to handle overrides - in virtual bases. + * pt.c (uses_template_parms): Handle SCOPE_REF. Fix CONSTRUCTOR. + (tsubst_copy): Handle CONSTRUCTOR. + (instantiate_decl): Set up context properly for variables. + * decl2.c (build_expr_from_tree): Handle CONSTRUCTOR. + * class.c (finish_struct): Reverse CLASSTYPE_TAGS. -Tue Apr 26 12:45:53 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Sep 18 13:30:20 1996 Brendan Kehoe - * typeck.c (build_function_call): Call build_function_call_real with - LOOKUP_NORMAL. + * lex.c (enum tree_node_kind) [GATHER_STATISTICS]: Put the enum back. - * *: Don't deal with TYPE_EXPRs. +Wed Sep 18 04:24:07 1996 Jason Merrill - * tree.c (lvalue_p): If the type of the expression is a reference, - it's an lvalue. + * method.c (make_thunk): Call comdat_linkage before setting the + TREE_CODE. - * cvt.c (convert_to_reference): Complain about passing const - lvalues to non-const references. - (convert_from_reference): Don't arbitrarily throw away const and - volatile on the target type. + * decl2.c (comdat_linkage): Use make_decl_one_only. + (import_export_decl): Likewise. + * decl.c (init_decl_processing): Check supports_one_only instead of + SUPPORTS_WEAK. - * parse.y: Simplify and fix rules for `new'. +Sat Sep 14 08:34:41 1996 Jason Merrill - * decl.c (grok_op_properties): operator void is illegal. + * decl2.c (grokfield): Tighten checking for access decls. -Mon Apr 25 02:36:28 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (make_typename_type): Resolve references to + current_class_type. Set CLASSTYPE_GOT_SEMICOLON. + (lookup_name_real): Types that depend on a template parameter get + an implicit 'typename' unless they're in the current scope. + (start_decl_1): We don't care about incomplete types that depend + on a template parm. + (grokdeclarator): Resolve 'typename's in the type specifier that + refer to members of the current scope. - * parse.y (components): Anonymous bitfields can still have declspecs. + * call.c (build_over_call): Remove 'inline called before + definition' diagnostic. + (build_method_call): Likewise. + * decl.c (duplicate_decls): Downgrade 'used before declared + inline' to a warning, only with -Winline. - * decl.c (pushdecl): Postpone handling of function templates like we - do C functions. +Fri Sep 13 17:31:40 1996 Stan Shebs - * search.c (expand_indirect_vtbls_init): Fix infinite loop when - convert_pointer_to fails. + * mpw-make.sed: Fix include paths, add @DASH_C_FLAG@ to compile. - * call.c (compute_conversion_costs_ansi): A user-defined conversion - by itself is better than that UDC followed by standard conversions. - Don't treat integers and reals specially. +Wed Sep 11 22:38:13 1996 Gerald Baumgartner - * cp-tree.h: Declare flag_ansi. + * call.c (build_method_call): When calling a signature + default implementation, as in other cases, let instance_ptr simply + be instance. - * typeck.c (c_expand_return): pedwarn on return in void function - even if the expression is of type void. - (build_c_cast): Don't do as much checking for casts to void. - (build_modify_expr): pedwarn about array assignment if this code - wasn't generated by the compiler. +Wed Sep 11 22:14:44 1996 Mike Stump - * tree.c (lvalue_p): A comma expression is an lvalue if its second - operand is. + * parse.y (simple_stmt): Cleanup and use do_poplevel (). - * typeck.c (default_conversion): Move code for promoting enums and - ints from here. - * cvt.c (type_promotes_to): To here. - * call.c (convert_harshness_ansi): Use type_promotes_to. Also fix - promotion semantics for reals. +Wed Sep 11 22:10:48 1996 Mike Stump -Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com) + * except.c (expand_start_catch_block): Add a pushlevel so that -g + works on hppa and SPARC. - * Make-lang.in (c++.install-common): Check for g++-cross. - * Makefile.in: Remove Cygnus cruft. - (config.status): Delete. - (RTL_H): Define. - (TREE_H): Use complete pathname, some native makes have minimal - VPATH support. - (*.o): Use complete pathname to headers in parent dir. - (doc, info, dvi): Delete. +Wed Sep 11 10:18:06 1996 Brendan Kehoe -Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com) + * typeck.c (build_indirect_ref): Catch PTR being an error_mark_node. - * Make-lang.in (c++.install-common): Check for g++-cross. - * Makefile.in: Remove Cygnus cruft. - (config.status): Delete. - (RTL_H): Define. - (TREE_H): Use complete pathname, some native makes have minimal - VPATH support. - (*.o): Use complete pathname to headers in parent dir. - (doc, info, dvi): Delete. +Mon Sep 9 19:51:14 1996 Gerald Baumgartner -Sun Apr 24 00:47:49 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_over_call): Check first whether DECL_CONTEXT exists + before testing whether it's a signature. - * decl.c (pushdecl): Avoid redundant warning on redeclaring function - with different return type. - (decls_match): Compare return types strictly. +Sun Sep 8 16:06:57 1996 Gerald Baumgartner -Fri Apr 22 12:55:42 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_new_method_call): Don't complain about signature + pointers and references not being an aggr type. + (build_this): If a signature pointer or reference was passed in, + just return it. + (build_new_method_call): If instance is a signature pointer, set + basetype to the signature type of instance. + * sig.c (build_signature_method_call): Deleted basetype and + instance parameters, they can be found as the DECL_CONTEXT of + function and as the first argument passed in. + * cp-tree.h: Changed declaration of build_signature_method_call. + * call.c (build_method_call): Deleted first two arguments in call + of build_signature_method_call. + (build_over_call): Added call to build_signature_method_call. - * cvt.c (build_type_conversion): Do try to convert through other - pointers. This will fail if the class defines multiple pointer - conversions. +Thu Sep 5 16:51:28 1996 Jason Merrill + + * typeck.c (build_c_cast): Don't tack a non_lvalue_expr onto a + target_expr. + +Thu Sep 5 10:05:38 1996 Brendan Kehoe + + * cvt.c (convert_to_reference): Use %#T, not %#D, for error. + +Wed Sep 4 17:16:09 1996 Bob Manson + + * except.c (expand_start_try_stmts): Move to except.c in the backend. + (expand_end_try_stmts): Remove. + + * init.c (perform_member_init): Use add_partial_entry () instead + of directly manipulating lists. + (emit_base_init): Ditto. + +Wed Sep 4 12:14:36 1996 Mike Stump - * error.c (dump_type_prefix): Print out pointers to arrays properly. - (dump_type_suffix): Ditto. (was 'int *[]', now 'int (*)[]') + * except.c (expand_exception_blocks): Always make sure USE and + CLOBBER insns that came at the end still do, the backend relies + upon this. - * typeck.c (build_unary_op): Disallow ++/-- on pointers to - incomplete type. +Wed Sep 4 07:44:48 1996 Jason Merrill + + * call.c (build_over_call): We can only use a TARGET_EXPR of the + right type. + +Tue Sep 3 19:26:05 1996 Jason Merrill + + * cvt.c (convert_to_reference): Revert last change, don't complain + about temp without target decl. + +Tue Sep 3 10:22:56 1996 Mike Stump + + * decl.c (grokdeclarator): Don't core dump when void() is given. + +Tue Sep 3 02:38:56 1996 Jason Merrill + + * decl.c (copy_args_p): Don't crash. + +Fri Aug 30 14:26:57 1996 Mike Stump + + * pt.c (tsubst): And support template args inside the exception + specification. + + * pt.c (tsubst): Add support for exception specifications in + template functions. + +Fri Aug 30 10:01:55 1996 Mike Stump + + * cp-tree.def (DECL_STMT): Eliminate the throw spec field, only 3 + fields now. + * cp-tree.h (start_decl): Eliminate the throw spec parameter. + (start_function): Likewise. + (start_method): Likewise. + (grokfield): Likewise. + (make_call_declarator): Add throw spec parameter. + (set_quals_and_spec): Add routine. + * lex.c (set_quals_and_spec): Likewise. + * decl.h (grokdeclarator): Eliminate the throw spec parameter. + * decl.c (shadow_tag): Eliminate the throw spec parameter to + grokdeclarator. + (groktypename): Likewise. + (start_decl): Eliminate the throw spec parameter. Eliminate the + throw spec parameter to grokdeclarator. Eliminate the throw spec + field in DECL_STMT. + (cp_finish_decl): Eliminate the throw spec field in DECL_STMT. + (grokfndecl): Remove useless set of raises. + (grokdeclarator): Eliminate the throw spec parameter. Eliminate + the throw spec parameter to start_decl. Pull the throw spec out + of the call declarator. + (grokparms): Eliminate the throw spec parameter to grokdeclarator. + (start_function): Eliminate the throw spec parameter. Eliminate + the throw spec parameter to grokdeclarator. + (start_method): Likewise. + * decl2.c (grokfield): Likewise. + (grokbitfield): Eliminate the throw spec parameter to grokdeclarator. + (grokoptypename): Likewise. + (finish_file): Eliminate the throw spec parameter to + start_function. Add throw spec to make_call_declarator. + * except.c (init_exception_processing): Add throw spec to + make_call_declarator. Eliminate the throw spec parameter to + start_decl. + (expand_start_catch_block): Eliminate the throw spec parameter to + grokdeclarator. + (expand_builtin_throw): Add throw spec to make_call_declarator. + Eliminate the throw spec parameter to start_function. + (start_anon_func): Likewise. + * lex.c (make_call_declarator): Add throw spec parameter. + (set_quals_and_spec): New routine. + (cons_up_default_function): Add throw spec to make_call_declarator. + Eliminate the throw spec parameter to grokfield. + * method.c (synthesize_method): Eliminate the throw spec parameter + to start_function. + * pt.c (process_template_parm): Eliminate the throw spec parameter + to grokdeclarator. + (tsubst): Add throw spec to make_call_declarator. + (tsubst_expr): Eliminate the throw spec parameter to start_decl. + (do_function_instantiation): Eliminate the throw spec parameter to + grokdeclarator. Eliminate the throw spec parameter to + start_function. + * rtti.c (synthesize_tinfo_fn): Eliminate the throw spec parameter + to start_function. + * parse.y (datadef): Remove non-winning optimization. + (decl): Likewise. + (fndef): Remove ambiguous error productions uncovered by grammer + fixing. + (constructor_declarator): Add exception_specification_opt here. + (component_constructor_declarator): Likewise. + (direct_after_type_declarator): Likewise. + (complex_direct_notype_declarator): Likewise. + (direct_abstract_declarator): Likewise. + (fn.def1): Remove exception_specification_opt. + (fn.def2): Likewise. + (condition): Likewise. + (initdcl0): Likewise. + (initdcl): Likewise. + (notype_initdcl0): Likewise. + (nomods_initdcl0): Likewise. + (component_decl_1): Likewise. + (component_declarator): Likewise. + (after_type_component_declarator0): Likewise. + (after_type_component_declarator): Likewise. + (notype_component_declarator): Likewise. + +Wed Aug 28 01:40:30 1996 Jason Merrill + + * call.c (build_over_call): Also use an INIT_EXPR when + initializing anything from an rvalue. + + * call.c (build_over_call): Call stabilize_reference when building + an INIT_EXPR instead of calling the copy ctor. + + * call.c (joust): Extend the previous change to all comparisons. + + * 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. + + * typeck.c (build_static_cast): Implement. + * tree.c (build_cplus_new): Handle getting a TARGET_EXPR. + * decl.c (grokparms): Use can_convert_arg instead of + implicit_conversion directly. + (copy_args_p): New fn. + * cvt.c (convert_to_reference): Don't complain about temp with + static_cast. + (build_up_reference): Handle TARGET_EXPRs. + * call.c (build_over_call): Elide unnecessary temps. + (can_convert*): Use new overloading code. + +Tue Aug 27 13:12:21 1996 Jason Merrill + + * call.c: Move TYPE_PTR*_MACROS ... + * cp-tree.h: To here. + * typeck.c (build_reinterpret_cast): Implement. + + * call.c (add_builtin_candidate): Use TYPE_PTROB_P instead of + ptr_complete_ob. + (joust): If we're comparing a function to a builtin and the worst + conversion for the builtin is worse than the worst conversion for the + function, take the function. + + * typeck.c (build_const_cast): Implement. + (comp_ptr_ttypes_const): Like comp_ptr_ttypes, for const_cast. + (comp_ptr_ttypes_reinterpret): Like cpt, for reinterpret_cast. + +Tue Aug 27 13:14:58 1996 Bob Manson + + * rtti.c (build_dynamic_cast): Don't try to dereference exprtype + 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 + + * cp-tree.h: New routine make_call_declarator. + * lex.c (make_call_declarator): Define it. + * except.c (init_exception_processing): Use it. + (expand_builtin_throw): Likewise. + (start_anon_func): Likewise. + * decl2.c (finish_file): Likewise. + * lex.c (cons_up_default_function): Likewise. + * parse.y: Likewise. + * pt.c (tsubst): Likewise. + +Mon Aug 26 17:40:03 1996 Mike Stump - * decl.c (duplicate_decls): Check mismatched TREE_CODES after - checking for shadowing a builtin. If we're redeclaring a builtin - function, bash the old decl to avoid an ambiguous overload. + * decl2.c (groktypefield): Remove unused code. - * cvt.c (convert_to_reference): Don't force arrays to decay here. +Mon Aug 26 17:00:33 1996 Mike Stump - * tree.c (lvalue_p): A MODIFY_EXPR is an lvalue. + * gxx.gperf: Change TYPE_QUAL into CV_QUALIFIER. + * parse.y: Likewise. Change maybe_type_qual into maybe_cv_qualifier. + 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 - * decl.c (duplicate_decls): Don't assume that the decls will have - types. + * decl.c (start_function): Only check interface_* for templates + with flag_alt_external_templates. - Mon Apr 18 11:35:32 1994 Chip Salzenberg (chip@fin.uucp) + * call.c (build_new_op): Check for comparison of different enum types. + (build_over_call): Fix arg # output. - [ cp/* changes propagated from c-* changes in 940318 snapshot ] - * c-decl.c (pushdecl): Warn if type mismatch with another external decl - in a global scope. + * typeck.c (build_component_ref): Handle pre-found TYPE_DECL. - Fri Apr 22 06:38:56 1994 Chip Salzenberg (chip@fin.uucp) +Wed Aug 21 00:13:15 1996 Jason Merrill - * cp/typeck2.c (signature_error): Use cp_error for "%T". + * call.c (build_new_op): Check for erroneous args. - Mon Apr 18 11:59:59 1994 Chip Salzenberg (chip@fin.uucp) + * call.c (build_new_method_call): Add missing args to cp_error. - [ cp/* changes propagated from c-* changes in 940415 snapshot ] - * cp/decl.c (duplicate_decls, pushdecl, builtin_function): - Use DECL_FUNCTION_CODE instead of DECL_SET_FUNCTION_CODE. + * tree.c (error_type): Dont print reference-to-array. - Mon Apr 18 11:55:18 1994 Chip Salzenberg (chip@fin.uucp) + * typeck.c (convert_for_assignment): Don't say contravariance for + removing const. - [ cp/* changes propagated from c-* changes in 940409 snapshot ] - * cp/decl.c (duplicate_decls): Put new type in same obstack as - old ones, or permanent if old ones in different obstacks. +Tue Aug 20 13:23:00 1996 Jason Merrill - Mon Apr 18 11:48:49 1994 Chip Salzenberg (chip@fin.uucp) + * call.c (build_over_call): Diagnose bad convs for `this'. - [ cp/* changes propagated from c-* changes in 940401 snapshot ] - * cp/parse.y (attrib): Handle string args as expressions, - merging the two rules. `mode' attribute now takes a string arg. - Delete the rule for an identifier as arg. + * lex.c (cons_up_default_function): Set DECL_ARTIFICIAL + on _ctor_arg. - Mon Apr 18 11:24:00 1994 Chip Salzenberg (chip@fin.uucp) + * call.c (convert_like): Handle bad convs. + (build_over_call): Handle bad convs better. - [ cp/* changes propagated from c-* changes in 940312 snapshot ] - * cp/typeck.c (pointer_int_sum): Multiplication should be done signed. - (pointer_diff): Likewise the division. + * decl2.c: -fansi-overloading is now the default. - Sun Mar 6 19:43:39 1994 Chip Salzenberg (chip@fin.uucp) + * call.c (build_new_method_call): Check for erroneous args. - [ cp/* changes propagated from c-* changes in 940304 snapshot ] - * cp/decl.c (finish_decl): Issue warning for large objects, - if requested. + * pt.c (instantiate_class_template): Propagate + TYPE_USES_MULTIPLE_INHERITANCE. - Sat Feb 19 22:20:32 1994 Chip Salzenberg (chip@fin.uucp) +Tue Aug 20 13:09:57 1996 Mike Stump - [ cp/* changes propagated from c-* changes in 940218 snapshot ] - * cp/parse.y (attrib): Handle attribute ((section ("string"))). - * cp/decl.c (duplicate_decls): Merge section name into new decl. + * call.c (enforce_access): Add static to routine. - Tue Feb 8 09:49:17 1994 Chip Salzenberg (chip@fin.uucp) +Sun Aug 18 14:35:54 1996 Jason Merrill - [ cp/* changes propagated from c-* changes in 940206 snapshot ] - * cp/typeck.c (signed_or_unsigned_type): Check for any - INTEGRAL_TYPE_P not just INTEGER_TYPE. + * call.c (build_user_type_conversion_1): Fix bad handling. + (compare_ics): Likewise. - Mon Dec 6 13:35:31 1993 Norbert Kiesel (norbert@i3.INformatik.rwth-aachen.DE) +Sat Aug 17 21:54:11 1996 Jason Merrill - * cp/decl.c (finish_enum): Start from 0 when determining precision - for short enums. + * call.c (standard_conversion): Oops. - Fri Dec 3 17:07:58 1993 Ralph Campbell (ralphc@pyramid.COM) +Sat Aug 17 16:28:11 1996 Geoffrey Noer - * cp/parse.y (unary_expr): Look at $1 for tree_code rather than - casting $$. + * g++.c: Update test for win32 (&& ! cygwin32). - Wed Nov 17 19:22:09 1993 Chip Salzenberg (chip@fin.uucp) +Sat Aug 17 03:45:31 1996 Jason Merrill - * cp/typeck.c (build_binary_op_nodefault): Propagate code - from C front-end to optimize unsigned short division. - (build_conditional_expr): Fix bug in "1 ? 42 : (void *) 8". + * typeck.c (comp_ptr_ttypes_real): Handle OFFSET_TYPEs properly. + (ptr_reasonably_similar): New fn. + * call.c (BAD_RANK): New rank. + (ICS_BAD_FLAG): New macro. + (standard_conversion): Handle almost-right pointer conversions. + (reference_binding): Handle bad rvalue bindings. + (add_*_candidate): Stuff. + (build_over_call): Pass bad conversions to convert_for_initialization. + (compare_ics): Handle bad convs. + (joust): Likewise. - Wed Nov 17 19:17:18 1993 Chip Salzenberg (chip@fin.uucp) +Fri Aug 16 15:02:19 1996 Bob Manson - * cp/call.c (convert_harshness_ansi): Given an (e.g.) char - constant, prefer 'const char &' to 'int'. + * init.c (expand_vec_init): Use ptrdiff_type_node instead of + integer_type_node when computing pointer offsets. - Wed Feb 3 13:11:48 1993 Chip Salzenberg (chip@fin.uucp) +Fri Aug 16 01:28:32 1996 Jason Merrill - * cp/class.c (finish_struct_methods): Handle multiple - constructors in fn_fields list. + * tree.c (lvalue_type): New fn. + (error_type): New fn. + * call.c (op_error): Use error_type. + (add_conv_candidate): Use lvalue_type. + (add_builtin_candidates): Likewise. + * error.c (args_as_string): Use error_type. -Fri Apr 22 12:48:10 1994 Kung Hsu (kung@mexican.cygnus.com) +Thu Aug 15 17:27:13 1996 Jason Merrill - * class.c (finish_struct): use TYPE_DECL_SUPPRESS_DEBUG to flag - types not to be dumped in stabs, like types in #pragma interface. - * decl.c (init_decl_processing): use TYPE_DECL_SUPPRESS_DEBUG to - mark unknown type. + * pt.c (instantiate_decl): Evaluate DECL_INITIAL of a VAR_DECL here. + (tsubst): Not here. -Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com) + * decl.c (init_decl_processing): With -ansi, __null's type is the + signed integral type with the same number of bits as a pointer. + Introduce a new variable null_node for it. + * cp-tree.h: Adjust. + * call.c (null_ptr_cst_p): Adjust. - * Language directory reorganization. - See parent makefile. +Thu Aug 15 17:09:54 1996 Mike Stump -Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com) + * except.c (do_unwind): Mark %i7 as used on the SPARC so we can + optimize. - * cp-tree.h (THUNK_DELTA): It is normally negative, so - use signed .i variant of frame_size rather than unsigned .u. - * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks, - use "VT" rather than "vt" due to binary incompatibility. - * class.c (get_vtable_name): Use strlen of VTABLE_NAME_FORMAT, - rather than sizeof, since it is now an expression. - * class.c (modify_one_vtable): Modify to skip initial element - containing a count of the vtable. +Thu Aug 15 01:36:49 1996 Jason Merrill -Thu Apr 21 00:09:02 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (import_export_decl): Ignore #pragma interface for tinfo + fns of classes without virtual functions. - * lex.c (check_newline): Force interface_unknown on main input file. + * call.c (add_function_candidate): Handle `this' specially. + (compare_ics): Likewise. - * pt.c (do_pending_expansions): Always emit functions that have been - explicitly instantiated. - (do_function_instantiation): Set DECL_EXPLICITLY_INSTANTIATED. - (do_type_instantiation): Set CLASSTYPE_VTABLE_NEEDS_WRITING and - DECL_EXPLICITLY_INSTANTIATED on all my methods. - * parse.y (explicit_instantiation): Call do_type_instantiation for - types. - * decl2.c (finish_vtable_vardecl): Call import_export_vtable. - * decl.c (start_function): Don't set DECL_EXTERNAL on a function - that has been explicitly instantiated. - * cp-tree.h (DECL_EXPLICITLY_INSTANTIATED): Alias for - DECL_LANG_FLAG_4. - * class.c: Move import_export_vtable to decl2.c, and comment out all - uses. - -Wed Apr 20 16:51:06 1994 Jason Merrill (jason@deneb.cygnus.com) - - * lex.c (process_next_inline): Don't muck with DECL_INLINE. - (do_pending_inlines): Ditto. - -Tue Apr 19 22:25:41 1994 Mike Stump - - Reimplement vtable building, and most vtable pointer setting. - Allows for earier maintenance, easier understandability, and most - importantly, correct semantics. - - * class.c (build_vtable): Removed unneeded - SET_BINFO_VTABLE_PATH_MARKED. - * class.c (prepare_fresh_vtable): Ditto. Added argument. - * class.c (modify_vtable_entry): General cleanup. - * class.c (related_vslot, is_normal, modify_other_vtable_entries, - modify_vtable_entries): Removed. - * class.c (add_virtual_function): General cleanup. - * class.c (finish_base_struct): Setup BINFO_VTABLE and - BINFO_VIRTUALS as early as we can, so that modify_all_vtables can - work. - * class.c (finish_vtbls): New routine, mostly from - unmark_finished_struct. - * class.c (overrides): New routine. - * class.c (modify_one_vtable): New routine, mostly from - modify_other_vtable_entries and modify_vtable_entries. - * class.c (modify_all_direct_vtables, modify_all_indirect_vtables, - modify_all_vtables): New routines. - * class.c (finish_struct): Added arguemnt to prepare_fresh_vtable - call. General cleanup on how pending_hard_virtuals are handled. - General cleanup on modifying vtables. Use finish_vtbls, instead of - unmark_finished_struct. - * cp-tree.h (init_vtbl_ptrs, expand_direct_vtbls_init, - get_first_matching_virtual, get_matching_virtual, - expand_vbase_vtables_init, expand_indirect_vtbls_init): Update. - * cvt.c (convert_pointer_to_real): cleanup error message. - * decl.c (grokfndecl): General cleanup. - * decl.c (finish_function): Change init_vtbl_ptrs call to - expand_direct_vtbls_init. Change expand_vbase_vtables_init call to - expand_indirect_vtbls_init. - * init.c (expand_virtual_init): Remove unneeded argument. - * init.c (init_vtbl_ptrs): Rename to expand_direct_vtbls_init, added - two arguments to make more general. Made more general. Now can be - used for vtable pointer initialization from virtual bases. - * init.c (emit_base_init): Change expand_vbase_vtables_init call to - expand_indirect_vtbls_init. Change init_vtbl_ptrs call to - expand_direct_vtbls_init. - * init.c (expand_virtual_init): General cleanup. - * init.c (expand_default_init): Change expand_vbase_vtables_init - call to expand_indirect_vtbls_init. - * init.c (expand_recursive_init_1): Change expand_vbase_vtables_init - call to expand_indirect_vtbls_init. - * init.c (expand_recursive_init): Change expand_vbase_vtables_init - call to expand_indirect_vtbls_init. - * search.c (get_first_matching_virtual): Rename to - get_matching_virtual. General cleanup and remove setting of - DECL_CONTEXT. That is now done in a cleaner way in - modify_vtable_entry and add_virtual_function. - * search.c (expand_vbase_vtables_init): Rename to - expand_indirect_vtbls_init. General cleanup. Use - expand_direct_vtbls_init to do hard work. Ensures that _all_ vtable - pointers from virtual bases are set up. - * search.c (bfs_unmark_finished_struct, unmark_finished_struct): - Removed. - - * *.[chy]: Remove support for VTABLE_USES_MASK. - -Tue Apr 19 12:51:59 1994 Jason Merrill (jason@deneb.cygnus.com) - - * cvt.c (convert_to_reference): Use NOP_EXPRs to switch between - reference and pointer types instead of bashing the types directly. - - * call.c (build_overload_call_real): Use the TREE_CODE to determine - whether the function is overloaded or not, rather than - TREE_OVERLOADED. - * *: Remove all uses of TREE_OVERLOADED. - - * decl.c (grokdeclarator): Only complain about initializing const - fields when -ansi or -pedantic. - -Tue Apr 19 12:42:42 1994 Doug Evans (dje@canuck.cygnus.com) - - * cp-tree.h (THUNK_DELTA): frame_size is now a union. - -Mon Apr 18 00:17:13 1994 Jason Merrill (jason@deneb.cygnus.com) - - Do overloading on a block-by-block basis, not function-by-function. - * decl.c: Lose overloads_to_forget. - (struct binding_level): Add overloads_shadowed field. - (poplevel): Restore overloads_shadowed. - (push_overloaded_decl): Use overloads_shadowed instead of - overloads_to_forget. - (finish_function): Don't look at overloads_to_forget. - - Copy enum_overflow logic from c-decl.c. - * decl.c (start_enum): Initialize enum_overflow. - (build_enumerator): Use enum_overflow. Also use current_scope(). - - * search.c (current_scope): Move Brendan's comment from - build_enumerator here. - - * typeck.c (convert_for_assignment): Change warnings to pedwarns for - discarding const/volatile. - -Sat Apr 16 01:18:21 1994 Jason Merrill (jason@deneb.cygnus.com) - - * typeck.c (comp_target_parms): Accept TEMPLATE_TYPE_PARMs on the rhs. - (comp_target_types): Ditto. - - * decl.c (lookup_name): Don't unset got_scope here. - - * spew.c (yylex): Only replace yylval with the TYPE_NESTED_NAME if - got_scope != NULL_TREE. - -Fri Apr 15 16:36:33 1994 Jason Merrill (jason@deneb.cygnus.com) - - Horrible kludge to prevent templates from being instantiated by - their base classes. - * parse.y (template_instantiate_once): Unset TYPE_BEING_DEFINED - before we get to left_curly. - * pt.c (instantiate_class_template): Set TYPE_BEING_DEFINED. - - * error.c (dump_decl): If it's a typedef, print out the name of the - decl, not just the underlying type. - - * decl.c (pushdecl): If the old duplicate decl was a TYPE_DECL, - update the IDENTIFIER_TYPE_VALUE of its name. - - * decl2.c (finish_file): When processing the initializer for a - static member, pretend that the dummy function is a member of the - same class. - -Fri Apr 15 15:56:35 1994 Kung Hsu (kung@mexican.cygnus.com) - - * class.c (build_vtable_entry): revert Apr 4 change. - * decl2.c (mark_vtable_entries): replace pure virtual function - decl with abort's. +Tue Aug 13 12:16:10 1996 Jason Merrill -Fri Apr 15 13:49:33 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (build_conditional_expr): Fix handling of __null. - * typeck.c (build_conditional_expr): Pedwarn on pointer/integer - mismatch, and don't pedwarn on 0/function pointer mismatch. + * decl2.c (comdat_linkage): New fn. + (import_export_vtable): Use it. + (import_export_decl): Use it. + * method.c (make_thunk): Use it. - * typeck2.c (digest_init): Lose code for special handling of unions. - (process_init_constructor): Since they're handled just fine here. - Pedwarn on excess elements. +Mon Aug 12 00:09:18 1996 Jason Merrill - * decl2.c (grokfield): Complain about local class method declaration - without definition. + * pt.c (end_template_decl): If we don't actually have parms, return. + * parse.y (template_header): Accept 'template <>'. -Fri Apr 15 13:19:40 1994 Per Bothner (bothner@kalessin.cygnus.com) + * errfn.c: Allow 5 args. - * method.c (emit_thunk): Add extern declaration for - current_call_is_indirect (needed for hppa). +Sun Aug 11 15:20:58 1996 Jason Merrill -Thu Apr 14 16:12:31 1994 Jason Merrill (jason@deneb.cygnus.com) + * tree.c (make_temp_vec): New fn. + * pt.c (push_template_decl): Handle partial specs. + (instantiate_class_template): Likewise. + (more_specialized): Use get_bindings. + (more_specialized_class): New fn. + (get_class_bindings): New fn. + (most_specialized_class): New fn. + (do_function_instantiation): List candidates for ambiguous case. + * decl.c (duplicate_decls): Lose reference to DECL_TEMPLATE_MEMBERS. + (shadow_tag): Call push_template_decl for partial specializations. + * parse.y: Likewise. + * cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Replaces + DECL_TEMPLATE_MEMBERS. + * call.c (print_z_candidates): Reduce duplication. - Improve local class support; allow classes in different blocks to - have the same name. - * decl.c (pushtag): Support local classes better. - (pushdecl_nonclass_level): New function for pushing mangled decls of - nested types into the appropriate scope. - (xref_defn_tag): Use pushdecl_nonclass_level instead of - pushdecl_top_level. - (grokfndecl): Don't mess with IDENTIFIER_GLOBAL_VALUE for local - class methods. - * method.c (do_inline_function_hair): Ditto. +Fri Aug 9 14:36:08 1996 Jason Merrill - * class.c (finish_struct): It is legal for a class with no - constructors to have nonstatic const and reference members. + * decl2.c (lang_decode_option): Allow -fansi-overloading. -Thu Apr 14 07:15:11 1994 Brendan Kehoe (brendan@lisa.cygnus.com) +Thu Aug 8 17:04:18 1996 Jason Merrill - * decl.c (push_overloaded_decl): Avoid giving errors about - built-ins, since duplicate_decls will have given warnings/errors - for them. + * pt.c (get_bindings): New fn. + (most_specialized): Likewise. + (do_function_instantiation): Use them. + (add_maybe_template): New fn. + * cp-tree.h (DECL_MAYBE_TEMPLATE): New macro. + * call.c (build_new_op): Handle guiding decls. + (build_new_function_call): Likewise. + * decl2.c (finish_file): Likewise. -Thu Apr 14 03:45:12 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (mark_used): Do synthesis here. + * call.c (build_method_call): Not here. + (build_over_call): Or here. + * typeck.c (build_function_call_real): Or here. + * tree.c (bot_manip): Call mark_used on functions used in default + args. - * cvt.c (convert_to_reference): Warn about casting pointer type to - reference type when this is probably not what they wanted. +Thu Aug 8 17:48:16 1996 Michael Meissner -Wed Apr 13 13:12:35 1994 Per Bothner (bothner@kalessin.cygnus.com) + * decl2.c (import_export_vtable): Delete code that disabled vtable + heuristic on systems with ASM_OUTPUT_EXTERNAL. - * decl.c (finish_decl): Don't mindlessly set TREE_USED for - static consts any more (toplev.c has now been modified to - not emit warnings if they are unused). +Wed Aug 7 12:44:11 1996 Jason Merrill -Wed Apr 13 00:22:35 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (build_x_function_call): Handle static call context + better. - * decl.c (grok_op_properties): If op new/delete get here with - METHOD_TYPEs, do a revert_static_member_fn. + * decl.c (finish_function): Set the DECL_CONTEXT of the result to + the function, not its outer block. - * cp-tree.h (IDENTIFIER_CLASS_TYPE_VALUE): Lose. - * init.c (is_aggr_typedef): Don't look at - IDENTIFIER_CLASS_TYPE_VALUE. - (get_aggr_from_typedef): Ditto. - (get_type_value): Ditto. - * call.c (build_scoped_method_call): Don't rely on overloaded - template names having IDENTIFIER_CLASS_VALUE set. + * call.c (build_field_call): Pass fields on to build_opfncall + regardless of TYPE_OVERLOADS_CALL_EXPR. + (build_method_call): Pass on to build_new_method_call sooner. - * parse.y (component_decl_1, fn.def2): Revert rules for - constructors. - (component_decl_1, fn.def2): Use $1 instead of $$, since $$ is being - clobbered. + * typeck.c (build_ptrmemfunc): Just return what instantiate_type + gives us. + * class.c (instantiate_type): Don't put a POINTER_TYPE to + METHOD_TYPE on an expression. Also make a copy of rhs instead of + modifying it. - * decl.c (start_function): Only warn about `void main()' if pedantic - || warn_return_type. +Tue Aug 6 12:58:46 1996 Jason Merrill -Tue Apr 12 02:14:17 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (compare_ics): Handle qual_conv after lvalue_conv. + (add_builtin_candidate): Don't take enums for ++. + (build_new_method_call): Handle non-aggregates and field calls. + Move new overloading code from... + * cvt.c: Here. - Clean up overloading of the template name. - * class.c (pushclass): overload the template name whenever pushing - into the scope of a template class, not just if it is - uninstantiated. - (popclass): Correspondingly. - * search.c (push_class_decls): Don't overload_template_name. - * pt.c (overload_template_name): Don't set IDENTIFIER_LOCAL_VALUE or - DECL_CONTEXT on things. - * parse.y (left_curly): Don't overload_template_name. - * class.c (finish_struct): Don't undo_template_name_overload. + * decl.c (grokparms): Don't check default args in templates. - * method.c (build_opfncall): Only pass one argument to global op - delete. +Mon Aug 5 17:17:06 1996 Jason Merrill - * call.c (build_method_call): Use TYPE_VEC_DELETE_TAKES_SIZE to - decide how many arguments to use for vec delete. + * cvt.c (build_new_op): Fix args to build_unary_op. + (add_builtin_candidates): Don't call type_promotes_to on float. - * decl.c (grok_op_properties): Be consistent in modifying - current_class_type. - (grokdeclarator): Only complain about function decls with no return - type if we're being pedantic. - -Mon Apr 11 00:10:53 1994 Jason Merrill (jason@deneb.cygnus.com) - - Add support for operator new [] and operator delete []. - - * tree.def: Add VEC_NEW_EXPR and VEC_DELETE_EXPR. - * ptree.c (print_lang_type): Indicate vec new/delete. - * parse.y: Support vec new/delete. - * method.c (build_decl_overload): Deal with vec new/delete. - (build_opfncall): Ditto. - * lex.c (init_lex): Set up values of ansi_opname and opname_tab for - vec new/delete. vec new uses "__vn", and vec delete uses "__vd". - * init.c (init_init_processing): Set up BIVN and BIVD. - (do_friend): Don't clean up after mistaken setting of TREE_GETS_NEW, - since it doesn't happen any more. - (build_new): Support vec new. Always call something. - (build_x_delete): Support vec delete. - (build_vec_delete): Lose dtor_dummy argument, add use_global_delete, - and pass it to build_x_delete. - * decl2.c (delete_sanity): Don't change behavior by whether or not - the type has a destructor. Pass use_global_delete to - build_vec_delete. - (coerce_delete_type): Make sure that the type returned has a first - argument of ptr_type_node. - * decl.c (init_decl_processing): Also declare the global vec - new/delete. - (grokdeclarator): Also force vec new/delete to be static. - (grok_op_properties): Note presence of vec new/delete, and play with - their args. If vec delete takes the optional size_t argument, set - TYPE_VEC_DELETE_TAKES_SIZE. - * cp-tree.h (TYPE_GETS_{REG,VEC}_DELETE): New macros to simplify - checking for one delete or the other. - (lang_type): gets_new and gets_delete are now two bits long. The - low bit is for the non-array version. Lose gets_placed_new. - (TYPE_VEC_DELETE_TAKES_SIZE): New macro indicating that the vec - delete defined by this class wants to know how much space it is - deleting. - (TYPE_VEC_NEW_USES_COOKIE): New macro to indicate when vec new must - add a header containing the number of elements in the vector; i.e. - when the elements need to be destroyed or vec delete wants to know - the size. - * class.c (finish_struct_methods): Also check for overloading vec - delete. - * call.c (build_method_call): Also delete second argument for vec - delete. + * decl.c (grokparms): Check the type of the default arg. - * decl.c (grokdeclarator): Correct complaints again. - (grokdeclarator): Fix segfault on null declarator. - (decls_match): Also accept redeclaration with no arguments if both - declarations were in C context. Bash TREE_TYPE (newdecl) here. - (duplicate_decls): Instead of here. + * cvt.c (build_new_op): Pass non-overloaded cases on rather than + returning NULL_TREE. - * parse.y (nested_name_specifier_1): Lose rules for dealing with - syntax errors nicely, since they break parsing of 'const i;'. + * typeck.c (build_x_binary_op): Avoid doing extra work. + (build_x_unary_op): Likewise. + (build_x_conditional_expr): Likewise. + * cvt.c (build_over_call): Return. + (add_builtin_candidate): Fix MEMBER_REF. + (build_new_op): Likewise. - * decl.c (lookup_name): if (got_scope == current_class_type) - val = IDENTIFIER_CLASS_VALUE (name). +Mon Aug 5 17:07:47 1996 Mike Stump - * search.c (lookup_nested_tag): Look in enclosing classes, too. + * method.c (build_overload_name): Put bug fix into code but leave + disabled for now so we can be bug compatible with older releases + that do repeats incorrectly. In the future, we can enable it. - * spew.c (yylex): Only look one character ahead when checking for a - SCOPE. +Mon Aug 5 13:46:28 1996 Jason Merrill - * lex.c (check_newline): Read first nonwhite char before - incrementing lineno. + * cvt.c (convert_like): Don't call build_cplus_new twice. - * decl.c (grokdeclarator): Don't claim that typedefs are variables - in warning. + * call.c, cp-tree.h, cvt.c, decl2.c, init.c, method.c, pt.c, typeck.c: + Control new overloading code with -fansi-overloading. - * parse.y: Divide up uses of unqualified_id into - notype_unqualified_id and unqualified_id, so that TYPENAME can be - used as an identifier after an object. +Sun Aug 4 15:29:11 1996 Jason Merrill - * class.c (push_nested_class): Don't push into non-class scope. + * cvt.c (build_over_call): Call build_cplus_new. + * call.c (build_method_call): Likewise. + * typeck.c (build_function_call_real): Likewise. + (build_conditional_expr): If both operands are TARGET_EXPRs, wrap + the COND_EXPR in a TARGET_EXPR so they use the same slot. - * decl.c (grokdeclarator): If an identifier could be a type - conversion operator, but has no associated type, it's not a type - conversion operator. + * cvt.c (build_up_reference): Propagate INDIRECT_BIND to + recursive calls. + * typeck.c (complete_type): Propagate + TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}. - * pt.c (unify): Check for equality of constants better. +Sat Aug 3 14:05:07 1996 Jason Merrill - * decl.c (grokdeclarator): Don't complain about access decls. + * cvt.c (joust): More ?: kludging. Sigh. + (build_over_call): Don't try to synthesize global fns. -Sun Apr 10 02:39:55 1994 Jason Merrill (jason@deneb.cygnus.com) + * search.c (lookup_conversions): Use binfo marking. - * decl.c (grokdeclarator): pedwarn about data definitions without - types here. +Sat Aug 3 12:33:42 1996 Bob Manson - * parse.y (datadef): Don't pedwarn about decls without types here, - since that is valid for functions. - (fn.def2, component_decl): Support constructors with declmods again. - (nomods_initdecls): For decls without any mods, so that we don't try - to get declspecs from some arbitrary $0. + * search.c (build_mi_matrix): Use the correct value of cid + when determining the new mi_size. - * search.c (lookup_field): Use cp_error. +Sat Aug 3 01:27:41 1996 Jason Merrill - * parse.y (nested_name_specifier_1): Don't check aggr/non-aggr type - here; it breaks destructors for non-aggr types. + * cvt.c (add_builtin_candidates): Do consider type conversion ops + for the first parms of += et al. + (strip_top_quals): New fn. + (reference_binding): Use it instead of TYPE_MAIN_VARIANT. + (implicit_conversion): Likewise. + (add_builtin_candidates): Be careful about arrays. + (build_new_method_call): Handle vtable optimization. - * decl.c (lookup_name): Only look for TYPE_DECLs in base classes of - a type being defined, like the comment says. - If got_scope is not an aggregate, just return NULL_TREE. +Fri Aug 2 01:26:59 1996 Jason Merrill - * pt.c (create_nested_upt): Kung's code for creating types nested - within uninstantiated templates now lives here (it used to live in - hack_more_ids). It needs to be expanded. + * cp-tree.h (LOOKUP_NO_TEMP_BIND): New flag. + * cvt.c (reference_binding): Use it. + (implicit_conversion): Use it. + (add_builtin_candidate, COND_EXPR): Use it. - * parse.y: Stop calling see_typename so much. + * cvt.c (build_new_function_call): Check for error args. - * decl.c (lookup_name): Deal with TTPs and UPTs. + * typeck.c (comptypes): Just check DERIVED_FROM_P, not UNIQUELY. - * lex.c (real_yylex): Don't set looking_for_typename just because we - saw a 'new'. - (dont_see_typename): #if 0 out. + * gxx.gperf: Add __null. + * hash.h: Regenerate. + * lex.h: Add RID_NULL. + * lex.c (init_lex): Create null_pointer_node here, stick it in + RID_NULL. + * decl.c (init_decl_processing): Still set its type here. + * cvt.c (cp_convert_to_pointer): Don't produce null_pointer_node. + (convert_to_pointer_force): Likewise. + (null_ptr_cst_p): Check for null_pointer_node; only accept (void*)0 + if (! pedantic). + * call.c (convert_harshness): Use null_ptr_cst_p. + * typeck.c (convert_for_assignment): Likewise. Don't produce + null_pointer_node. - * spew.c (yylex): Increment looking_for_typename if the next - character is SCOPE, rather than setting it to 1; this way, the value - from seeing an aggr specifier will not be lost. This kinda relies - on looking_for_typename never being < 0, which is now true. + * error.c (args_as_string): Handle lists of actual args, too. + * cvt.c (null_ptr_cst): Support (void*)0 for now. + (build_user_type_conversion_1): Improve diagnostics. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_method_call): Likewise. Move call before def diagnostic... + (build_over_call): Here. - * parse.y (nested_name_specifier_1): Accept TEMPLATE_TYPE_PARMs, - too. - (named_class_head_sans_basetype): Accept template types, too. Oops. + * cvt.c (build_new_method_call): Don't complain about no match if + LOOKUP_SPECULATIVELY. + (build_over_call): Fix 'this' for virtual fn. + (build_new_method_call): Add diagnostic. -Fri Apr 8 16:39:35 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Aug 1 16:45:09 1996 Jason Merrill - * decl2.c (reparse_decl_as_expr1): Handle SCOPE_REFs. + * cvt.c (add_function_candidate): Expect 'this' and 'in_chrg' for + constructors to be passed in. + (build_over_call): Likewise. + (build_user_type_conversion_1): Pass them in. + (convert_like): Likewise. + (build_object_call): Handle overloaded conversions. + (build_over_call): Pass the right args to build_vfn_ref. + (standard_conversion): Fix pmf convs. + (joust): Handle comparing statics and non-statics. + (build_new_method_call): New fn. + * call.c (build_method_call): Call it if NEW_OVER. - * parse.y: Lose START_DECLARATOR. +Thu Aug 1 16:06:14 1996 Mike Stump - * search.c (lookup_nested_tag): New function to scan CLASSTYPE_TAGS - for a class. + * lex.c (do_identifier): Don't use %O on IDENTIFIER_OPNAME_Ps, use + %D instead. - * parse.y: Simplify fn.def2 and component_decl. Support 'enum - A::foo' syntax. Catch invalid scopes better. +Thu Aug 1 15:24:02 1996 Mike Stump - * parse.y, lex.c: lose TYPENAME_COLON. + * except.c (expand_throw): Use maybe_build_cleanup_and_delete + instead of just maybe_build_cleanup so that we deallocate the + thrown object. - * decl2.c (groktypefield): #if 0 out. +Thu Aug 1 15:18:00 1996 Brendan Kehoe - * decl.c (lookup_name): If the type denoted by got_scope is - currently being defined, look in CLASSTYPE_TAGS rather than FIELDS. + * decl2.c (finish_prevtable_vardecl): Make non-static for pt.c's use. + * cp-tree.h (finish_prevtable_vardecl): Add decl. - * class.c (push_nested_class): Don't try to push into - error_mark_node. +Thu Aug 1 11:53:51 1996 Bob Manson -Fri Apr 8 07:26:36 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + * 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. - * Makefile.in (stamp-parse): Update count of conflicts to 33. + * error.c (dump_decl): Don't explode (or explode more gracefully + as appropriate) if the object being dumped has a null type. + (dump_expr): Likewise. -Thu Apr 7 17:47:53 1994 Jason Merrill (jason@deneb.cygnus.com) + * search.c (build_mi_matrix): Ensure that mi_size is large enough, + by counting the number of nodes that we'll need before allocating + the array. + (lookup_fnfields): Fix comment. + (breadth_first_search): Fix comment. - A saner implementation of nested types that treats template types - no differently from non-template types. There are still some - shortcomings of our system; most notably, it is difficult to look - for a nested type that is hidden by another name, because of the way - we keep track of hidden types. But this shouldn't be a problem for - just about anyone. Perhaps lookup_field should be fixed up a bit. +Wed Jul 31 09:57:05 1996 Jason Merrill - * spew.c: Moved handling of nested types/scoping from the lexer - into the parser. Removed variable template_type_seen_before_scope. - Removed functions frob_identifier, hack_more_ids, and various cruft - that was #if 0'd out in the past, reducing the size of the file from - 1146 lines to 450 lines. We can't quite do away with spew.c yet, - though; we still need it for do_aggr () and checking for SCOPE after - the current identifier. And setting lastiddecl. + * pt.c (instantiate_class_template): Propagate TYPE_PACKED and + TYPE_ALIGN. + * class.c (finish_struct): Call cplus_decl_attributes here. + (finish_struct_1): Not here. + * cp-tree.h: Adjust. - * parse.y: Moved handling of nested types/scoping from the lexer - into the parser, using a new global variable `got_scope'. Reduced - the number of states by 53. Implemented all uses of explicit global - scope. Removed terminals SCOPED_TYPENAME and SCOPED_NAME. Removed - nonterminals tmpl.1, scoped_base_class, id_scope, typename_scope, - scoped_typename. Added nonterminals nested_type, - qualified_type_name, complete_type_name, qualified_id, ptr_to_mem, - nested_name_specifier, global_scope, overqualified_id, type_name. - Changed many others. Added 9 new reduce/reduce conflicts, which are - nested type parallels of 9 that were already in the grammar for - non-nested types. Eight of the now 33 conflicts should be removed - in the process of resolving the late binding between variable and - function decls. + * pt.c (type_unification): New parameter STRICT. + (unify): If STRICT, don't allow cv addition or base deduction. + * call.c, class.c, cvt.c, cp-tree.h: Adjust. - * gxxint.texi (Parser): Update. +Tue Jul 30 13:06:13 1996 Jason Merrill - * cp-tree.h (IS_AGGR_TYPE_CODE): Add UNINSTANTIATED_P_TYPE. + * search.c (get_template_base{_recursive}): New fns. + * pt.c (more_specialized): New fn. + (do_function_instantiation): Use it. + (unify): Handle base deduction. + * cvt.c (joust): Use more_specialized. + Don't arbitrarily choose between non-builtin candidates. + (build_over_call): Call require_complete_type. - * lex.h: Add decl for got_scope. + * decl.c (start_function): Statics are static even in a #pragma + interface file. - * lex.c (see_typename): Claim to be the lexer when calling - lookup_name. + * decl2.c (import_export_vtable): Disable vtable heuristic on + systems with ASM_OUTPUT_EXTERNAL. - * decl.c (lookup_name): When called from the lexer, look at - got_scope and looking_at_typename; otherwise don't. + * cvt.c (compare_ics): Fix comparison of PMEM_CONV and BASE_CONV. + (standard_conversion): No std conv to enum type. -Thu Apr 7 22:05:47 1994 Mike Stump + * cvt.c (standard_conversion): Fix order of args to DERIVED_FROM_P + for ptm's. - 31th Cygnus<->FSF merge. + * cvt.c (reference_binding): Bind directly to a base subobject of + a class rvalue. -Thu Apr 7 17:47:53 1994 Jason Merrill (jason@deneb.cygnus.com) + * cvt.c (build_new_op): Enforce access control. - * decl2.c (mark_vtable_entries): Call this to mark all the - entries in the vtable addressable. - (finish_decl_parsing): Handle SCOPE_REFs. +Tue Jul 30 09:22:53 1996 Bob Manson - * decl.c (decls_match): Always call compparms with strict == 1. - Handle the special case of C function redecl here. - (duplicate_decls): Only keep the old type if the new decl takes no - arguments. + * typeck2.c (process_init_constructor): When scanning the + union for a named field, skip things that aren't FIELD_DECLs. - * typeck.c (compparms): Also allow t1 to be ... if strict == 0. + * method.c (synthesize_method): Don't scan fndecl's rtl if + we're at the end of the file; just assume the function can't + be inlined. -Thu Apr 7 16:17:50 1994 Mike Stump +Mon Jul 29 15:48:30 1996 Jason Merrill - * class.c (build_vtable_entry): Fix breakage introduced Apr 5 - 17:48:41. + * cvt.c (build_builtin_candidate): Stick a dummy conversion in if + it failed. -Wed Apr 6 16:05:10 1994 Per Bothner (bothner@kalessin.cygnus.com) + * cvt.c (build_user_type_conversion_1): Handle overloaded + conversion ops. - * init.c (build_virtual_init), search.c (build_vbase_vtables_init), - ch-tree.h: Every place these functions were called, the result was - immediately passed to expand_expr_stmt. Reduce redundancy by - calling expand_expr_init *inside* these functions. These - makes for a simpler interface, and we don't have to build - compound expressions. Hence, rename these function to: - expand_virtual_init and expand_vbase_vtables_init respectively. - * init.c, decl.c: Change callers of these functions. - * init.c, cp-tree.h (expand_virtual_init): Make static. + * cvt.c (add_builtin_candidates): Don't consider type conversion + operators for the first parameter of operator=. - * decl2.c (finish_file): Check TREE_PUBLIC||TREE_ADDRESSABLE - rather than DECL_SAVED_INSNS before emitting inlines. +Mon Jul 29 15:33:55 1996 Bob Manson -Wed Apr 6 13:06:39 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (complete_type): Only call layout_type if we're not + expanding a template. - * spew.c (init_spew): #if 0 out stuff used by arbitrate_lookup. +Mon Jul 29 14:40:38 1996 Jason Merrill - * decl.c (duplicate_decls): If this is a new declaration of an - extern "C" function, keep the type (for the argtypes). - (redeclaration_error_message): Don't check DECL_LANGUAGE here. - (decls_match): Call compparms with a value of strict dependent on - the value of strict_prototypes for DECL_LANGUAGE (oldecl). + * cvt.c (compare_ics): Oops. - * typeck.c (compparms): ... is only equivalent to non-promoting - parms if we're not being strict. + * cvt.c (op_error): Oops. - * parse.y (empty_parms): Don't check flag_ansi || pedantic here. + * cp-tree.def: Add RVALUE_CONV, rename EXACT_CONV to IDENTITY_CONV. + * cvt.c: Add IDENTITY_RANK before others. Use real_lvalue_p. + (build_conv): Use them. + (implicit_conversion): Use them. + (convert_like): Handle them. + (build_new_op): Handle builtin COND_EXPR again. + (add_builtin_candidates): Strip cv-quals. Fix oops. Include enums + in lists of types for COND_EXPR. + (add_builtin_candidate): Add enum candidates for COND_EXPR. - * decl.c (init_decl_processing): if (flag_ansi || pedantic) - strict_prototypes_lang_c = strict_prototypes_lang_cplusplus; +Mon Jul 29 12:05:40 1996 Bob Manson - * decl2.c (grok_function_init): Don't set DECL_INITIAL on pure - virtuals. + * typeck.c (build_modify_expr): Always attempt to build a call to + the assignment operator, even if we're using a default one. + (convert_for_initialization): Call complete_type. -Tue Apr 5 17:48:41 1994 Per Bothner (bothner@kalessin.cygnus.com) +Mon Jul 29 11:25:08 1996 Jason Merrill - Support for implementing vtables with thunks. - * tree.def (THUNK_DECL): New TREE_CODE. - * cp-tree.h (FNADDR_FROM_VTABLE_ENTRY), tree.c - (fnaddr_from_vtable_entry): Handle flag_vtable_thunks case. - * cp-tree.h (memptr_type): New variable. - * class.c (build_vtable_entry): Build thunk if necessary. - * class.c (build_vfn_ref): If using thunks, don't need - to add delta field from vtable (there is none!). - * decl.c: Add memptr_type as well as vtable_entry_type. - If using thunks, the latter is just ptr_type_node. - * gc.c, typeck.c: Use memptr_typeChange, not vtable_entry_type. - * decl2.c (finish_vtable_vardecl): Handle thunks. - * expr.c (cplus_expand_expr): Support THUNK_DECL. + * cvt.c (reference_binding): A REF_BIND gets the reference type. + (implicit_conversion): Likewise. + (convert_like): Likewise. + (compare_ics): Likewise. + (compare_qual): Likewise. + (print_z_candidates): Handle no candidates. + (build_new_op): Don't handle builtin COND_EXPR for now. - * decl.c (grokdeclarator): Set DECL_THIS_EXTERN if "extern". - * decl.c (start_function): Set current_extern_inline based on - DECL_THIS_EXTERN, not TREE_PUBLIC. - * decl.c (finish_function): Call mark_inline_for_output if needed, +Sat Jul 27 11:27:47 1996 Stan Shebs - Improve intelligence about when to emit inlines. - * cp-tree.h (lang_decl_flags): New field saved_inline. - * cp-tree.h (DECL_SAVED_INLINE): New macro. - * class.c (add_virtual_function): Don't set TREE_ADDRESSABLE. - * decl.h, decl.c (pending_addressable_inlines): Removed. - * decl2.c (pending_addressable_inlines): Renamed to saved_inlines. - * decl2.c (mark_inline_for_output): Do nothing if - DECL_SAVED_INLINE; otherwise set it (and add to saved_inlines list). - * decl2.c (finish_vtable_vardecl): SET_CLASSTYPE_INTERFACE_KNOWN - and set CLASSTYPE_INTERFACE_ONLY if there is a non-inline virtual. - * decl2.c (finish_file): Writing out inlines later, so we can - also handle the ones needed for vtbales. - * decl2.c (write_vtable_entries, finish_vtable_typedecl): Removed. + * cvt.c (build_builtin_candidate): Init local var in an ANSI way. - * cp-tree.h, class.c, decl2.c, search.c: Remove -fvtable-hack - and flag_vtable_hack. Use -fvtable-thunks and flag_vtable_thunks - instead. (The rationale is that these optimizations both break binary - compatibility, but should become the default in a future release.) +Fri Jul 26 01:07:22 1996 Jason Merrill -Wed Apr 6 10:53:56 1994 Mike Stump + * cvt.c (joust): If the candidates are the same, arbitrarily pick one. - * class.c (modify_vtable_entries): Never reset the DECL_CONTEXT - of a fndecl, as we might not be from that vfield. + * cvt.c (build_builtin_candidate): Oops. + (build_new_op): Oops. -Tue Apr 5 17:43:35 1994 Kung Hsu (kung@mexican.cygnus.com) + * method.c (build_opfncall): Pass COND_EXPR on. + * cvt.c (build_builtin_candidate): Reorganize, support COND_EXPR. + (add_builtin_candidate{,s}): Likewise. + (add_builtin_candidates): Likewise. + (print_z_candidates, op_error, build_new_op): Likewise. + (type_decays_to): New fn. + * lex.c (init_lex): Just say ?: for COND_EXPR. - * class.c (add_virtual_function): fix bug for pure virtual, so - that DECL_VINDEX of the dummy decl copied won't be error. - (see also Apr 4 change) +Thu Jul 25 09:33:33 1996 Jason Merrill -Tue Apr 5 17:23:45 1994 Per Bothner (bothner@kalessin.cygnus.com) + * typeck.c (complete_type): Call layout_type rather than building + a new array type. - * typeck.c (c_expand_return): Before checking that we're not - returning the address of a local, make sure it's a VAR_DECL. - (And don't worry about it being a TREE_LIST.) + * cvt.c (add_builtin_candidate): Pointer arithmetic candidates + only use ptrdiff_t. -Tue Apr 5 13:26:42 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Jul 24 12:45:08 1996 Jason Merrill - * parse.y (YYDEBUG): Always define. - * lex.c (YYDEBUG): Ditto. + * cvt.c: Always compile the new overloading code (but don't use it). + (implicit_conversion): Add a BASE_CONV when converting to + the same class type. + (convert_like): Handle BASE_CONV. -Mon Apr 4 11:28:17 1994 Kung Hsu (kung@mexican.cygnus.com) +Tue Jul 23 12:46:30 1996 Jason Merrill - * class.c (finish_struct): backup out the change below, put the - new change for the same purpose. The change below breaks code. + * cvt.c (build_new_op): Support {MAX,MIN}_EXPR. + (add_builtin_candidate): Likewise. - * class.c (finish_struct): if pure virtual, copy node and make - RTL point to abort, then put in virtual table. - * decl2.c (grok_function_iit): reinstate Mar 31 change. - -Sat Apr 2 03:12:58 1994 Jason Merrill (jason@deneb.cygnus.com) - - * init.c (build_new): pedwarn about newing const and volatile - types. - - * tree.c (get_identifier_list): Only do the special handling - thing if we're dealing with the main variant of the record type. - - * cvt.c (convert_to_reference): When converting between - compatible reference types, use the pointer conversion machinery. - Don't just blindly overwrite the old type. - -Fri Apr 1 17:14:42 1994 Jason Merrill (jason@deneb.cygnus.com) + NEW_OVER changes: + * typeck.c (build_x_function_call): Try an operator function + whenever we call an object of class type. + * method.c (build_opfncall): Pass CALL_EXPRs through. + * 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 + builtin candidates. + (build_new_op): Handle CALL_EXPR. Don't try to decay void. + Fall back on preincrement handling. Use op_error. + Handle warn_synth. + (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. - * call.c (build_method_call): When looking at global functions, - be sure to use instance_ptr for the first argument, not some version - of it that has been cast to a base class. Also do this before - comparing candidates. +Mon Jul 22 16:21:55 1996 Bob Manson -Thu Mar 31 19:50:35 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (tsubst_expr): Handle CONTINUE_STMT. - * call.c (build_method_call): Constructors can be called for - const objects. +Mon Jul 22 15:38:58 1996 Mike Stump -Thu Mar 31 16:20:16 1994 Kung Hsu (kung@mexican.cygnus.com) + * typeck.c (build_component_ref_1): Use build_component_ref + instead of open coding it here. - * decl2.c (grok_func_init): do not abort as rtl for pur virtual - fucntions. They can be defined somewhere else. +Mon Jul 22 12:18:54 1996 Jason Merrill -Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) + * g++.c (main): Don't link with -lg++. - * decl.c (init_decl_processing): Declare __builtin_return_address - and __builtin_frame_address for C++ as well. + NEW_OVER changes: + * cvt.c (convert_to_reference): Don't use convert_from_refeence on + result of build_type_conversion. + (cp_convert): Only call build_method_call for ctors if + build_type_conversion failed. + (ptr_complete_ob): New function. + (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 + 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. + (build_new_op): New function. + (build_over_call): Fix handling of methods. + (compare_ics): Handle AMBIG_CONV properly. + * typeck2.c: Increment abort count. + * method.c (build_opfncall): Forward most requests to build_new_op. + * cp-tree.h (IS_OVERLOAD_TYPE): Tweak. -Thu Mar 31 12:35:49 1994 Mike Stump +Fri Jul 19 17:59:29 1996 Brendan Kehoe - * typeck2.c (store_init_value): Integral constant variables are - always constant, even when doing -fpic. + * error.c (dump_expr, case CONSTRUCTOR, case CAST_EXPR): Take out + invalid second argument to dump_expr_list. -Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) +Fri Jul 19 14:04:05 1996 Mike Stump - * decl.c (redeclaration_error_message): Pass the types to - comptypes. + * decl.c (lookup_name_real): Make sure we do obj->X::i correctly. -Wed Mar 30 21:29:25 1994 Mike Stump +Thu Jul 18 14:48:23 1996 Bob Manson - Cures incorrect errors about pure virtuals in a class, when they - have been overridden in a derived class. + * decl2.c (import_export_vtable): ASM_OUTPUT_EXTERNAL, not + ASSEMBLE_EXTERNAL. - * search.c (get_abstract_virtuals): Reimplement. - * search.c (get_abstract_virtuals_1): New routine. +Mon Jul 15 17:48:43 1996 Mike Stump -Wed Mar 30 14:10:04 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck2.c (process_init_constructor): New pedwarn for using { } + to initialize a pointer to member function. + * typeck.c (build_ptrmemfunc1): Avoid use of digest_init so that + we can avoid the new error. - * pt.c (push_template_decls): Make the pushed level pseudo - global. +Mon Jul 15 15:42:03 1996 Mike Stump - * parse.y (extdefs): Don't pop everything if the current binding - level is pseudo_global. + * typeck.c (build_ptrmemfunc1): New function to hide details of + pointer to member functions better. - * decl.c (pop_everything): Stop on reaching a pseudo-global - binding level. +Mon Jul 15 14:23:02 1996 Mike Stump - * cp-tree.h (DECL_FUNCTION_MEMBER_P): Change to more reliable test. + * init.c (resolve_offset_ref): Resolve OFFSET_REFs that are + methods into the actual method, as we know the implied object is + not used. - * decl.c (duplicate_decls): Only copy DECL_SOURCE_{FILE_LINE} if - the old decl actually had an initializer. +Mon Jul 15 13:08:29 1996 Brendan Kehoe - * {various}: Clean up gcc -W complaints. + * parse.y (maybecomma_warn): Only emit the pedwarn if we're not + inside a system header. - * cp-tree.h (DECL_FUNCTION_MEMBER_P): Currently defined to be - (DECL_CONTEXT (NODE) != NULL_TREE). +Fri Jul 12 16:30:05 1996 Bob Manson - * parse.y (lang_extdef): Call pop_everything if necessary. + * call.c (build_method_call): Call complete_type on the + instance type. - * decl.c (pop_everything): New function for popping binding - levels left over after a syntax error. - (pushdecl): Use DECL_FUNCTION_MEMBER_P to decide whether or not - a function is a member. +Thu Jul 11 17:16:40 1996 Mike Stump -Wed Mar 30 14:20:50 1994 Mike Stump + * typeck.c (build_component_ref): Always build up an OFFSET_REF + for obj_ptr->func so that we can know which object to use in a + method call. - Cures calling a more base base class function, when a more derived - base class member should be called in some MI situations. +Wed Jul 10 19:36:37 1996 Mike Stump - * search.c (make_binfo): Use more the more specialized base - binfos from the binfo given as the second argument to make_binfo, - instead of the unspecialized ones from the TYPE_BINFO. - * class.c (finish_base_struct): Ditto, update callers. - * search.c (dfs_get_vbase_types): Ditto. - * tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto. - * decl.c (xref_tag): Use NULL_TREE instead of 0. - * lex.c (make_lang_type): Ditto. + * typeck.c (build_ptrmemfunc): Remove sorry, now we can cast + around things. Also improve maintainability. -Wed Mar 30 14:10:04 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Jul 10 18:20:11 1996 Bob Manson - * decl.c (pushdecl): If pushing a C-linkage function, only do a - push_overloaded_decl. - (duplicate_decls): Standard overloading does not shadow built-ins. + * decl.c (grokdeclarator): Check for overflow when evaluating an + array dimension. -Tue Mar 29 00:54:18 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Jul 10 17:26:19 1996 Jason Merrill - * pt.c (end_template_decl): Don't call push_overloaded_decl. + * cvt.c (cp_convert): Don't check for ambiguity with constructor + if NEW_OVER. - * init.c (do_friend): Don't call push_overloaded_decl. + * typeck.c (build_x_function_call): Pass function overload + questions to new overloading code if NEW_OVER. + * init.c (expand_aggr_init_1): Only check for type conversion ops + if we're doing copy-initialization (i.e. LOOKUP_ONLYCONVERTING). + Don't check for ambiguity with constructor if NEW_OVER. + * cvt.c (convert_to_reference): Dereference the result of a type + conversion operator. + (build_conv): Propagate ICS_USER_FLAG. + (implicit_conversion): Call instantiate_type. + Pass LOOKUP_ONLYCONVERTING instead of LOOKUP_NORMAL. + (add_function_candidate): Fix cv-quals on argtype. + (print_z_candidates): New function. + (build_new_function_call): Call it. + (build_user_type_conversion_1): If LOOKUP_ONLYCONVERTING, don't + consider non-converting constructors. + Call print_z_candidates. + Return an AMBIG_CONV for an ambiguous conversion. + (build_user_type_conversion): Handle AMBIG_CONV. + (convert_like): Fix test for building TARGET_EXPR. + Call instantiate_type. + Handle AMBIG_CONV and LVALUE_CONV. + (build_over_call): Handle 0 args and ellipsis. + * cp-tree.def: Add AMBIG_CONV. + +Tue Jul 9 17:48:48 1996 Mike Stump + + * decl.c (lookup_name_real): If we find mem in obj when parsing + `obj->mem', make sure we return the right value. + +Tue Jul 9 16:11:28 1996 Bob Manson + + * search.c (get_base_distance): Call complete_type. - * decl.c (pushdecl): Call push_overloaded_decl for functions and - function templates. - (duplicate_decls): functions and function templates are not - duplicates, but don't complain about calling this function to - compare them. - (push_overloaded_decl): Don't deal with linkage. Call - duplicate_decls. - (redeclaration_error_message): Deal with linkage. +Tue Jul 9 12:46:34 1996 Mike Stump + + * decl.c (store_bindings): Make static. - * decl.c (start_function): If push_overloaded_decl returns an - older version of the function, deal with it. +Mon Jul 8 16:42:31 1996 Jason Merrill - * decl.c (start_function): Be sure only to push_overloaded_decl - for non-members. + * init.c (expand_aggr_init_1): Don't check type conversions if + NEW_OVER. - * decl.c (grokfndecl): Put back clearing of DECL_CHAIN for - methods. - (start_function): Lose broken and redundant code for checking old - decl. + * cvt.c (z_candidate): Put back template field. + (add_function_candidate): Set it. + (add_template_candidate): Likewise. + (joust): Use it. + (compare_qual): Handle references and pointers to members. + (compare_ics): Handle reference bindings. - * init.c (add_friend): Give line numbers of both friend decls - when warning about re-friending. + * decl.c (duplicate_decls): Propagate DECL_ONE_ONLY. - * pt.c (tsubst): Use comptypes rather than == to compare the - types of the method as declared and as defined, since default - parameters may be different. +Mon Jul 8 16:18:56 1996 Bob Manson - * call.c (build_method_call): Use brendan's candidate printing - routine. + * call.c (compute_conversion_costs): Call complete_type. - * decl.c (start_method): Methods defined in the class body are - inline whether or not it's a template class. + * tree.c (vec_binfo_member): Use comptypes instead of comparing + pointers, so we can handle template parameters. -Mon Mar 28 16:39:26 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Jul 5 16:51:53 1996 Bob Manson - * parse.y (initdcl0): Add "extern" to current_declspecs if - have_extern_spec && ! used_extern_spcec. + * cvt.c (cp_convert_to_pointer): We have to call complete_type + here; let's make it explicit instead of a side effect of an + error check. - * tree.c (really_overloaded_fn): A fn with more than one - overload. +Wed Jul 3 16:29:51 1996 Jason Merrill - * pt.c (end_template_decl): Use really_overloaded_fn. + * cvt.c (z_candidate): Remove template field. + (reference_binding): Handle binding to temporary. + (implicit_conversion): Likewise. + (add_function_candidate): Handle artificial constructor parms. + Handle functions with too few parms. + (add_template_candidate): New function. + (build_user_type_conversion_1): Handle constructors. + (convert_like): Likewise. + (build_over_call): Likewise. + (build_new_function_call): Support templates. + (compare_ics): Fix reference, inheritance handling. - * decl.c (duplicate_decls): When smashing a decl into a previous - definition, keep the old file and line. - Don't deal with overloaded functions. - Lose old code for checking arg types of functions. - Check for overloaded C functions. - (pushdecl): Deal with overloaded functions. - (start_decl): Expect pushdecl to return an appropriate function decl. - (start_function): Ditto. - (push_overloaded_decl): Don't check for overloaded C functions. +Mon Jul 1 22:58:18 1996 Bob Manson - * *.c: Stop using DECL_OVERLOADED, it being archaic. - TREE_OVERLOADED should probably go, too. + * decl.c: Add signed_size_zero_node. + (init_decl_processing): Build it. + * class.c (prepare_fresh_vtable): Use it instead of size_zero_node + when we're trying to make a negative delta. -Mon Mar 28 14:00:45 1994 Ron Guilmette (rfg@netcom.com) +Mon Jul 1 17:56:19 1996 Brendan Kehoe - * typeck.c (comp_target_types): Call comp_target_parms with - strict == 1. + Stop doing this damn index==strchr variable name confusion. + * class.c (add_virtual_function): Change local var INDEX to be + named IDX. + (add_method): Likewise. + * lex.c (print_parse_statistics): Likewise. + * search.c (make_memoized_table_entry): Likewise. + (lookup_fnfields_here): Likewise. + (lookup_field): Likewise. + (lookup_fnfields): Likewise. + (get_baselinks): Likewise. + * sig.c (build_signature_table_constructor): Likewise. + (build_signature_method_call): Likewise. + * typeck.c (build_x_array_ref): Change INDEX parm to be named IDX. + (get_member_function_from_ptrfunc): Likewise. + (build_ptrmemfunc): Change local var INDEX to be IDX. + (c_expand_start_case): Likewise. -Sun Mar 27 00:07:45 1994 Jason Merrill (jason@deneb.cygnus.com) +Sat Jun 29 14:05:46 1996 Jason Merrill - * parse.y (empty_parms): Don't parse () as (...) in extern "C" - sections if we're compiling with -ansi or -pedantic. + * cvt.c (cp_convert_to_pointer): Move user-defined type conversion + handling to before extraction of TYPE_PTRMEMFUNC_FN_TYPE. + (convert_to_reference): Use build_type_conversion to convert to + the reference type directly. + (standard_conversion): Fix void* case, non-conversions. + (reference_binding): Fix expr == 0 case, non-conversions. + (convert_like): Support REF_BIND. + (compare_qual): Split out from compare_ics. + (compare_ics): Use it, handle icses with only a qual_conv. - * decl.c (decls_match): Don't treat (int) and (int&) as matching. + * init.c (expand_vec_init): Don't crash if decl is NULL. - * decl2.c (grokfield): Don't pedwarn twice about initializing - field. +Fri Jun 28 11:52:51 1996 Stan Shebs - * decl.c (push_overloaded_decl): Warn about shadowing - constructor. - (redeclaration_error_message): Don't allow 'int a; int a;' + * mpw-config.in: New file, configury for Mac MPW. + * mpw-make.sed: New file, makefile editing for MPW. - * cvt.c (build_up_reference): Only check for valid upcast if - LOOKUP_PROTECT is set, not just any flag. +Thu Jun 27 15:18:30 1996 Jason Merrill -Fri Mar 25 01:22:31 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (instantiate_class_template): Call repo_template_used. - * lex.c (check_newline): When we see a #pragma implementation, - also set it for the main input file. + * search.c (lookup_conversions): Only lookup conversions in + complete types. - * init.c (build_new): Convert array size argument to size_t. +Thu Jun 27 12:59:53 1996 Brendan Kehoe - * parse.y (primary): If we're doing a parenthesized type-id, call - groktypename before passing it to build_new. + * cp-tree.def: Renamed from tree.def, to avoid confusion with + gcc's tree.def. + * cp-tree.h, lex.c: Include cp-tree.def. + * Makefile.in (CXX_TREE_H): Reference cp-tree.def. - * call.c (build_method_call): Deal properly with const and - volatile for instances of reference type. +Wed Jun 26 18:29:47 1996 Bob Manson - * decl.c (store_return_init): Change 'if (pedantic) error' to 'if - (pedantic) pedwarn'. + * init.c (build_vec_delete_1): Call complete_type. - * decl.c (grokdeclarator): Don't complain about putting `static' - and `inline' on template function decls. +Mon Jun 24 17:17:32 1996 Mike Stump -Thu Mar 24 23:18:19 1994 Jason Merrill (jason@deneb.cygnus.com) + * except.c (start_anon_func): Make sure anonymous functions are + never external. - * call.c (build_method_call): Preserve const & volatile on - `this'. +Fri Jun 21 15:10:58 1996 Jason Merrill -Thu Mar 24 16:21:52 1994 Mike Stump + * decl.c (finish_function): If function_depth > 1, set nested. - * init.c (build_new, build_vec_delete): Use global new and delete - for arrays. - * decl2.c (delete_sanity): Ditto. + * decl2.c (grokbitfield): Revert Bob's change. + * class.c (finish_struct_1): Fix handling of named bitfield widths. -Thu Mar 24 02:10:46 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Jun 20 23:35:38 1996 Jason Merrill - * cvt.c (convert_to_reference): If i is an lvalue, - (int &)i -> *(int*)&i, as per 5.2.8p9 of the latest WP. - (convert_force): Call convert_to_reference with LOOKUP_COMPLAIN. + * pt.c (add_pending_template): Handle types. + (lookup_template_class): With -fexternal-templates, just add the class + to pending_templates instead of instantiating it now. + * decl2.c (finish_file): Handle types in pending_templates. -Wed Mar 23 17:45:37 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Jun 20 14:08:40 1996 Bob Manson - * decl.c (duplicate_decls): Also propagate DECL_TEMPLATE_MEMBERS - and DECL_TEMPLATE_INSTANTIATIONS. + * decl2.c (grokbitfield): Handle constant decls appropriately. + Give an appropriate error message now instead of spewing core + later. - * init.c (build_new): Handle array typedefs properly. +Thu Jun 20 13:01:51 1996 Jason Merrill -Wed Mar 23 18:23:33 1994 Mike Stump + * decl2.c: Don't turn on thunks by default for now. - 30th Cygnus<->FSF merge. +Wed Jun 19 11:37:04 1996 Jason Merrill -Wed Mar 23 00:46:24 1994 Mike Stump + * typeck.c (complete_type): Handle error_mark_node. + (common_type, OFFSET_TYPE): Handle template_type_parms. - * class.c (modify_vtable_entries): Avoid running off the end of the - virtuals list when processing a virtual destructor. - * class.c (get_vtable_entry): Ditto. +Tue Jun 18 10:02:15 1996 Jason Merrill -Wed Mar 23 00:23:59 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (instantiate_decl): If at_eof, call import_export_decl + regardless of DECL_INLINE. - * decl.c (duplicate_decls): If two template decls don't match, - just return 0. + * typeck.c (mark_addressable): Set TREE_ADDRESSABLE on CONSTRUCTORs. -Tue Mar 22 23:49:41 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (finish_struct_bits): Copy TYPE_SIZE. - * typeck.c (convert_for_assignment): Don't pedwarn about - converting function pointer to void *. + * rtti.c (build_dynamic_cast): Support templates. + * tree.def: Support DYNAMIC_CAST_EXPR. + * pt.c (tsubst_copy): Likewise. + * decl2.c (build_expr_from_tree): Likewise. -Tue Mar 22 22:23:19 1994 Mike Stump +Mon Jun 17 15:23:36 1996 Jason Merrill - Major revamp of pointer to member functions. Cures major - nonfunctionality when used in casts, and MI situations. + * typeck.c (build_static_cast): Support templates. + (build_const_cast): Likewise. + * tree.def: Support CONST/STATIC_CAST_EXPR. + * pt.c (tsubst_copy): Likewise. + * decl2.c (build_expr_from_tree): Likewise. - * cvt.c (convert_force): Update call site of build_ptrmemfunc. - * typeck.c (convert_for_assignment): Ditto. - * typeck2.c (digest_init): Ditto. - * typeck2.c (process_init_constructor): Simplify by moving code into - digest_init. - * typeck2.c (digest_init): Do default_conversions on init value, if - we are processing pointer to member functions. - * class.c (get_vfield_offset): Now non-static. Convert bit offset - into byte offset. - * cp-tree.h (get_vfield_offset): Ditto. - * typeck.c (get_member_function_from_ptrfunc): Convert down to right - instance, before fetching vtable pointer. - * typeck.c (get_delta_difference): New routine. - * typeck.c (build_ptrmemfunc): Revamp to handle casting better, also - get vtable pointer out of right subobject. +Sun Jun 16 12:33:57 1996 Jason Merrill -Tue Mar 22 17:56:48 1994 Mike Stump + * decl2.c (finish_vtable_vardecl): Don't trust + TREE_SYMBOL_REFERENCED for vtables of local classes. - * search.c (get_binfo): Return NULL instead of aborting, when - passed a UNION_TYPE. +Fri Jun 14 18:13:36 1996 Jason Merrill -Tue Mar 22 12:44:54 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (tsubst_copy): Handle operator T. - These patches implement handling of redefinition/redeclaration of - templates. +Wed Jun 12 17:52:40 1996 Brendan Kehoe - * typeck.c (comptypes): Simplify. All TEMPLATE_TYPE_PARMs are - considered compatible. + * init.c (build_delete): Move creation of PARMS inside test of + TYPE_HAS_DESTRUCTOR, since it's never used outside of that block. - * parse.y (template_def): Pass defn argument to end_template_decl. +Tue Jun 11 15:09:18 1996 Bob Manson - * pt.c (end_template_decl): Add defn argument. Check for - redefinition. Simplify. + * typeck.c (build_conditional_expr): Don't assume that + the arguments to ?: are always pointers or records. - * error.c (OB_UNPUT): New macro, to remove mistakes. - (aggr_variety): Subroutine of dump_aggr_type. +Tue Jun 11 13:56:23 1996 Jason Merrill - * decl.c (decls_match): Support templates. - (duplicate_decls): No longer static. Don't try to lay out template - decls. - (pushdecl): Simplify. + * decl2.c (import_export_decl): Still emit static/weak/comdat + copies of inline template functions with -fno-implicit-templates. - * cp-tree.h (DECL_TEMPLATE_MEMBERS): Use DECL_SIZE instead of - DECL_INITIAL. +Tue Jun 11 11:42:13 1996 Bob Manson -Mon Mar 21 11:46:55 1994 Jason Merrill (jason@deneb.cygnus.com) + * init.c (build_delete): Determine the complete basetype + path to the destructor we're calling. - * error.c (dump_decl): Support class template decls. - (dump_type): Don't adorn template type parms. +Fri Jun 7 15:30:10 1996 Bob Manson - * decl.c (duplicate_decls): Save DECL_TEMPLATE_INFO from old decl - if it was a definition. - (redeclaration_error_message): Do the cp_error thang, and reject - redefinition of templates. + * decl.c (build_enumerator): Always copy the INTEGER_CST used to + initialize the enum, because we really and truly don't know where + it came from. + (start_enum): Don't copy integer_zero_node because + build_enumerator will do it. -Mon Mar 21 19:36:06 1994 Per Bothner (bothner@kalessin.cygnus.com) +Fri Jun 7 11:11:09 1996 Jason Merrill - * decl.c (grokdeclarator): Set TREE_PUBLIC for METHOD_TYPE - in FIELD context, when appropriate. Also, - CLASSTYPE_INTERFACE_ONLY is irrelevant to setting TREE_PUBLIC. - Also, simplify check for bogus return specifiers. + * decl.c (finish_function): Do access control on base destructors. -Mon Mar 21 11:46:55 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (tsubst, case FUNCTION_DECL): Set up + IDENTIFIER_GLOBAL_VALUE for member functions so pushdecl doesn't + hose us. - * parse.y (after_type_declarator1): Expand type_quals. - (notype_declarator1): Ditto. - (absdcl1): Ditto. +Fri Jun 7 10:37:33 1996 Mike Stump -Sat Mar 19 01:05:17 1994 Jason Merrill (jason@deneb.cygnus.com) + * cvt.c (build_up_reference): If we have already extended the + 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 - * decl.c (grokdeclarator): Treat class-local typedefs like static - members; i.e. 'typedef int f();' means that f is a function type, - not a method type. + * pt.c (tsubst_expr, case DECL_STMT): Don't pass + LOOKUP_ONLYCONVERTING at all for now. - * parse.y (decl): Change direct_* back to *. - (type_id): Change direct_abstract_declarator to absdcl. - (direct_declarator, direct_initdecls, direct_initdcl0): Remove again. + * search.c (add_conversions): Put the conversion function in + TREE_VALUE, the basetype in TREE_PURPOSE. + * cvt.c (build_type_conversion): Adjust. + * cvt.c (build_expr_type_conversion): Adjust. + * call.c (user_harshness): Adjust. -Fri Mar 18 12:47:59 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Jun 3 15:30:52 1996 Jason Merrill - These two patches fix crashes on instantiating a template inside a - function with C linkage or containing labels. + * method.c (emit_thunk): Pretend this is a FUNCTION_DECL for the + backend's benefit. - * class.c (current_lang_stacksize): No longer static. +Mon Jun 10 18:58:19 1996 Mike Stump - * decl.c (struct saved_scope): Add lang_base, lang_stack, - lang_name, lang_stacksize, and named_labels. - (push_to_top_level): Save them. - (pop_from_top_level): Restore them. + * except.c (expand_start_catch_block): Add a dummy region, if we + get an error, so that we can avoid core dumping later. - * gxxint.texi (Parser): Update. +Fri May 31 14:56:13 1996 Mike Stump - These two patches finish moving the task of expr/declarator - ambiguity resolution from the lexer to the parser, and add one more - r/r conflict. START_DECLARATOR can now be nuked. + * cp-tree.h (OFFSET_REF): Remove. + * tree.def (CP_OFFSET_REF): Rename to OFFSET_REF. + * expr.c (cplus_expand_expr): Cleanup callers of expand_expr. + * init.c (expand_aggr_init_1): Likewise. + (build_new): Likewise. + * typeck.c (expand_target_expr): Likewise. - * parse.y (decl): Add "direct_" in typespec X rules. - (direct_declarator): New nonterminal for - direct_after_type_declarator and direct_notype_declarator. - (direct_initdecls): Like initdecls, but uses direct_initdcl0. - (direct_initdcl0): Like initdcl0, but uses direct_declarator. - (named_parm): Add typespec direct_declarator rule. +Fri May 31 14:22:08 1996 Jason Merrill - * spew.c (yylex): #if 0 out START_DECLARATOR insertion. + * typeck.c (build_modify_expr): Don't use TREE_VALUE on a + TARGET_EXPR. - These two patches disable some excessive cleverness on the part of - g++; a non-class declaration always hides a class declaration in the - same scope, and g++ was trying to unhide it depending on the - enclosing expression. +Wed May 29 17:04:33 1996 Mike Stump - * spew.c (arbitrate_lookup): #if 0 out. + * cvt.c (build_up_reference): Redo how and when temporaries are + created. + * decl.c (grok_reference_init): Don't try and be smart about + running cleanups. - * decl.c (lookup_name): Never call arbitrate_lookup. +Wed May 29 16:02:08 1996 Mike Stump - * parse.y (complex_notype_declarator1): Add '*' - complex_notype_declarator1 and '&' complex_notype_declarator1 rules. + * cvt.c (build_up_reference): Add NULL_TREE to all calls to build + (TARGET_EXPR...), now that it has 4 arguments. + * tree.c (build_cplus_new): Likewise. - * parse.y (complex_direct_notype_declarator): Restore id_scope - see_typename TYPENAME rule, remove all other rules beginning with - those tokens. - (notype_unqualified_id): Add '~' see_typename IDENTIFIER rule. +Thu May 23 16:40:30 1996 Jason Merrill -Thu Mar 17 17:30:01 1994 Jason Merrill (jason@deneb.cygnus.com) + * error.c (dump_expr, case CAST_EXPR): Handle T() properly. - These changes fix the compiler's handling of the functional cast/ - object declaration ambiguities in section 6.8 of the ARM. They also - add 11 reduce/reduce conflicts. Sigh. + * pt.c (instantiate_decl): Don't call push/pop_cp_function_context. + * decl.c (struct saved_scope): Remove named_labels, + {base,member}_init_list. + (maybe_push_to_top_level): Don't set them. Call + push_cp_function_context if appropriate. + (pop_from_top_level): Likewise. - * parse.y: Add precedence decls for OPERATOR and '~'. - (notype_unqualified_id): New nonterminal, encompasses all of the - ANSI unqualified-id nonterminal except TYPENAMEs. - (expr_or_declarator): New nonterminal to delay parsing of code like - `int (*a)'. - (primary): Use notype_unqualified_id. - (decl): Add typespec initdecls ';' and typespec declarator ';' - rules. - (initdcl0): Deal with the above. - (complex_notype_declarator1): A notype_declarator that is not also - an expr_or_declarator. - (complex_direct_notype_declarator): A direct_notype_declarator that - doesn't conflict with expr_or_declarator. Use - notype_unqualified_id. Remove id_scope see_typename TYPENAME rule. - (functional_cast): New nonterminal, for the three functional cast - rules. So that they can be moved after - complex_direct_notype_declarator. - (see_typename): Don't accept type_quals any more. + * method.c (do_build_assign_ref): Remove obsolete check of + TYPE_HAS_ASSIGN_REF (basetype). - * decl2.c (reparse_decl_as_expr): New function to deal with parse - nodes for code like `int (*a)++;'. - (reparse_decl_as_expr1): Recursive subroutine of the above. - (finish_decl_parsing): New function to deal with parse nodes for - code like `int (*a);'. See the difference? + * decl.c (grokfndecl): Diagnose user definition of + implicitly-declared methods. -Thu Mar 17 12:16:10 1994 Mike Stump +Thu May 23 12:13:08 1996 Bob Manson - These changes break binary compatibility in code with classes - that use virtual bases. + * method.c (do_build_copy_constructor): Add code to give + meaningful error messages instead of crashing. + (do_build_assign_ref): Don't synthesize assignment operators for + classes containing reference or const members. - * search.c (dfs_get_vbase_types): Simplify and correct to make - sure virtual bases are initialized in dfs ordering. - * search.c (get_vbase_types): Simplify and make readable. + * class.c (struct base_info): Remove cant_synth_copy_ctor + 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 + messages instead of silently generating code to perform a bitcopy. -Thu Mar 17 12:01:10 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed May 22 11:45:19 1996 Bob Manson - * parse.y: s/ typename / type_id /g + * lex.c (real_yylex): Remove old-n-crufty #if 0 code for + determining types for constant values. -Wed Mar 16 17:42:52 1994 Kung Hsu (kung@mexican.cygnus.com) + * decl.c (struct named_label_list): Use instead of stuffing + random items into a TREE_LIST node. + (named_label_uses): Use the new struct. + (poplevel): Likewise. + (lookup_label): Likewise. + (define_label): Add an error message to tell the user the line + where the goto is located in addition to the destination of the + goto. + (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. - * parse.y (typespec): add SCOPE TYPENAME for global scoped - type. e.g. ::B x. +Wed May 22 09:33:23 1996 Jason Merrill - * decl.c (complete_array_type): fix a bug that in -pendantic - mode even there's no initializer, it will continue to build - default index. + * cvt.c (build_expr_type_conversion): Adjust. -Wed Mar 16 17:43:07 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue May 21 11:21:56 1996 Jason Merrill - * parse.y (direct_notype_declarator): Add PTYPENAME rule, remove - all of the scoped PTYPENAME rules. + * call.c (build_method_call): Always convert 'this' to the + appropriate type. -Wed Mar 16 16:39:02 1994 Mike Stump + * search.c (add_conversions): Put the conversion function in + TREE_VALUE, the type in TREE_PURPOSE. + * cvt.c (build_type_conversion): Adjust. + * call.c (user_harshness): Adjust. - * init.c (build_offset_ref): The value of A::typedef_name is - always the TYPE_DECL, and never an error. + * method.c (emit_thunk): Call temporary_allocation and + permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too. -Tue Mar 15 20:02:35 1994 Jason Merrill (jason@deneb.cygnus.com) + * tree.c (build_cplus_array_type): Handle tweaking of + TYPE_MAIN_VARIANT here. + * typeck.c (common_type): Not here. - * search.c (get_base_distance_recursive): Two binfos can only - represent the same object if they are both via_virtual. + * typeck.c (complete_type): Only try to complete an array type if + it has a domain. - * class.c (finish_base_struct): Check vbases for ambiguity, too. +Mon May 20 14:55:59 1996 Jason Merrill - * search.c (get_vbase_types): Accept binfo argument, too. + * decl.c (grokvardecl): Call complete_type. + (grokdeclarator): Call complete_type for PARM_DECLs. -Tue Mar 15 19:22:05 1994 Kung Hsu (kung@mexican.cygnus.com) +Fri May 17 16:41:17 1996 Jason Merrill - * decl.c (complete_array_type): complete TYPE_DOMAIN of the - initializer also, because back-end requires it. + * pt.c (instantiate_class_template): Re-set + CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1. -Tue Mar 15 15:33:31 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri May 17 14:56:55 1996 Mike Stump - * error.c (dump_expr): Support member functions (which show up as - OFFSET_REFs). + * cp-tree.h (cp_expand_decl_cleanup): Remove, the backend is now + smart enough to do it right. + * tree.c (cp_expand_decl_cleanup): Likewise. + * decl.c (cp_finish_decl): Use expand_decl_cleanup instead of + cp_expand_decl_cleanup. + (store_parm_decls): Likewise. + (hack_incomplete_structures): Likewise. + * except.c (push_eh_cleanup): Likewise. -Mon Mar 14 16:24:36 1994 Mike Stump +Fri May 17 13:13:51 1996 Mike Stump - * init.c (build_new): Set the return type of multidimensional - news correctly. + * expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++ + frontend to the backend where it belongs. + * tree.c (unsave_expr): Likewise. + (unsave_expr_now): Likewise. + * tree.def (UNSAVE_EXPR): Likewise. + * cp-tree.h (unsave_expr): Likewise. + (unsave_expr_now): Likewise. -Fri Mar 11 15:35:39 1994 Kung Hsu (kung@mexican.cygnus.com) +Fri May 17 11:02:41 1996 Mike Stump - * call.c (build_method_call): if basetype not equal to type - of the instance, use the type of the instance in building - destructor. + * init.c (emit_base_init): Make sure the partial EH cleanups live + on the function_obstack. -Thu Mar 10 17:07:10 1994 Kung Hsu (kung@mexican.cygnus.com) +Thu May 16 15:29:33 1996 Bob Manson - * parse.y (direct_notype_declarator): add push_nested_type for - 'template_type SCOPED_NAME' rule. + * expr.c (do_case): Don't try to dereference null TREE_TYPEs + when checking for pointer types. -Tue Mar 8 00:19:58 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu May 16 13:38:58 1996 Jason Merrill - * parse.y (parm): Add typed_declspec1 {absdcl, epsilon} rules. + * pt.c (instantiate_class_template): Remove obsolete check for + access declarations. -Sat Mar 5 04:47:48 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu May 16 13:34:15 1996 Mike Stump - * parse.y (regcast_or_absdcl): New nonterminal to implement late - reduction of constructs like `int ((int)(int)(int))'. - (cast_expr): Use it. - (sub_cast_expr): Everything that can come after a cast. - (typed_declspecs1): typed_declspecs that are not typed_typespecs. - (direct_after_type_declarator): Lose PAREN_STAR_PAREN rule. - (direct_abstract_declarator): Replace '(' parmlist ')' rule with - '(' complex_parmlist ')' and regcast_or_absdcl. - (parmlist): Split - (complex_parmlist): Parmlists that are not also typenames. - (parms_comma): Enabler. - (named_parm): A parm that is not also a typename. Use declarator - rather than dont_see_typename abs_or_notype_decl. Expand - typed_declspecs inline. - (abs_or_notype_decl): Lose. - (dont_see_typename): Comment out. - (bad_parm): Break out abs_or_notype_decl into two rules. + * call.c (build_overload_call): Simplify calls to + build_overload_call by removing last parameter. + (build_method_call): Likewise. + * cp-tree.h: Likewise. + * method.c (build_opfncall): Likewise. + * typeck.c (build_x_function_call): Likewise. -Fri Mar 4 18:22:39 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu May 16 13:15:43 1996 Mike Stump - * decl2.c (reparse_decl_as_casts): New function to change parse - nodes for `(int)(int)(int)' from "function taking int and returning - function taking int and returning function taking int" to "... cast - to int, cast to int, cast to int". + * call.c (default_parm_conversions): Factor out common code. + (build_method_call): Use it. + (build_overload_call_real): Use it. - * decl2.c (reparse_decl_as_expr): Recursive function to change - parse nodes for `A()()' from "function returning function returning - A" to "A().operator()". +Wed May 15 14:46:14 1996 Mike Stump - * parse.y (primary): Replace `typespec LEFT_RIGHT' rule with - `typespec fcast_or_absdcl' rule. - (fcast_or_absdcl): New nonterminal to implement late reduction of - constructs like `A()()()()'. - (typename): Replace `typespec absdcl1' rule with - `typespec direct_abstract_declarator' rule. - (direct_abstract_declarator): Replace `LEFT_RIGHT type_quals' rule - with `fcast_or_absdcl type_quals' rule. + * call.c (build_method_call): Allow implicit & on METHOD_TYPEs, + but pedwarn as the code is bogus. + * typeck.c (decay_conversion): Likewise. + (build_function_call_real): Use build_addr_func instead of + default_conversion. Don't allow pointer-to-method functions down + here. + (build_unary_op): Use real pointer-to-member functions instead of + fake ones. + (build_ptrmemfunc): Use build_addr_func instead of build_unary_op. + (convert_for_assignment): Removed some obsolete code. + * decl2.c (reparse_absdcl_as_expr): Pass current_class_ref to + build_x_function_call instead of current_class_ptr. Only call + digest_init once on an initializer, we do this just checking + TREE_TYPE. + (build_expr_from_tree): Pass current_class_ref to + build_x_function_call instead of current_class_ptr. + * init.c (build_member_call): Likewise. + * pase.y: Likewise. + * error.c (dump_expr): Handle OFFSET_REFs better. + * pt.c (unify): Handle pointer-to-member functions better. + * decl.c (finish_function): Clear out current_class_ref just like + we do for current_class_ptr. -Fri Mar 4 16:18:03 1994 Mike Stump - - * tree.c (lvalue_p): Improve OFFSET_REF handling, so that it - matches Section 5.5. + * typeck.c (get_delta_difference): Handle virtual bases better. -Fri Mar 4 14:01:59 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue May 14 16:37:37 1996 Jason Merrill - * error.c (dump_type_prefix): Don't print basetype twice for - pmfs. + * sig.c (build_signature_table_constructor): Use the delta for + the original basetype for this virtual function with thunks. + (build_signature_method_call): We still need to adjust 'this' + with thunks. -Fri Mar 4 13:24:33 1994 Mike Stump +Tue May 14 16:27:25 1996 Mike Stump - * typeck.c (convert_arguments): Handle setHandler(A::handlerFn) - so that it is like setHandler(&A::handlerFn). Cures an `invalid - lvalue in unary `&''. + * call.c (build_addr_func): New routine. Used to get the `real' + address of a function or a method. Needed to avoid getting a + pointer-to-member function. + (build_call): New routine to build CALL_EXPRs. + (build_method_call): Use it. + * cvt.c (convert_to_aggr): Likewise. + * typeck.c (build_function_call_real): Likewise. + * sig.c (build_signature_table_constructor): Use build_addr_func. + * cp-tree.h (build_call, build_addr_func): Declare them. -Fri Mar 4 11:15:59 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue May 14 12:47:47 1996 Mike Stump - * gxxint.texi (Copying Objects): New section discussing default - op= problems with virtual inheritance. + * cp-tree.h (LOOKUP_AGGR): Remove, unused. + * parse.y: Remove uses of LOOKUP_AGGR. - * decl2.c (grokoptypename): Just does grokdeclarator and - build_typename_overload, since the parser can't call grokdeclarator - directly. +Tue May 14 12:07:51 1996 Mike Stump - * method.c (build_typename_overload): Set IDENTIFIER_GLOBAL_VALUE - and TREE_TYPE on generated identifiers. + * *.[chy]: Rename current_class_decl to current_class_ptr, and + C_C_D to current_class_ref. - * decl.c (grokdeclarator): Don't deal with TYPE_EXPRs anymore. +Mon May 13 16:55:23 1996 Jason Merrill - * parse.y (parm): Convert `const char *' to `__opPCc' here. + * call.c (convert_harshness): Tighten up pointer conversions. - * error.c (dump_decl): Say sorry rather than my_friendly_aborting - if we can't figure out what to do. - (dump_type*): Ditto. +Sat May 11 04:33:50 1996 Doug Evans - * typeck2.c (build_m_component_ref): 'component' is an expr, not - a decl. Also move the IS_AGGR_TYPE check after the stripping of - REFERENCE_TYPE. + * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef. + (finish_file): Likewise. -Fri Mar 4 04:46:05 1994 Mike Stump +Fri May 10 11:09:57 1996 Jason Merrill - * call.c (build_method_call): Handle b->setHandler(A::handlerFn) - so that it is like b->setHandler(&A::handlerFn). Cures an `invalid - lvalue in unary `&''. + * cvt.c (convert_fn_ptr): We don't use thunks for pmfs. -Thu Mar 3 12:38:15 1994 Jason Merrill (jason@deneb.cygnus.com) + * method.c (emit_thunk): Set flag_omit_frame_pointer in default + code. - * parse.y: Add precedence specification for START_DECLARATOR. - (type_quals): Move before primary. - (typename): Move before typed_declspecs, add 'typespec absdcl1' rule. +Thu May 9 18:18:30 1996 Jason Merrill - * decl2.c (grokoptypename): Lose. + * decl2.c: Turn on thunks by default where supported. - * decl.c (grokdeclarator): Parse TYPE_EXPRs in the initial scan, - rather than waiting until later. +Tue May 7 20:39:57 1996 Mike Stump -Wed Mar 2 14:12:23 1994 Jason Merrill (jason@deneb.cygnus.com) + * cp-tree.h (build_overload_call_maybe): Removed. + * call.c (build_overload_call_real): Invert meaning of last arg to + be require_complete. + (build_overload_call): Likewise. + * typeck.c (build_x_function_call): Use build_overload_call_real + instead of build_overload_call_maybe. - * parse.y (unary_expr): Use 'typename' in 'new' rules, rather - than expanding it inline. - (typename): Expand empty option of (former) absdcl inline. - (abs_or_notype_decl): Ditto. - (absdcl): Lose empty rule. - (conversion_declarator): New nonterminal for 'typename' of 'operator - typename'. - (operator_name): Use it instead of absdcl. +Mon May 6 01:23:32 1996 Jason Merrill - * parse.y: Add precedence declarations for SCOPED_TYPENAME, - TYPEOF, and SIGOF. - (typed_declspecs): Accept typed_typespecs, rather than typespec - directly. Add rules with reserved_typespecquals. - (reserved_declspecs): Don't accept typespecqual_reserved at the - beginning of the list. The typed_declspecs rule will deal with this - omission. - (declmods): Accept nonempty_type_quals, rather than TYPE_QUAL - directly. + * decl2.c (finish_file): Don't try to emit functions that haven't + been compiled. - * parse.y (direct_notype_declarator, - direct_after_type_declarator, direct_abstract_declarator): Split up - the declarator1 nonterminals to match the draft standard and avoid - ambiguities. - (new_type_id, new_declarator, direct_new_declarator, - new_member_declarator): New nonterminals to implement the subset of - 'typename' allowed in new expressions. - (unary_expr): Use new_type_id instead of typename. - (after_type_declarator1, absdcl1): Fix semantics of member pointers. - (abs_member_declarator, after_type_member_declarator): Lose. +Fri May 3 09:30:13 1996 Jason Merrill - * parse.y (absdcl1): Don't require parens around - abs_member_declarator. - (abs_member_declarator): Lose see_typename from rules. - (after_type_member_declarator): Ditto. + * decl2.c (finish_vtable_vardecl): Oops. - * tree.c (get_identifier_list): New function, containing code - previously duplicated in get_decl_list and list_hash_lookup_or_cons. - (get_decl_list): Use it. - (list_hash_lookup_or_cons): Ditto. + * decl.c (maybe_push_to_top_level): Do save previous_class_*. + Also store the bindings from previous_class_values. + (pop_from_top_level): Restore them. - * parse.y (typed_declspecs, declmods): It's not necessary to hash - the declspecs on class_obstack, so don't. This way typed_typespecs - can reduce to typed_declspecs. +Thu May 2 21:56:49 1996 Jason Merrill -Wed Mar 2 14:29:18 1994 Jason Merrill (jason@cygnus.com) + * decl2.c (finish_vtable_vardecl): Only write out vtable if its + symbol has been referenced. + (finish_file): Re-join synthesis/vtable loop with inline emission + loop, disable inlining when an inline is output. - * cvt.c (build_up_reference): If we aren't checking visibility, - also allow base->derived conversions. +Thu May 2 17:20:02 1996 Mike Stump -Mon Feb 28 15:14:29 1994 Per Bothner (bothner@kalessin.cygnus.com) + * except.c (init_exception_processing): Setup saved_in_catch. + (push_eh_cleanup): Reset __eh_in_catch. + (expand_start_catch_block): Set __eh_in_catch. - * typeck.c (build_c_cast): Remove bogus hack when converting - to a reference type. +Thu May 2 16:21:17 1996 Mike Stump - * cp-tree.h (lang_decl::vbase_init_list, DECL_VBASE_INIT_LIST): - Removed, not used. - (lang_stype::methods, lang_decl::next_method): New fields. - (CLASSTYPE_METHODS, DECL_NEXT_METHOD): New macros. - * decl.c (duplicate_decls): Preserve DECL_NEXT_METHOD. + * except.c (push_eh_cleanup): Add tracking for whether or not we + have an active exception object. + (expand_builtin_throw): Use it to make sure a rethrow without an + exception object is caught. - * cp-tree.h, decl2.c (flag_vtable_hack): New flag. - * decl2.c (finish_vtable_vardecl): If flag_vtable_hack, - and !CLASSTYPE_INTERFACE_KNOWN, try to use the presence of - a non-inline virtual function to control emitting of vtables. - * class.c (finish_struct): Build CLASSTYPE_METHODS list. - * search.c (build_vbase_vtables_init): Don't assemble_external - (yet) if flag_vtable_hack. - * class.c (build_vfn_ref): Ditto. +Thu May 2 11:26:41 1996 Jason Merrill -Mon Feb 28 14:54:13 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (maybe_push_to_top_level): Clear out class-level bindings + cache. - * parse.y (component_decl): Don't include "typed_declspecs - declarator ';'" speedup, since it breaks enums. +Wed May 1 11:26:52 1996 Jason Merrill -Fri Feb 25 15:43:44 1994 Per Bothner (bothner@kalessin.cygnus.com) + * decl2.c (finish_file): Also use sentries for vars with + DECL_ONE_ONLY or DECL_WEAK set (should any such happen to be + created). - * class.c (finish_struct): Minor optimization for building - fn_fields list. + * lex.c (handle_cp_pragma): Disable #pragma + interface/implementation if SUPPORTS_ONE_ONLY > 1. -Fri Feb 25 15:23:42 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Apr 30 11:25:46 1996 Jason Merrill - * decl.c (start_function): Fix detection of function overloading. + * method.c (emit_thunk): Wrap default case in + temporary/permanent_allocation. -Thu Feb 24 22:26:19 1994 Mike Stump + * method.c (make_thunk): Use DECL_ONE_ONLY. + (emit_thunk): Call assemble_end_function. - * lex.c (check_newline): #pragma interface can take a string - argument, just like #pragma implementation. #pragma implementation - checks for garbage on the line, line #pragma interface does. Main - input files do not auto implement like named files, #pragma - implementation must be used explicitly. +Mon Apr 29 15:38:29 1996 Jason Merrill -Thu Feb 24 17:09:01 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (import_export_vtable): Use DECL_ONE_ONLY. + (import_export_decl): Likewise. + (finish_prevtable_vardecl): Disable vtable hack if + SUPPORTS_ONE_ONLY > 1. - * parse.y (components): Handle list of one again. - (notype_components): Ditto. - (after_type_declarator1): Take maybe_raises out again. +Mon Apr 29 14:32:47 1996 Mike Stump - * gxxint.texi (Parser): Document additional r/r conflict. + * typeck.c (build_modify_expr): PREINCREMENT_EXPR and + PREDECREMENT_EXPRs take two arguments, not one. -Wed Feb 23 14:42:55 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Apr 29 00:27:53 1996 Jason Merrill - * gxxint.texi (Parser): Add node. + * class.c (build_vtable_entry): Don't build thunks for abstract + virtuals. - * Makefile.in (stamp-parse): Update expected conflict count. + * lex.c (real_yylex): Fix handling of __PRETTY_FUNCTION__ like C + frontend. - * parse.y (various): Replace "declmods declarator" with "declmods - notype_declarator". The comment saying that "declmods declarator ';'" - corresponds to "int i;" was wrong; it corresponds to "const i;". - (component_decl): Add "typed_declspecs declarator ';'" rule; this - *does* correspond to "int i;". Change "declmods components" to - "declmods notype_components". - (components): Don't deal with a list of one anymore. - (notype_components): New nonterminal, corresponds to notype_declarator. - ({after_,no}type_component_decl{,0}): More new nonterminals. - ({after_,no}type_declarator): Fold in START_DECLARATOR token. - Eliminates four reduce/reduce conflicts. +Sat Apr 27 16:45:35 1996 Jason Merrill - (expr): Depend on nontrivial_exprlist instead of nonnull_exprlist. - (nontrivial_exprlist): New nonterminal: A list of at least two - expr_no_commas's. - (nonnull_exprlist): Depend on nontrival_exprlist. - Eliminates four reduce/reduce conflicts. + * class.c (set_rtti_entry): Use size_zero_node. + (build_vtable): Likewise. - (named_class_head): Move intermediate code block into separate - nonterminal so that we can stick %prec EMPTY on it. +Sat Apr 27 14:48:57 1996 Jason Merrill - Add more %prec EMPTY's to eliminate remaining shift/reduce - conflicts. + * class.c (finish_struct_1): Pass size_zero_node to set_rtti_entry. + (prepare_fresh_vtable): Likewise. - (after_type_declarator): Add maybe_raises to fndecl rules. - (after_type_declarator_no_typename): Remove. - For correctness. +Fri Apr 26 13:14:14 1996 Jason Merrill - Document remaining reduce/reduce conflicts. + * method.c (emit_thunk): Call mark_used on the target function. -Tue Feb 22 12:10:32 1994 Jason Merrill (jason@deneb.cygnus.com) + * call.c (build_method_call): Don't warn about pending templates. - * search.c (get_base_distance): Only bash BINFO_INHERITANCE_CHAIN - (TYPE_BINFO (type)) if we care about the path. +Thu Apr 25 14:55:44 1996 Jason Merrill - * tree.c (lvalue_p): A COND_EXPR is an lvalue if both of the - options are. + * decl2.c (finish_file): Fix list walking logic. -Mon Feb 21 19:59:40 1994 Mike Stump + * typeck2.c (check_for_new_type): Only warn if -pedantic. - * Makefile.in (mostlyclean): lex.c is a source file, don't - remove. +Wed Apr 24 15:41:15 1996 Bob Manson -Sat Feb 19 01:27:14 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (finish_struct_1): Remove old code for + dont_allow_type_definitions. + * cp-tree.h: Likewise. + * spew.c: Make sure cp-tree.h is included before parse.h, so the + 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 + 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 + for check_for_new_type(). - * parse.y: Eliminate 20 shift/reduce conflicts. +Wed Apr 24 00:36:21 1996 Jason Merrill -Fri Feb 18 11:49:42 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (finish_file): Only use a sentry if the decl is public. - * pt.c (type_unification): Add subr argument; if set, it means - that we are calling ourselves recursively, so a partial match is OK. - (unify): Support pointers to methods and functions. - (tsubst): Support method pointers. - * decl.c (build_ptrmemfunc_type): No longer static, so that - tsubst can get at it. + * pt.c (tsubst_expr, DECL_STMT): If we don't have an initializer, + don't pass LOOKUP_ONLYCONVERTING. - * init.c (is_aggr_typedef): Pretend template type parms are - aggregates. - * decl2.c (build_push_scope): If cname refers to a template type - parm, just grin and nod. +Tue Apr 23 17:18:47 1996 Bob Manson - * call.c (build_overload_call_real): Pass subr argument to - type_unification. - * pt.c (do_function_instantiation): Ditto. - * class.c (instantiate_type): Ditto. + * typeck.c (common_type): Fix the ARRAY_TYPE case so it + properly keeps track of const and volatile type modifiers. - * search.c (get_base_distance): If BINFO is a binfo, use it and - don't mess with its BINFO_INHERITANCE_CHAIN. +Tue Apr 23 10:52:56 1996 Jason Merrill - * cvt.c (convert_to_reference): Fix temporary generation. - If ambiguous, return error_mark_node. + * tree.c (cp_tree_equal): C++ version of simple_cst_equal. + * pt.c (comp_template_args): Use it. - * init.c (build_new): Put back some necessary code. + * rtti.c (get_tinfo_fn, build_dynamic_cast, expand_*_desc): Call + assemble_external for artificial function decls. -Thu Feb 17 15:39:47 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (cp_finish_decl): Oops. - * init.c (build_new): Deal with array types properly. +Mon Apr 22 17:28:27 1996 Jason Merrill - * search.c (get_binfo): Become a shell for get_base_distance. - (get_binfo_recursive): Lose. - (get_base_distance_recursive): Find the path to the via_virtual base - that provides the most access. - (get_base_distance): Ditto. + * decl2.c (import_export_decl): Put static data member templates + into common storage, or make them weak, depending on whether they + are dynamically or statically initialized. + (get_sentry): New function. + (finish_file): Do import_export_decl for static data members before + building the init/fini functions. Don't init/fini a variable that's + EXTERNAL. Use a sentry for variables in common. Fix mismatching + push/pop_temp_slots. + * decl.c (cp_finish_decl): If DECL_NOT_REALLY_EXTERN, do the + expand_static_init thang. + * method.c (get_id_2): New function. - * parse.y (explicit_instantiation): Syntax is 'template class - A', not 'template A'. +Mon Apr 22 15:32:45 1996 Bob Manson - * typeck.c (convert_for_initialization): Remove bogus warning. + * parse.y (empty_parms): Make sure we use C++-style prototypes + when we're declaring member functions. - * parse.y (datadef): Revert patch of Oct 27. +Sun Apr 21 10:08:22 1996 Jason Merrill -Thu Feb 17 15:12:29 1994 Per Bothner (bothner@kalessin.cygnus.com) + * Makefile.in (CONFLICTS): 16 s/r conflicts. + * parse.y (self_template_type): New nonterminal. - * class.c (build_vfn_ref): Cast delta field to ptrdiff_type_node, - rather than integer_type_node. Does wonders for the Alpha. +Thu Apr 18 08:56:54 1996 Jason Merrill -Thu Feb 17 13:36:21 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (make_typename_type): Handle getting a TYPE_DECL for a + name. + * parse.y (base_class.1): Allow 'typename foo::bar'. - * decl.c (build_ptrmemfunc_type): Make sure that the pmf type - goes onto the same obstack as its target type. + * lex.c (check_newline): Remove #pragma code that plays with the + input stream, since we now deal with tokens. Clear nextchar when + we're done. + (handle_cp_pragma): Use real_yylex. + (handle_sysv_pragma): Don't do skipline here. Only call real_yylex + in one place. -Wed Feb 16 00:34:46 1994 Jason Merrill (jason@deneb.cygnus.com) + * lex.c (check_for_missing_semicolon): Handle SELFNAME. - * cvt.c (convert_to_reference): If converting via constructor - on local level, go back to build_cplus_new approach. + * lex.c (handle_cp_pragma): Fix "#pragma implementation". - * tree.c (build_cplus_new): If with_cleanup_p, set cleanup slot - to error_mark_node to prevent expand_expr from building a cleanup - for this variable. +Wed Apr 17 16:51:33 1996 Jason Merrill - * lex.c (default_assign_ref_body): Return *this from the memcpy - version, too. + * parse.y: New token SELFNAME for potential constructor. + * spew.c (yylex): Handle it. + * lex.c (identifier_type): Produce it. - * decl.c (grok_reference_init): Just return if called with - error_mark_node, don't worry about initializing non-const reference - with temporary. + * parse.y (complete_type_name): In :: case, don't push class binding. + (complex_type_name): Likewise. - * cvt.c (convert_to_reference): Do the right thing for - non-aggregate reference conversions, pedwarn when generating a - non-const reference to a temporary. +Wed Apr 17 15:02:40 1996 Mike Stump - * class.c (finish_struct): TYPE_HAS_COMPLEX_{INIT,ASSIGN}_REF and - TYPE_NEEDS_CONSTRUCTING all depend on TYPE_USES_VIRTUAL_BASECLASSES - again. + * typeck.c (build_reinterpret_cast): Handle pointer to member + functions. -Tue Feb 15 19:47:19 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Apr 17 12:28:26 1996 Brendan Kehoe - * decl.c (grok_reference_init): Pawn off a lot of the work on - convert_to_reference. Generally do the right thing. + * lex.c (handle_cp_pragma): New function, with decl, doing the cc1plus + pragmas. + (check_newline): Put the vtable/unit/implementation/interface pragma + code into handle_cp_pragma, replacing it with a call. + (handle_sysv_pragma): Give int return type, and take FINPUT and TOKEN + args. Get the next token after handling the pragma token. - * cvt.c (convert_to_reference): Conform to the initial comment; - i.e. don't create temps if decl != error_mark_node. Handle - cleanups better for temps that do get created. Don't pretend - that we can use an 'A' to initialize a 'const double &' just by - tacking on a NOP_EXPR. Support LOOKUP_SPECULATIVELY. +Wed Apr 17 10:28:34 1996 Jason Merrill - * call.c (build_method_call): Set TREE_HAS_CONSTRUCTOR on - constructor calls. + * cvt.c (cp_convert_to_pointer): Avoid doing base analysis on pmfs. + (convert_to_pointer_force): Likewise. -Mon Feb 14 14:50:17 1994 Jason Merrill (jason@deneb.cygnus.com) + * init.c (build_new): Fix array new without -fcheck-new. - * decl.c (grok_reference_init): Make a temporary for initializing - const reference from constant expression. +Tue Apr 16 13:44:58 1996 Jason Merrill -Mon Feb 14 11:31:31 1994 Per Bothner (bothner@kalessin.cygnus.com) + * cp-tree.h, call.c, class.c, decl.c, parse.y, pt.c, rtti.c, + tree.c: Lose TYPE_NESTED_NAME. - * cp-tree.h, decl.c (set_identifier_local_value): Deleted function. - * decl.c (pushdecl): Define decl in correct binding_level - (which isn't always the inner_binding_level). + * parse.y (nested_name_specifier_1): Don't treat non-identifiers + as identifiers. - * cvt.c (build_up_reference): Don't ever call expand_aggr_init. - It's ugly, and I don't think it's the right thing to do. + * tree.def: Add VEC_INIT_EXPR. + * expr.c (cplus_expand_expr): Handle it. + * init.c (build_new): Use it instead of the RTL_EXPR nastiness and + the extra file-scope symbol nastiness. - * cp-tree.h, class.c, decl.c, decl2.c, sp/search.c: - Remove NEW_CLASS_SCOPING, assuming it is always 1. - * decl.c (pop_decl_level): Removed; manually inlined. +Mon Apr 15 16:21:29 1996 Jason Merrill -Sun Feb 13 19:04:56 1994 Jason Merrill (jason@deneb.cygnus.com) + * method.c (make_thunk): Thunks are static. + (emit_thunk): Use ASM_OUTPUT_MI_THUNK if it's defined. - * class.h (candidate): Add basetypes field. + * decl2.c (mark_vtable_entries): Emit thunks as needed. + (finish_file): Don't emit them here. - * call.c (build_method_call): Do access checking after choosing a - function, not before. +Sun Apr 14 11:34:39 1996 Jason Merrill - * Makefile.in (cvt.o, call.o, method.o): Depend on class.h. - (mostlyclean): Remove ../cc1plus. + * rtti.c (build_dynamic_cast): Handle null pointers. + (ifnonnull): New function. -Fri Feb 11 11:52:26 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Apr 12 09:08:27 1996 Bob Manson - * class.c (finish_struct): Don't allow adjusting access to a field - of a base class if a local field has the same name. + * call.c (build_method_call): Remember the original basetype we + were called with. Give an error message instead of trying + (incorrectly) to call a non-static member function through a + non-inherited class. - * error.c (dump_type_prefix): Output basetype for METHOD_TYPEs. + * search.c (expand_upcast_fixups): Mark the new fixup as + DECL_ARTIFICIAL. -hu Jan 13 17:55:51 EST 1994 Gnanasekaran Swaminathan (gs4t@virginia.edu) +Thu Apr 11 03:57:09 1996 Jason Merrill - * cp-tree.h (DESTRUCTOR_NAME_P): do not confuse AUTO_TEMP names - with destructor names when either NO_DOLLAR_IN_LABEL or - NO_DOT_IN_LABEL are not defined. + * init.c (build_new): Use a TARGET_EXPR for alloc_expr. - Now `template class A {...}' works. + * class.c (set_rtti_entry): Fix for thunks. - * pt.c (grok_template_type): substitute template parm types - with actual types in complex type as well. - (coerce_template_parms): update the grok_template_type () - function call. + * decl2.c (import_export_decl): Still emit typeinfo fns for + cv-variants of builtin types. - * pt.c (tsubst): Traverse method list using DECL_CHAIN. + * rtti.c (expand_class_desc): Set up base_info_type_node here. + (init_rtti_processing): Instead of here. - * decl.c (grok_op_properties): Allow operator++/-- to have - default arguments. +Wed Apr 10 14:17:13 1996 Jason Merrill - * typeck2.c (store_init_value): Don't abort when called to - initialize a type that needs constructing with a CONSTRUCTOR. + * rtti.c (init_rtti_processing): Do init regardless of -frtti. + (build_typeid): Only complain about taking dynamic typeid without + -frtti. - * init.c (expand_aggr_init_1, CONSTRUCTOR case): If - store_init_value fails, build and expand an INIT_EXPR. If - store_init_value succeeds, call expand_decl_init. + * decl2.c: flag_rtti defaults to 1. -Fri Feb 11 02:49:23 1994 Mike Stump + * rtti.c (get_tinfo_var): The general class case is now smaller. + (init_rtti_processing): Pack the latter three fields of base_info + into 32 bits. - * class.c (build_vbase_path): Use complete_type_p instead of - resolves_to_fixed_type_p to determine if the virtual bases are in - their right place for the type of expr. Cures problem of thinking a - virtual base class is one place, when it is in fact someplace else. +Wed Apr 10 13:50:14 1996 Mike Stump -Fri Feb 11 00:26:46 1994 Mike Stump + * init.c (expand_member_init): Don't dump if name is NULL_TREE. - * init.c (resolve_offset_ref): Make sure we first convert to - intermediate type, if given, when dealing with members off `this'. - Solves an incorrrect `type `foo' is not a base type for type - `multiple'' when it is infact, a base type. +Wed Apr 10 12:56:02 1996 Mike Stump -Thu Feb 10 21:49:35 1994 Mike Stump + * search.c (make_memoized_table_entry): Undefer the pop, if necessary. + (push_memoized_context): Split out code to undefer pop_type_level to + (clear_memoized_cache): here. + (pop_memoized_context): We can only handle one layer of deferral of + pop_type_level so clear the cache, if there was a previous level. - * class.c (modify_other_vtable_entries): Use get_binfo, instead - of binfo_value. Solves problem with compiler giving a `base class - `B' ambiguous in binfo_value (compiler error)' on complex MI - herarchies, when a virtual function is first defied in a virtual - base class. +Tue Apr 9 23:06:09 1996 Jason Merrill -Thu Feb 10 17:19:32 1994 Mike Stump + * rtti.c (init_rtti_processing): Build up base_info_type_node. + (expand_class_desc): Use one pointer to an array of base_info + structs, passed using a CONSTRUCTOR. - * class.c (build_vbase_path): Don't complain about ambiguous - intermediate conversion when converting down to a virtual base - class, even if they might seem to be ambiguous. +Tue Apr 9 14:20:57 1996 Mike Stump -Thu Feb 10 12:18:26 1994 Jason Merrill (jason@deneb.cygnus.com) + * class.c (build_vbase_path): Remove block extern for + flag_assume_nonnull_objects here. + (build_vfn_ref): Split out functionality into build_vtbl_ref. + (build_vtbl_ref): New routine. + (build_vtable): Set up rtti info here. + (add_virtual_function): Note in CLASSTYPE_RTTI the best + place where we can get the rtti pointers from to avoid having to + search around for a place. + (finish_base_struct): Likewise. + (finish_struct_1): Likewise. Never create totally new vtables + with totally new vtable pointers for rtti. Disable code to layout + vtable pointers better until we want to break binary + compatibility. + * rtti.c (build_headof_sub): New routine to convert down to a + sub-object that has an rtti pointer in the vtable. + (build_headof): Use it. Also, use build_vtbl_ref now to be more + maintainable. + (build_dynamic_cast): Make sure we have saved it, if we need to. + * search.c (dfs_init_vbase_pointers): Disable code that deals with + a more efficient vtable layout, enable later. + * call.c (flag_assume_nonnull_objects): Moved declaration to + * cp-tree.h: here. Declare build_vtbl_ref. + * pt.c (instantiate_class_template): Use NULL_TREE instead of 0 in + function calls that want a tree. - * typeck2.c (build_functional_cast): #if 0 out constructor - inheritance code, improve error messages. +Tue Apr 9 12:10:26 1996 Jason Merrill - * class.c (finish_base_struct): Complain about base with only - non-default constructors in derived class with no constructors. + * rtti.c (build_dynamic_cast): Handle downcasting to X* given + other X subobjects in the most derived type. Ack. - * decl.c (grokdeclarator): Fix detection of virtual new/delete. + * rtti.c (build_dynamic_cast): No need to strip cv-quals here, + get_typeid will do it for us. + (get_typeid_1): Break out call-building for expand_*_desc to use. + (get_typeid): Call it. + (expand_*_desc): Likewise. + * decl.c (init_decl_processing): Don't set TYPE_BUILT_IN on char * + and void *. + (init_decl_processing): Lose builtin_type_tdescs lossage. + * decl2.c (finish_vtable_vardecl): Remove obsolete code. -Wed Feb 9 22:02:32 1994 Mike Stump +Mon Apr 8 17:23:23 1996 Bob Manson - * search.c (build_mi_virtuals, add_mi_virtuals, - report_ambiguous_mi_virtuals): Removed unneeded code. - * class.c (finish_struct_bits): Ditto. + * pt.c (tsubst): When calling set_nested_typename, use + TYPE_NESTED_NAME (current_class_type) instead of + current_class_name. -Wed Feb 9 11:27:17 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (pushdecl): Likewise. + (pushdecl_class_level): Likewise. + (grokdeclarator): Use NULL_TREE instead of 0 in the call to + set_nested_typename. + +Sun Apr 7 10:44:31 1996 Jason Merrill - * pt.c (end_template_instantiation): Push decl before - pop_from_top_level. + * rtti.c (synthesize_tinfo_fn): Handle arrays. + + * cp-tree.h (DECL_REALLY_EXTERN): New macro. + +Sat Apr 6 13:56:27 1996 Jason Merrill + + * rtti.c (throw_bad_cast): Use entry point __throw_bad_cast. + (init_rtti_processing): Lose bad_cast_type. + (build_dynamic_cast): Use throw_bad_cast. + + * rtti.c (synthesize_tinfo_fn): Handle enums and pmfs. + + * decl2.c (finish_file): Don't synthesize artificial functions + that are external and not inline. + + * rtti.c (get_tinfo_fn): If at_eof, call import_export_decl. + + * decl2.c (finish_file): Handle having new inlines added to + saved_inlines by synthesis. + + * rtti.c (get_bad_cast_node): Don't require . + +Fri Apr 5 17:02:09 1996 Jason Merrill + + RTTI rewrite to initialize nodes as needed, not require that + users #include , complete functionality and reduce wasted + space. + * rtti.c (init_rtti_processing): New fn. + (build_typeid): The vtable entry is now a function. + (get_tinfo_var): New fn. + (get_tinfo_fn): Likewise. + (get_typeid): Use it. + (build_dynamic_cast): Declare and use entry point __dynamic_cast. + (build_*_desc): Rename to expand_*_desc and rewrite to use entry + points __rtti_*. + (add_uninstantiated_desc, get_def_to_follow, build_t_desc): Lose. + (synthesize_tinfo_fn): New fn. + * method.c (build_t_desc_overload): Lose. + (build_overload_with_type): More generic. + * decl.c (init_decl_processing): Call init_rtti_processing. + * class.c (set_rtti_entry): Use get_tinfo_fn. + * decl2.c (mark_vtable_entries): Mark the rtti function. + (finish_prevtable_vardecl): Don't build_t_desc. + (import_export_decl): Handle tinfo functions. + (finish_file): Likewise. + * typeck.c (inline_conversion): New fn. + (build_function_call_real): Use it. + * cp-tree.h: Add decls. + + * method.c (hack_identifier): Also convert component_refs from + references. - * typeck2.c (build_m_component_ref): Make sure datum is of - aggregate type. + * lex.c (cons_up_default_function): Use the type, not the name, in + declspecs. - * init.c (get_type_value): New function, returns - IDENTIFIER_TYPE_VALUE or IDENTIFIER_CLASS_TYPE_VALUE or NULL_TREE. + * decl2.c (import_export_vtable): Fix weak vtables. - * call.c (build_method_call): Don't die on call to destructor for - non-type. +Fri Apr 5 13:30:17 1996 Bob Manson - * decl.c (grokdeclarator): Complain about virtual op new and op - delete, make static virtuals unvirtual instead of unstatic. + * search.c (get_base_distance_recursive): Fix access checks for + protected bases. - * typeck.c (build_c_cast): Also call default_conversion on - methods. +Fri Apr 5 11:02:06 1996 Brendan Kehoe - * decl.c (grokdeclarator): Don't complain about anonymous - bitfields. + * call.c (unary_complex_lvalue): Delete unneeded decl, it's in + cp-tree.h. + (convert_harshness): Add prototypes wrapped by PROTO. + * decl2.c (grok_function_init): Likewise. + (do_toplevel_using_decl): Change to void return type. + * class.c (build_vtable_entry): Remove decl of make_thunk. + (merge_overrides): Fix order of arg definitions. + (finish_vtbls): Likewise. + (fixup_vtable_deltas): Likewise. + (modify_all_direct_vtables): Likewise. + (modify_all_indirect_vtables): Likewise. + * search.c (get_base_distance_recursive): Likewise. + (get_abstract_virtuals_1): Likewise. + (fixup_virtual_upcast_offsets): Likewise. + (lookup_fnfields_1): Add prototypes wrapped by PROTO. + * init.c (perform_member_init): Fix order of arg definitions. + (expand_aggr_init_1): Add prototypes wrapped by PROTO. + * cp-tree.h (make_thunk): Add decl. + (overload_template_name, push_template_decl): Add decls. + (do_toplevel_using_decl): Change to void return type. + (vec_binfo_member): Add decl. - * parse.y (simple_stmt, for loops): Move the continue point after - the cleanups. +Thu Apr 4 13:33:10 1996 Brendan Kehoe - * class.c (finish_struct): Fix setting of - TYPE_HAS_COMPLEX_INIT_REF. + * typeck.c (mark_addressable, convert_for_assignment, + convert_for_initialization, pointer_int_sum, pointer_diff, + unary_complex_lvalue): Add prototypes wrapped by PROTO. + (convert_sequence): #if 0 fn decl, since definition also is. -Tue Feb 8 13:21:40 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Apr 4 11:00:53 1996 Mike Stump - * init.c (build_new): Deal with `new double (1)'. + * rtti.c (build_dynamic_cast): Make sure we strip qualifiers on + cast to pointer types for type searching. - * class.c (finish_struct): TYPE_HAS_COMPLEX_*_REF are supersets of - TYPE_HAS_REAL_*_REF, but TYPE_HAS_COMPLEX_INIT_REF is independent of - TYPE_NEEDS_CONSTRUCTING. +Wed Apr 3 17:10:57 1996 Brendan Kehoe - * decl.c (duplicate_decls): Propagate access decls. + * typeck.c (get_delta_difference): Use cp_error, not error, in the + case where BINFO == 0. - * typeck2.c (process_init_constructor): Accept empty_init_node - for initializing unions. +Wed Apr 3 12:01:02 1996 Mike Stump - * class.c, lex.c, cp-tree.h: Use - TYPE_HAS_COMPLEX_ASSIGN_REF where TYPE_HAS_REAL_ASSIGN_REF was used - before, use TYPE_HAS_COMPLEX_INIT_REF for TYPE_NEEDS_CONSTRUCTING in - some places. + * call.c (build_method_call): Fix wording of error messages so + constructors come out right. - * decl.c (finish_decl): Don't complain about uninitialized const - if it was initialized before. +Tue Apr 2 16:06:59 1996 Bob Manson -Mon Feb 7 18:12:34 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (push_overloaded_decl): Don't warn about hidden + constructors when both the type and the function are declared + in a system header file. - * lex.c (default_assign_ref_body): Don't deal with vbases for - now. +Mon Apr 1 09:03:13 1996 Bob Manson - * decl.c (finish_decl): Fix reversed logic for objects and other - things that need to be constructed but have no initializer. + * class.c (finish_struct_1): Propagate the TYPE_PACKED + flag for the type to the type's fields. - * class.c (finish_struct): Don't set TYPE_HAS_* flags that are - set by grok_op_properties or finish_decl. +Sat Mar 30 12:14:33 1996 Brendan Kehoe - * decl.c: Don't warn about extern redeclared inline unless - -Wextern-inline is given. - * decl2.c (lang_decode_option): Ditto. - * cp-tree.h: Ditto. + * parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning. -Mon Feb 7 17:29:24 1994 Per Bothner (bothner@kalessin.cygnus.com) +Fri Mar 29 15:51:36 1996 Bob Manson - * decl.c (pushdecl_with_scope): Fix thinko. Add forward - declaration. + * class.c (base_info, finish_base_struct): Replace + needs_virtual_dtor with base_has_virtual. - * decl.c (pushdecl_with_scope): New function. - * decl.c (pushdecl_top_level): Use new function. - * decl.c (pushtag): Initialize newdecl. - * decl.c (pushtag): Push new type decl into correct scope. + (finish_struct_1): Remove the old code that tried to make default + destructors virtual. Use base_has_virtual when checking if we need + to add a vtable entry for the rtti code. -Mon Feb 7 14:42:03 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Mar 29 14:02:36 1996 Jason Merrill - * call.c, cvt.c, init.c, search.c, cp-tree.h: - Eradicate LOOKUP_PROTECTED_OK. + * pt.c (push_template_decl): Complain about template decl with + inappropriate declaration. -Mon Feb 7 13:57:19 1994 Per Bothner (bothner@kalessin.cygnus.com) +Fri Mar 29 12:15:35 1996 Bob Manson - * decl.c (pushtag, xref_tag), cp-tree.h: Add extra parameter - 'globalize' to signify implicit declarations. - * decl.c (globalize_nested_type, maybe_globalize_type): Removed. - * decl.c (set_identifier_type_value_with_scope): New function. - * decl.c (set_identifier_local_value): Simplify. - * spew.c (yylex, do_addr): Modify to return a _DEFN if a - forward declaration (followed by ';' and not preceded by 'friend'). - * class.c, decl.c, except.c, init.c, parse.y, - pt.c, search.c: Add new argument to calls to xref_tag and - pushtag. + * typeck.c (build_x_unary_op): Remove bogus check for taking + the address of a member function. -Mon Feb 7 00:22:59 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Mar 29 11:56:02 1996 Jason Merrill - * cp-tree.h (ACCESSIBLY_UNIQUELY_DERIVED_P): New macro, means what - ACCESSIBLY_DERIVED_FROM_P meant before. - (ACCESSIBLY_DERIVED_FROM_P): Now disregards ambiguity. + * parse.y (constructor_declarator): Only push the class if + we are not already in the class. - * cvt.c (build_up_reference): Call get_binfo with PROTECT == 1. +Fri Mar 29 09:41:02 1996 Jeffrey A. Law - * search.c (get_base_distance_recursive): Members and friends of - a class X can implicitly convert an X* to a pointer to a private or - protected immediate base class of X. - (get_binfo_recursive): Ditto. - (get_base_distance): Ignore ambiguity if PROTECT < 0. - (get_binfo): Lose multiple values of PROTECT. - (compute_access): Protected is OK if the start of the - search is an accessible base class of current_class_type. + * method.c (emit_thunk): Remove current_call_is_indirect nonsense. + Add additional argument to INIT_CUMULATIVE_ARGS. - * method.c (build_opfncall): Do check access on operator new here. +Thu Mar 28 16:41:39 1996 Jason Merrill - * decl.c (finish_function): Don't check access on operator new - here. + * decl.c (shadow_tag): Fix error about anon union with methods. -Sun Feb 6 14:06:58 1994 Jason Merrill (jason@deneb.cygnus.com) + * parse.y (self_reference): Only generate a self-reference if this + is a non-template class. + (opt.component_decl_list): Only use it if it was generated. - * decl.c (xref_tag): The base of a derived struct is NOT always - public. Duh. + * parse.y (component_decl_1): Use constructor_declarator. + (fn.def2): Likewise. + (notype_component_declarator0): Likewise. - * pt.c (do_explicit_instantiation): New function, called from - parser to do explicit function instantiation. - (type_unification): Allow the args list to be terminated with - void_list_node. - (do_pending_expansions): Look at i->interface for non-member - templates. +Thu Mar 28 15:11:35 1996 Bob Manson - * parse.y (datadef): Move explicit_instantiation here. - (structsp): From here. - (datadef): Complain about `int;'. + * typeck.c (build_x_unary_op): Add checks for taking the address + of a TARGET_EXPR or of a member function, and give appropriate + warnings. -Sun Feb 6 12:33:18 1994 Per Bothner (bothner@kalessin.cygnus.com) +Thu Mar 28 14:49:26 1996 Jason Merrill - * pt.c (end_template_instantiation), cp-tree.h: Remove unused - second parameter, and simplify first from a TREE_LIST where - we only care about its TREE_VALUE to just the value (an IDENTIFIER). - * pt.c (instantiate_member_templates): Simplify argument list - from a TREE_LIST to just an IDENTIFIER. - * lex.c (yyprint): PRE_PARSED_CLASS_DECL is now just an IDENTIFIER. - * parse.y (template_instantiate_once): Simplify accordingly. - * decl.c (inner_binding_level): New. Use various places to - simplify. + * pt.c (process_template_parm): Allow template type parms to be + used as types for template const parms. -Sun Feb 6 02:49:37 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Mar 27 15:51:19 1996 Mike Stump - * typeck2.c (build_functional_cast): int() -> int(0). + * init.c (expand_vec_init): Ensure the eh cleanups are on the + function_obstack. -Sat Feb 5 00:53:21 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Mar 27 10:14:30 1996 Jason Merrill - * class.c (finish_struct): Don't do a bitwise copy for op= if the - class has a virtual function table. + * decl.c (lookup_name_real): Be even more picky about the + ambiguous lookup warning. + (grokdeclarator): Tweak SCOPE_REF constructor declarators here. + * parse.y (constructor_declarator): Rather than here. - * typeck.c (convert_for_initialization): Restore warnings about - not using defined op=. Should really be my_friendly_aborts, I - s'pose. + * parse.y (constructor_declarator): New nonterminal. + (fn.def1): Use it. + (explicit_instantiation): Likewise. -Fri Feb 4 14:21:00 1994 Jason Merrill (jason@deneb.cygnus.com) +Tue Mar 26 13:41:33 1996 Jason Merrill - * class.c (finish_struct): Tidy up conditions for doing bitwise - copies of objects. + Add implicit declaration of class name at class scope. + * decl.c (lookup_name_real): Restrict pedwarn about ambiguous lookup. + * parse.y (self_reference): New nonterminal. + (opt.component_decl_list): Use it. + (fn.def1): Add nested_name_specifier type_name cases. + * class.c (build_self_reference): New function. + (finish_struct): Handle access_default later, move self-reference + decl to the end. + * pt.c (lookup_template_class): Handle getting a TYPE_DECL. + * cp-tree.h: Adjust. - * decl.c (build_default_constructor): #if 0 out. + * pt.c (do_function_instantiation): Separate handling of member + functions and non-member functions properly. - * *: Eradicate TYPE_GETS_{ASSIGNMENT,ASSIGN_REF,CONST_ASSIGN_REF, - CONST_INIT_REF}, TYPE_HAS_REAL_CONSTRUCTOR. +Mon Mar 25 14:23:22 1996 Jason Merrill - * decl.c (grokdeclarator): Don't return void_type_node for - friends being defined here. + * pt.c (process_template_parm): Improve error for 'volatile class K'. - * init.c (perform_member_init): Only do the init if it's useful. + * class.c (finish_struct_1): Check the right slot for destructors. - * lex.c (default_copy_constructor_body): If we don't need to do - memberwise init, just call __builtin_memcpy. - (default_assign_ref_body): Ditto. + * decl.c (start_enum): Complain about enum templates. - * decl.c (grokdeclarator): If friendp && virtualp, friendp = 0. +Mon Mar 25 13:25:31 1996 Mike Stump -Fri Feb 4 13:02:56 1994 Mike Stump + * init.c (resolve_offset_ref): Offset pointers to member data by one. + * typeck.c (unary_complex_lvalue): Likewise. - * lex.c (reinit_parse_for_method, cons_up_default_function): - Don't give warn_if_unknown_interface warning when it came from a - system header file. - * pt.c (end_template_decl, instantiate_template): Ditto. - * decl.c (start_decl): Ditto. +Mon Mar 25 13:30:42 1996 Bob Manson -Fri Feb 4 00:41:21 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (c_expand_return): Check for a returned local + array name, similar to the check for an ADDR_EXPR. - * decl.c (grokdeclarator): Don't try to set TYPE_WAS_ANONYMOUS on - enums. +Mon Mar 25 13:07:19 1996 Jason Merrill - * decl2.c (constructor_name_full): Use IS_AGGR_TYPE_CODE instead of - IS_AGGR_TYPE, since we don't know it's a type. + * decl.c (cp_finish_decl): Don't build cleanups for static + variables here. -Thu Feb 3 11:36:46 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Mar 22 17:57:55 1996 Mike Stump - * decl.c (grokdeclarator): Don't complain about anonymous unions. + * typeck.c (build_modify_expr): Fix error messages to be more + accurate. + * cp-tree.h (assop_as_string): Parallel to op_as_string, but for + assignment operators. + * error.c (assop_as_string): Likewise. Add support for `%Q' for + assignment operators. - * cp-tree.h (TYPE_WAS_ANONYMOUS): This struct was originally - anonymous, but had a name given to it by a typedef. +Fri Mar 22 13:48:29 1996 Jason Merrill - * decl.c (grokdeclarator): When renaming an anonymous struct, set - TYPE_WAS_ANONYMOUS. + * decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also + give an error if initialized. Pedwarn about nested type with the + same name as its enclosing class. - * decl2.c (constructor_name_full): Use TYPE_WAS_ANONYMOUS. + * pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT. - * cp-tree.h (DECL_UNDEFINED_FRIENDS): #if 0 out. + * typeck.c (require_complete_type): Be sure to instantiate the + MAIN_VARIANT of the type. - * init.c (xref_friend): Don't set up DECL_UNDEFINED_FRIENDS. - (embrace_waiting_friends): Don't use DECL_UNDEFINED_FRIENDS. - - * decl.c (grokdeclarator): Set TYPE_NESTED_NAME properly on nested - anonymous structs that get typedef'd. + * decl2.c (finish_file): Instantiate pending templates before + processing static constructors and destructors. - * decl.c (grokdeclarator): Always return void_type_node for - friends. + * pt.c (instantiate_decl): Don't instantiate functions at toplevel + unless at_eof. - * error.c (dump_function_decl): Don't use DECL_CLASS_CONTEXT for - friends. - (dump_function_decl): Don't print out default args for - a function used in an expression. +Fri Mar 22 09:30:17 1996 Bob Manson - * decl.c (grokdeclarator): Give error on abstract declarator used - in an invalid context (i.e. `void (*)();'). + * decl2.c (delete_sanity): If error_mark_node is passed + in as an expression, quit while we're ahead. - * error.c (cp_line_of): Support _TYPE nodes. - (cp_file_of): Ditto. + * decl.c (grokdeclarator): Give an error message if `friend' + is combined with any storage class specifiers. - * cvt.c (build_up_reference): Don't abort if passed a SAVE_EXPR; - it can happen for the RHS of an assignment stmt where the LHS is - a COND_EXPR. +Wed Mar 20 14:51:55 1996 Jason Merrill - * init.c (expand_aggr_init_1): Deal with bracketed initializer - lists properly. + * parse.y (named_complex_class_head_sans_basetype): Don't crash on + definition of nonexistent nested type. - * class.c (finish_struct): Deal with enumerators and typedefs - again. + * error.c (dump_decl, case TYPE_DECL): Fix decision for whether or + not to say 'typedef'. -Wed Feb 2 11:30:22 1994 Jason Merrill (jason@deneb.cygnus.com) +Wed Mar 20 00:11:47 1996 Brendan Kehoe - * class.c (finish_struct): Tidy up loop over fields. + * cp-tree.h (struct lang_type): Make search_slot a tree, not a char*. + * search.c (dfs_walk, dfs_init_vbase_pointers, + expand_upcast_fixups): Remove cast of CLASSTYPE_SEARCH_SLOT. + (dfs_find_vbases): Remove cast for CLASSTYPE_SEARCH_SLOT init. - * errfn.c (cp_thing): Don't advance twice after a format. +Tue Mar 19 17:56:03 1996 Jason Merrill - * class.c (finish_struct): Complain about needing a constructor - if a member has only non-default constructors, and don't try to - generate a default constructor. + * except.c (build_throw): Support minimal parse. + * pt.c (tsubst_copy): Support THROW_EXPR. + * decl2.c (build_expr_from_tree): Likewise. - * decl.c (finish_decl): Also do the constructor thing if - TYPE_NEEDS_CONSTRUCTING is set (for arrays). + * pt.c (mangle_class_name_for_template): Always allocate + scratch_firstobj. - * search.c (unuse_fields): New function: mark all fields in this - type unused. - (dfs_unuse_fields): Helper function. +Tue Mar 19 16:34:31 1996 Bob Manson - * class.c (pushclass): If the new class is the same as the old - class, still unuse the fields. - (unuse_fields): Move to search.c. + * cvt.c (cp_convert_to_pointer): Give an appropriate error + when trying to cast from an incomplete type. - * decl.c (grok_op_properties): Add friendp argument. - (grokfndecl): Pass it. - (start_method): Ditto. +Tue Mar 19 16:00:33 1996 Jason Merrill - * decl2.c (delete_sanity): Add use_global_delete parameter to catch - ::delete calls. + * pt.c (instantiate_class_template): Don't bother setting up + CLASSTYPE_TAGS explicitly, as the nested types will add + themselves. - * parse.y (unary_expr): Pass new parameter to delete_sanity. +Tue Mar 19 15:48:43 1996 Bob Manson - * lex.c (default_copy_constructor_body): Don't choke if the union - has no fields. - (default_assign_ref_body): Ditto. + * decl.c (shadow_tag): Remove old error check for usage of + an enum without a previous declaration. + (xref_tag): Add error message about usage of enums without a + previous declaration. - * call.c (compute_conversion_costs_ansi): Do the right thing for - ellipsis matches. +Tue Mar 19 09:21:35 1996 Jason Merrill - * decl.c (push_to_top_level): Optimize. + * lex.c (do_identifier): Only do name consistency check if we're + parsing. - * decl.c (start_function): Look for the lexical scope of a friend - in DECL_CLASS_CONTEXT. + * pt.c (push_template_decl): Don't crash if we get a member defn + that doesn't match. - * init.c (do_friend): Set DECL_CLASS_CONTEXT on global friends. + * decl.c (xref_tag_from_type): New function to do an xref without + always having to figure out code_type_node. + * cp-tree.h: Declare it. + * pt.c (instantiate_class_template): Use it for friend classes. + (lookup_template_class): Use it. -Tue Feb 1 15:59:24 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck2.c (build_functional_cast): Pull out a single parm before + passing it to build_c_cast. - * cp-tree.h (TREE_GETS_PLACED_NEW): New macro. +Tue Mar 19 09:07:15 1996 Bob Manson - * init.c (init_init_processing): Don't assign BIN/BID to the - IDENTIFIER_GLOBAL_VALUEs of their respective operators. - (build_new): Check TREE_GETS_PLACED_NEW. + * expr.c (do_case): Give an error message if a pointer is + given as a case value. - * decl.c (grok_op_properties): Don't set TREE_GETS_NEW for a decl of - op new with placement, set TREE_GETS_PLACED_NEW. +Mon Mar 18 21:57:54 1996 Jason Merrill - * cp-tree.h (ANON_UNION_P): New macro. Applies to decls. + * typeck.c (build_c_cast): Don't pull single TEMPLATE_DECL out of + an overload list. - * class.c (finish_struct): Don't treat anonymous unions like - other aggregate members. Do synthesize methods for unions without - a name, since they may or may not be "anonymous unions". + * lex.c (cons_up_default_function): Really, now, interface hackery + does not apply to synthesized methods. - * decl2.c (grok_x_components): Wipe out memory of synthesized methods - in anonymous unions. +Mon Mar 18 18:20:57 1996 Mike Stump - * lex.c (default_copy_constructor_body): Support unions. - (default_assign_ref_body): Ditto. + * call.c (build_method_call): Ctors and dtors now have special names + with respect to lookups. + * class.c (add_method): Likewise. + (grow_method): Likewise. + (finish_struct_methods): Likewise. + (warn_hidden): Likewise. + (finish_struct_1): Likewise. + * cvt.c (convert_to_reference): Likewise. + (convert_to_aggr): Likewise. + (cp_convert): Likewise. + * decl2.c (check_classfn): Likewise. + * init.c (expand_member_init): Likewise. + (expand_default_init): Likewise. + (expand_aggr_init_1): Likewise. + (build_offset_ref): Likewise. + (build_new): Likewise. + (build_delete): Likewise. + * lex.c (do_inline_function_hair): Likewise. + * search.c (lookup_field_1): Likewise. + (lookup_fnfields_here): Likewise. + (lookup_field): Likewise. + (lookup_fnfields): Likewise. + (get_virtual_destructor): Likewise. + (dfs_debug_mark): Likewise. + (dfs_pushdecls): Likewise. + (dfs_compress_decls): Likewise. + * tree.c (layout_basetypes): Likewise. + * typeck.c (build_component_ref): Likewise. + (build_x_function_call): Likewise. + (build_modify_expr): Likewise. + (convert_for_initialization): Likewise. + (build_functional_cast): Likewise. + * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Likewise. + (CTOR_NAME): New. + (DTOR_NAME): New. + * decl.c (ctor_identifier): New. + (dtor_identifier): New. + (init_decl_processing): Set them. + +Mon Mar 18 18:00:51 1996 Mike Stump + + * typeck.c (build_component_ref): Don't get confused by fields whose + context has no type name, like pointer to member functions. + +Mon Mar 18 13:19:03 1996 Jason Merrill + + * decl.c (grokdeclarator): Handle typedef without declarator. + + * pt.c (tsubst): Handle SCOPE_REF in declarator. + + * parse.y (bad_parm): Catch another case of missing `typename'. + + * lex.c (yyprint): Handle TYPE_DECLs. + + * decl.c (start_function): Don't try to be clever. + + * lex.c: Lose compiler_error_with_decl. + * typeck2.c: Lose error_with_aggr_type. + (incomplete_type_error): Use cp_* instead of old functions. + (readonly_error): Likewise. + * typeck.c (convert_arguments): Likewise. + * search.c (lookup_nested_field): Likewise. + * method.c (make_thunk): Likewise. + * decl.c (grokparms): Likewise. + * cp-tree.h: Update. -Mon Jan 31 12:07:30 1994 Jason Merrill (jason@deneb.cygnus.com) + * tree.c (min_tree_cons): Call copy_to_permanent for the purpose + and value. - * cp-tree.h: Fix documentation of LOOKUP_GLOBAL, add prototypes. +Mon Mar 18 11:25:52 1996 Bob Manson - * error.c (args_as_string): New function (%A), like type_as_string - except NULL_TREE -> "..." + * method.c (build_opfncall): When deleting a pointer to an + array, build a new pointer to the tree past any ARRAY_TYPE + nodes. - * call.c (build_overload_call_real): Fix for new overloading. +Mon Mar 18 10:11:46 1996 Brendan Kehoe - * decl.c (grok_op_properties): Set all of the TYPE_OVERLOADS_* flags - here. + * decl.c (lookup_name_real): Initialize local var TYPE to NULL_TREE. - * parse.y (operator_name): Instead of here. +Fri Mar 15 11:03:57 1996 Jason Merrill - * typeck2.c (build_functional_cast): Treat a TREE_LIST as a list - of functions. + * pt.c (instantiate_decl): Only call import_export_decl if at_eof + and ! DECL_INLINE. - * call.c (build_overload_call_real): Support LOOKUP_SPECULATIVELY. + * decl.c (finish_function): Don't set nested based on + hack_decl_function_context. + * parse.y (function_try_block): Check for nested function. + (pending_inlines): Likewise. - * method.c (build_opfncall): Don't need to massage return value - any more, call build_overload_call with all flags. + * decl2.c (build_expr_from_tree): If a unary op already has a + type, just return it. - * typeck.c (build_x_binary_op): Put back speculative call to - build_opfncall. - (build_x_unary_op): Ditto. - (build_x_conditional_expr): Ditto. + * decl2.c (finish_prevtable_vardecl): Use ADJUST_VTABLE_LINKAGE. -Mon Jan 31 10:00:30 1994 Mike Stump + * decl2.c (walk_vtables): vardecl_fn returns int; return 1 if it does. + (finish_file): Check the return value of walk_vtables. + (finish_prevtable_vardecl): Return int. + (finish_vtable_vardecl): Likewise. + (prune_vtable_vardecl): Likewise. + * lex.c (set_vardecl_interface_info): Likewise. + * cp-tree.h: Adjust return types. - * cvt.c (build_type_conversion_1): Change call to pedwarn into - warning, and conditionalize upon warn_cast_qual. + * class.c (delete_duplicate_fields_1): Don't complain about + duplicate nested types if they're the same type. + (finish_struct): Remove check for duplicate. + * decl2.c (grokfield): Don't check for typedef of anonymous type. -Fri Jan 28 11:48:15 1994 Jason Merrill (jason@deneb.cygnus.com) +Thu Mar 14 10:00:19 1996 Jason Merrill - * search.c (lookup_field): If xbasetype is a binfo, copy it to - avoid clobbering its inheritance info. + * cp-tree.h: Lose SIGNATURE_GROKKING_TYPEDEF. - * call.c (build_method_call): Don't overwrite basetype_path with - TYPE_BINFO (inst_ptr_basetype) if they have the same type. + * decl.c (grokdeclarator): Lose special handling of class-level + typedef. Lose SIGNATURE_GROKKING_TYPEDEF. Set + SIGNATURE_HAS_OPAQUE_TYPEDECLS later. - * search.c (compute_access): Fix handling of protected inheritance - and friendship with the enclosing class. + * cvt.c (convert_pointer_to_real): Retain cv-quals in conversion. - * typeck2.c (store_init_value): Allow passing of TREE_CHAIN for - initialization of arbitrary variable. + * pt.c (tsubst_copy): Strip cv-quals from destructor name types. - * typeck2.c (build_functional_cast): Only try calling a method if - one exists. + * search.c (compute_access): Fix handling of anonymous union + members. + * class.c (finish_struct_anon): Propagate TREE_{PRIVATE,PROTECTED} + from anonymous unions to their members. - * decl.c (grokdeclarator): Move handling of constructor syntax - initialization into first loop for generality. - (parmlist_is_random): Lose. + * typeck.c (build_x_function_call): For static member functions, + hand off to build_member_call. - * lex.c (cons_up_default_function): Set TREE_PARMLIST on arguments - to default function. +Wed Mar 13 14:03:34 1996 Jason Merrill -Thu Jan 27 19:26:51 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (build_component_ref): Handle OFFSET_REFs. - * decl.c (grokparms): Abort if we get called with something we don't - expect. + * init.c (expand_vec_init): Fix init == 0 case. -Thu Jan 27 17:37:25 1994 Mike Stump +Tue Mar 12 14:36:02 1996 Jason Merrill - * call.c (build_overload_call_real): Change argument complain to - flags to match style of rest of code. Pass it down to - build_function_call_real as necessary. - * call.c (build_overload_call, build_overload_call_maybe): Change - argument complain to flags to match style of rest of code. - * cp-tree.h (build_function_call_real): Added fourth flags - argument. - * cvt.c (convert_to_reference): Only give warning messages, if - LOOKUP_COMPLAIN is set. - * typeck.c (build_x_function_call): Change simple complain - argument to build_overload_call_maybe and build_overload_call, to - LOOKUP_COMPLAIN to match style of rest of code. - * typeck2.c (build_functional_cast): Ditto. - * typeck.c (build_function_call_real): Add flags, so that we can - not complain, if we don't want to complain. Complain about - arguments, if we are complaining, otherwise don't. - * typeck.c (build_function_call, build_function_call_maybe): - Stick in flags argument. - * typeck.c (build_x_binary_op, build_x_unary_op, - build_x_conditional_expr, build_x_compound_expr): Follow style of - build_x_indirect_ref, as it is more correct and more common. + * init.c (build_new): Pedwarn about init and array new. + (expand_vec_init): Handle lists, use convert_for_initialization. -Thu Jan 27 14:36:20 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (convert_for_initialization): Pass LOOKUP_NO_CONVERSION + when converting to an aggregate type. + * cvt.c (cp_convert): Pass it through. - * call.c (build_method_call): Don't check for being called with - a pointer. + * typeck.c (build_conditional_expr): Handle user-defined + conversions to slightly different types. - * decl2.c (finish_file): Don't play with DECL_CLASS_CONTEXT for the - static initializer function. + * decl.c (grokdeclarator): Force an array type in a parm to be + permanent. - * init.c (build_member_call): Use convert_force here, too. + * decl2.c (do_using_directive): Sorry. + (do_namespace_alias): Likewise. + * lex.c (real_yylex): Warn about using the `namespace' keyword. - * search.c (compute_access): Only treat static members specially - if they are referenced directly. +Sun Mar 10 22:26:09 1996 Jason Merrill -Wed Jan 26 18:28:14 1994 Jason Merrill (jason@deneb.cygnus.com) + * parse.y (datadef): Move call to note_list_got_semicolon up. - * gxxint.texi (Access Control): New node. +Fri Mar 8 11:47:26 1996 Mike Stump - * search.c (current_scope): New function; returns whichever of - current_class_type and current_function_decl is the most nested. - (compute_access): Total overhaul to make it clearer and more - correct. Don't use the cache for now; in the only situation where - it was used before, it gained nothing. This frees up three of the - DECL_LANG_FLAGs for possible other use! + * tree.c (unsave_expr): Don't unsave, UNSAVE_EXPRs. - * cp-tree.h: #if 0 out DECL_PUBLIC & friends. +Fri Mar 8 11:29:06 1996 Mike Stump - * typeck.c (build_component_ref_1): Don't check DECL_PUBLIC. + * decl.c (cp_finish_decl): The exception regions have to be + nested, not overlapping. We start the exception region for a + decl, after it has been fully built, and all temporaries for it + have been cleaned up. - * call.c (build_method_call): Use convert_force to cast `this' -- - rely on the access checking for the method itself. +Thu Mar 7 17:46:06 1996 Mike Stump - * init.c (is_friend): Do the nesting thing, handle types. I am - my own friend. - (is_friend_type): Become a shell for is_friend. - (add_friend): Never stick in ctype. - Why are the friendship functions in init.c, anyway? + * tree.c (vec_binfo_member): Don't core dump if we have no bases. -Wed Jan 26 17:50:00 1994 Mike Stump +Thu Mar 7 14:11:49 1996 Jason Merrill - * cvt.c (build_type_conversion_1): Don't conditionalize call to - pedwarn upon pedantic. + * tree.def: Add RETURN_INIT. + * pt.c (instantiate_decl): Handle RETURN_INIT. + * decl.c (store_return_init): Handle minimal_parse_mode. -Wed Jan 26 17:20:46 1994 Mike Stump + * tree.c (cp_build_type_variant): Just return an error_mark_node. + * decl.c (make_typename_type): Don't try to get the file and line + of an identifier. + * typeck.c (comptypes): Handle TYPENAME_TYPE. - * cvt.c (convert_to_reference): Add 8.4.3 checking so that one - gets a warning if one tries to initialize a non-const & from a - non-lvalue. - * cvt.c (convert_to_reference): Use %P format for argument - numbers in warnings. +Wed Mar 6 18:47:50 1996 Per Bothner -Wed Jan 26 14:35:06 1994 Mike Stump + * decl.c (poplevel): Make sure we clear out and restore old local + non-VAR_DECL values by default when they go out of scope. - * init.c (build_delete): Follow style in call.c to construct the - virtual call to the desctructor, as that code is right. Fixes a - problem of the compiler saying a pointer conversion is ambiguous. +Wed Mar 6 09:57:36 1996 Jason Merrill -Wed Jan 26 11:28:14 1994 Jason Merrill (jason@deneb.cygnus.com) + * method.c (build_overload_value): Use DECL_ASSEMBLER_NAME in + referring to addresses of variables and functions. - * cp-tree.h (VTABLE_NAME_P): Change other occurrence of - VTABLE_NAME_FORMAT to VTABLE_NAME. + * error.c (dump_expr): Support SIZEOF_EXPR. - * *: s/visibility/access/g + * init.c (do_friend): Use the return value of check_classfn. -Tue Jan 25 18:39:12 1994 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (convert_arguments): Call complete_type. - * typeck.c (build_modify_expr): Don't smash references if INIT_EXPR. + * method.c (hack_identifier): After giving an error, set value to + error_mark_node. -Tue Jan 25 13:54:29 1994 Mike Stump +Tue Mar 5 16:00:15 1996 Jason Merrill + + * tree.c (hack_decl_function_context): Kludge around DECL_CONTEXT + lossage for local classes. + * cp-tree.h: Declare it. + * decl.c (lookup_name_real): Evil, painful hack for local classes. + (grokfndecl): Set DECL_CLASS_CONTEXT and DECL_NO_STATIC_CHAIN here. + Use hack_decl_function_context. + (grokdeclarator): Don't set DECL_NO_STATIC_CHAIN here. + (start_function): Use hack_decl_function_context. + (finish_function): Likewise. + * method.c (synthesize_method): Likewise. + * lex.c (process_next_inline): Likewise. + (do_pending_inlines): Likewise. + * decl2.c (finish_file): Unset DECL_STATIC_FUNCTION_P when we're + done with it. - * init.c (build_delete): Back out Jan 17th & 18th pacthes, as - they break libg++. +Mon Mar 4 22:38:39 1996 Gerald Baumgartner -Tue Jan 25 13:11:45 1994 Jason Merrill (jason@deneb.cygnus.com) + * sig.c (build_signature_pointer_or_reference_type): Align + signature pointers/references on 8-byte boundaries so they can be + grabbed 2 words at a time on a Sparc. - * decl.c (duplicate_decls): Fix pointer arithmetic. +Tue Mar 5 10:21:01 1996 Jason Merrill -Mon Jan 24 15:50:06 1994 Chip Salzenberg (chip@fin.uucp) + * method.c (hack_identifier): Requiring a static chain is now a + hard error. + * decl.c (grokdeclarator): Set DECL_NO_STATIC_CHAIN on nested + functions. - [ cp-* changes propagated from c-* changes in 940114 snapshot ] - * cp-parse.y (maybe_attribute): Allow multiple __attribute__ - clauses on a declaration. +Mon Mar 4 20:03:33 1996 Jason Merrill -Mon Jan 24 17:06:23 1994 Jason Merrill (jason@deneb.cygnus.com) + * init.c (build_offset_ref): Call complete_type. - * class.c (finish_struct): Do synthesize methods for anon - structs, just not unions. + * decl.c (pop_from_top_level): Always pop previous_class_type. -Mon Jan 24 13:50:13 1994 Kung Hsu (kung@mexican.cygnus.com) + * parse.y: Handle multiple decls in a for-init-statement. + * pt.c (tsubst_expr): Likewise. - * decl.c (xref_tag): handle anonymous nested type. - * decl.c (globalize_nested_type): add no globalize bit check. - * spew.c (hack_more_ids) : templated nested decl not push top - level. + * pt.c (tsubst): Use tsubst_expr for the second operand of an + ARRAY_REF. - * parse.y : get rid of 'goto do_components'. It is much better - for debugging. + * decl.c (maybe_push_to_top_level): Don't save previous_class_type. + (poplevel_class): Set it here. + (pop_from_top_level): Pop it here if we're returning to class scope. + * class.c (pushclass): Don't set it here. - * decl.c (is_anon_name): get rid of the function and use the - macro ANON_AGGRNAME_P. - * pt.c : ditto. + * decl.c (maybe_push_to_top_level): Save current_template_parms, + and clear it if !pseudo. + (pop_from_top_level): Restore it. -Fri Jan 21 14:06:02 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (finish_file): Push the dummy each time we walk the list + of vtables. - * class.c (finish_struct): Don't synthesize any methods for - anonymous structs/unions. + * error.c (dump_expr): Support LOOKUP_EXPR and actually do + something for CAST_EXPR. + +Mon Feb 19 14:49:18 1996 Rusty Russell - * typeck.c (build_modify_expr): Don't treat pmf's as class objects. + * cvt.c (cp_convert): Warn about implicit conversion of the + address of a function to bool, as it is always true. -Thu Jan 20 18:56:46 1994 Jason Merrill (jason@deneb.cygnus.com) +Fri Feb 23 23:06:01 1996 Rusty Russell - * method.c (build_opfncall): Call build_indirect_ref on - synthesized instance for operator delete. + * typeck.c (c_expand_return): Fix warning for local externs returned. - * pt.c (type_unification): Don't abort if called with a list of - types in ARGS. +Mon Mar 4 15:03:11 1996 Jason Merrill - * class.c (instantiate_type): Deal with function templates. + * tree.c (mapcar): Propagate const and volatile properly. -Thu Jan 20 16:55:35 1994 Jim Wilson (wilson@sphagnum.cygnus.com) + * typeck.c (complete_type): Be sure to instantiate the + MAIN_VARIANT of the type. - * Makefile.in (CC): Default to cc not gcc. + * method.c (synthesize_method): Class interface hackery does not + apply to synthesized methods. -Thu Jan 20 13:47:54 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Mar 4 14:05:23 1996 Jason Merrill - * typeck.c (build_modify_expr): Call constructor if appropriate. + * pt.c (comp_template_args): Use comptypes rather than just + checking for TEMPLATE_TYPE_PARM equivalence. - * decl.c (push_to_top_level): Clear out class-level bindings cache. + * typeck.c (build_x_function_call): Call complete_type before + checking TYPE_OVERLOADS_CALL_EXPR. -Wed Jan 19 13:51:22 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Mar 4 18:48:30 1996 Manfred Hollstein - * call.c (resolve_scope_to_name): Work recursively (previously only - looked down one level). + * g++.c (main): Check also for new define ALT_LIBM. - * lex.c (do_pending_inlines): If we're still dealing with the last - batch of inlines, don't start working on a new one. +Fri Mar 1 13:09:33 1996 Jason Merrill - * Makefile.in (stamp-parse): Update conflict count. - (TAGS): Fix. + * pt.c (instantiate_class_template): If we don't have a pattern + yet, that's OK. + (coerce_template_parms): If we see a local class, bail. - * parse.y (explicit_instantiation): New rule; implements - 'template A' syntax (though not 'template foo(int)' yet). - (structsp): Add explicit_instantiation. + * decl.c (grok_reference_init): Make sure there's a type before + checking its code. -Tue Jan 18 13:53:05 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (do_function_instantiation): Avoid crashing on invalid decls. + (push_template_decl): Likewise. - * class.c (finish_struct, etc.): Simplify decision to synthesize - a destructor. + * parse.y (named_class_head): Set + CLASSTYPE_TEMPLATE_SPECIALIZATION here if we have basetypes. - * call.c, class.c, cp-tree.h, decl.c, init.c, - ptree.c, search.c, typeck.c, typeck2.c: Nuke - TYPE_NEEDS_CONSTRUCTOR (change all calls to TYPE_NEEDS_CONSTRUCTING). - * init.c (expand_aggr_init_1): Don't try non-constructor methods - of initializing objects. - (build_new): Don't try other methods if the constructor lookup fails. + * decl.c (xref_tag): Diagnose redeclaration of template + type-parameter name. - * class.c (finish_base_struct): Set cant_have_default_ctor and - cant_synth_copy_ctor properly. - (finish_struct): Ditto. + * error.c (dump_type): Handle anonymous template type parms. -Mon Jan 17 13:58:18 1994 Jason Merrill (jason@deneb.cygnus.com) + * pt.c (instantiate_template): Use TYPE_MAIN_DECL instead of + TYPE_STUB_DECL. + (coerce_template_parms): Likewise. - * typeck.c (build_modify_expr_1): #if 0 out again. - (build_modify_expr): #if 0 out memberwise init code again. +Thu Feb 29 16:26:01 1996 Mike Stump - * lex.c (default_copy_constructor_body): Be const-correct. - (default_assign_ref_body): Ditto. + * class.c (instantiate_type, case {ARRAY,INDIRECT}_REF, + case ADDR_EXPR): Don't modify rhs if a subinstantiation fails. - * init.c (perform_member_init): Use TYPE_HAS_CONSTRUCTOR to decide - whether or not to use it, rather than TYPE_NEEDS_CONSTRUCTING. - (expand_aggr_init): Disable silent conversion from initializer list - to list of args for a constructor. +Thu Feb 29 08:20:25 1996 Jason Merrill - * class.c (base_info): Lose needs_default_ctor. - (finish_base_struct): Ditto. - (finish_struct): Ditto. + * pt.c (instantiate_template): Take the MAIN_VARIANT of the type + before trying to get its STUB_DECL. + (coerce_template_parms): Likewise. - * decl.c (init_decl_processing): Don't turn off flag_default_inline - just because flag_no_inline is on. - (finish_decl): Use TYPE_HAS_CONSTRUCTOR to decide to use - constructor. + * parse.y (template_type_parm): If they didn't use 'class', + pretend they did after giving an error. - * class.c (finish_struct): Synthesize default ctor whenever - allowed. + * pt.c (coerce_template_parms): Diagnose use of local class. - * Makefile.in (TAGS): Don't try to run etags on cp-parse.y. + * decl.c (grok_reference_init): Use instantiate_type. -Sat Jan 15 18:34:33 1994 Mike Stump + * error.c (dump_expr): Handle TEMPLATE_DECLs. - * Makefile.in, configure: Handle the C++ front-end in a - subdirectory. - * cp-*: Move C++ front-end to cp/*. + * parse.y (named_class_head): Diagnose mismatching types and tags. -Fri Jan 14 14:09:37 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (pushdecl): Type decls and class templates clash with + artificial type decls, not hide them. - * cp-typeck.c (build_function_call_real): Modify to match other - instances of taking the address of the function. + * decl.c (redeclaration_error_message): Diagnose redefinition of + templates properly. + (duplicate_decls): Diagnose disallowed overloads for template + functions, too. - * cp-class.c (finish_struct): Set TYPE_HAS_REAL_CONSTRUCTOR to 1 if - there are non-synthesized constructors. - Only set TYPE_NEEDS_CONSTRUCTOR if TYPE_HAS_REAL_CONSTRUCTOR. - Always generate copy constructor if possible. + * decl.c (start_decl): Call complete_type before checking for a + destructor. - * cp-tree.h (lang_type): Add has_real_constructor bitfield. - (TYPE_HAS_REAL_CONSTRUCTOR): Define. + * pt.c (tsubst): Use tsubst_expr on the elts of a VEC. - * cp-lex.c (default_copy_constructor_body): Use init syntax - for all bases. + * decl.c (xref_tag): A TEMPLATE_TYPE_PARM is a match. - * cp-type2.c (store_init_value): Only give error for initializer list - if TYPE_HAS_REAL_CONSTRUCTOR. +Wed Feb 28 09:28:44 1996 Jason Merrill -Thu Jan 13 15:38:29 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (grok_op_properties): Don't check for operator++(int) in + a template. - * cp-tree.h (DECL_SYNTHESIZED): Add defn. - (lang_decl): Add synthesized bitfield to decl_flags. + * tree.c (perm_manip): Return a copy of variable and function + decls with external linkage. - * cp-lex.c (cons_up_default_function): Use DECL_SYNTHESIZED to mark - artificial methods, rather than a line # of 0. + * tree.def: Change some of the min tree codes to type "1". + * pt.c (uses_template_parms): Handle 'e's, return 1 for LOOKUP_EXPRs. + * method.c (build_overload_int): Emit something arbitrary for + anything but an INTEGER_CST if we're in a template. -Fri Jan 14 18:25:29 1994 Kung Hsu (kung@mexican.cygnus.com) + * decl.c (cp_finish_decl): Call complete_type before deciding + whether or not to lay out the decl. - * cp-decl (xref_tag): fix a bug in conflict type. - * cp-parse.y : add SCOPED_NAME for uninstantiated template nested - type reference. - * cp-spew.c (yylex) : generated SCOPED_NAME token. - * cp-lex.c (yyprint): handle SCOPED_NAME. + * lex.c (do_identifier): Check for DECL_INITIAL before using it. -Fri Jan 14 17:00:29 1994 Mike Stump +Tue Feb 27 16:35:32 1996 Jason Merrill - * cp-decl.c (pushdecl): Revert patch from Jan 11 19:33:03, as it is - not right. + * typeck2.c (build_x_arrow): Call complete_type. -Thu Jan 13 14:00:35 1994 Kung Hsu (kung@mexican.cygnus.com) + * pt.c (add_pending_template): Broken out. + (lookup_template_class): If -fexternal-templates, call it for all + the methods of implemented types. + (instantiate_class_template): Instead of instantiating them here. + (instantiate_decl): Handle -fexternal-templates earlier. - * cp-decl2.c (grok_x_components): fix a bug that enum type does not - have type_flags. +Tue Feb 27 15:51:32 1996 Brendan Kehoe -Thu Jan 13 11:39:34 1994 Mike Stump + * search.c, lex.c, decl.c, class.c, cp-tree.h: Don't wrap the + memoized lookup stuff inside GATHER_STATISTICS. - Ensure that all vtable pointers are initialized with all the right - values. +Tue Feb 27 10:38:08 1996 Jason Merrill - * cp-class.c (is_normal): Changed to reflect new meaning of - CLASSTYPE_VFIELD_PARENT. - * cp-class.c (maybe_fixup_vptrs): Use of - CLASSTYPE_NEEDS_VIRTUAL_REINIT here is misguided. Use - BINFO_MODIFIED instead. - * cp-class.c (finish_struct): Changed to reflect new meaning of - CLASSTYPE_VFIELD_PARENT. - * cp-decl.c (get_binfo_from_vfield): Removed, unneeded now. - * cp-decl.c (finish_function): Use init_vtbl_ptrs, instead of open - coding it here. - * cp-init.c (init_vfields): Changed name to init_vtbl_ptrs, and - re-implement. - * cp-init.c (emit_base_init): Use new name init_vtbl_ptrs. - * cp-tree.h (vfield_parent): Changed to integer. - * cp-tree.h (CLASSTYPE_VFIELD_PARENT): Changed docs to reflect new - meaning. - * cp-tree.h (init_vtbl_ptrs): Added init_vtbl_ptrs. + * decl.c (start_decl): Complain about array of incomplete type + here. + (grokdeclarator): Not here. -Wed Jan 12 18:24:16 1994 Kung Hsu (kung@mexican.cygnus.com) + * parse.y (template_parm): Expand full_parm inline so we can set + the rule's precedence. - * cp-decl.c (xref_tag): re-implement globalize nested type. - * cp-decl2.c (grok_x_components): ditto. - * cp-parse.y: ditto. - * cp-tree.h (lang_type): add no_globalize bit in type_flags. + * pt.c (tsubst_expr): If we're in a template, just do tsubst_copy. + (tsubst): tsubst_expr the DECL_INITIAL of FIELD_DECLs. + * decl2.c (grokbitfield): Don't check for integer constant here. + * class.c (finish_struct_1): Check here. -Wed Jan 12 14:08:09 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (define_label): Make the min decl go on permanent_obstack. - * cp-decl.c (grokdeclarator): Don't set TREE_PUBLIC on friend - decls with a definition attached. + * pt.c (unify): Don't handle CONST_DECLs. + (uses_template_parms): Don't check DECL_INITIAL on a CONST_DECL. + (tsubst_copy): Likewise. - * cp-typeck.c (build_modify_expr): Undo previous change in the case - of INIT_EXPRs. + * lex.c (do_identifier): Do pull the DECL_INITIAL out of a + CONST_DECL for a template parm. -Tue Jan 11 19:33:03 1994 Jason Merrill (jason@deneb.cygnus.com) +Mon Feb 26 12:48:18 1996 Jason Merrill - * cp-typeck.c (build_modify_expr): Replace code for generating - assignment semantics for classes with an error. - (build_modify_expr_1): #if 0 out. + * decl.c (grokdeclarator): Complain about array of incomplete type + here. + (start_decl_1): Not here. - * cp-decl.c (pushdecl): Patch bogus design of pushdecl - behavior for overloaded functions (it doesn't push anything). + * pt.c (tsubst): Handle pointer-to-function declarators. - * cp-class.c (finish_struct): When generating default op=, - set TYPE_HAS_ASSIGNMENT. + * method.c (hack_identifier): If pedantic, diagnose local class + methods that require a static chain. -Mon Jan 10 18:48:06 1994 Mike Stump + * decl.c (grok_op_properties): No longer static. + * cp-tree.h: Declare it. + * pt.c (tsubst): Call it for operators. + Use tsubst_copy for TREE_VECs. - * cp-cvt.c (convert): Make {double, clashing enum} -> enum - invalid. - * cp-typeck.c (convert_for_assignment): Simplify. - * cp-decl2.c (warn_enum_clash): Removed. - * invoke.texi (-Wenum-clash): Removed. - * toplev.c (-Wenum-clash): Removed. + * parse.y (template_arg): The expr has precedence like '>'. -Mon Jan 10 17:48:37 1994 Kung Hsu (kung@mexican.cygnus.com) +Fri Feb 23 14:51:52 1996 Jason Merrill - * cp-decl.c (finish_decl): fix incorrect popclass call. + * pt.c (coerce_template_parms): Don't coerce an expression using + template parms. + (uses_template_parms): Also check DECL_INITIAL in CONST_DECLs. + (tsubst): Don't use build_index_2_type if the max_value uses template + parms. + * method.c (build_overload_int): Emit something arbitrary for an + expression using template parms. + + * parse.y (template_close_bracket): New non-terminal to catch use + of '>>' instead of '> >' in template class names. + (template_type): Use it. + * Makefile.in (CONFLICTS): Causes one more r/r conflict. + + * tree.def: Add CAST_EXPR. + * typeck2.c (build_functional_cast): Use CAST_EXPR instead of + CONVERT_EXPR for minimal_parse_mode. + * typeck.c (build_c_cast): Likewise. + * pt.c (tsubst_copy): Likewise. + * decl2.c (build_expr_from_tree): Likewise. + * error.c (dump_expr): Likewise. + +Fri Feb 23 10:36:46 1996 Brendan Kehoe + + * except.c (SetTerminate, SetUnexpected): Put back global vars. + (init_exception_processing): Put back decl/init of + set_unexpected_fndecl and set_terminate_fndecl, needed to get the + fns from libstdc++. + + * decl.c (struct binding_level): Delete ACCEPT_ANY bitfield. + (declare_uninstantiated_type_level, uninstantiated_type_level_p): + Delete unused fns. + * cp-tree.h (declare_uninstantiated_type_level, + uninstantiated_type_level_p): Delete prototypes. + +Thu Feb 22 19:36:15 1996 Jason Merrill + + * pt.c (tsubst_expr): Add default return. + +Thu Feb 22 16:47:24 1996 Brendan Kehoe + + * error.c (fndecl_as_string): Delete unused arg CNAME. + * sig.c (build_signature_table_constructor, + build_signature_method_call): Fix calls. + + * class.c (the_null_vtable_entry): Delete var definition. + (init_class_processing): Delete tree the_null_vtable_entry init. + * decl.c (no_print_{functions, builtins}): Declare as static. + (__tp_desc_type_node): #if 0 var definition. + (init_type_desc): #if 0 init of __tp_desc_type_node. + (vb_off_identifier): Move var decl into init_decl_processing. + (current_function_assigns_this): Declare as static. + (int_ftype_ptr_ptr_int, void_ftype_ptr_int_int): Delete var decls. + (init_decl_processing): Delete init of void_ftype_ptr_ptr_int. + Move decls of string_ftype_ptr_ptr and int_ftype_string_string here. + * decl2.c (delete_sanity): Delete definition/mod of local var ELT_SIZE. + * init.c (BI_header_type, BI_header_size): Declare as static. + * pt.c (template_classes): Delete unused var. + (add_pending_template): Delete decl for non-existent fn. + (lookup_template_class): Delete vars CODE and TAG_CODE. + (instantiate_template): Delete unused var TARGS. + * cp-tree.h (vb_off_identifier, current_function_assigns_this): + Delete decls. + (__tp_desc_type_node): #if 0 var decl. + (fndecl_as_string): Fix prototype. + +Thu Feb 22 15:56:19 1996 Jason Merrill + + * tree.def: Add GOTO_STMT. + * pt.c (tsubst_expr): Support goto and labels. + * decl.c (define_label): Support minimal parsing. + * parse.y (simple_stmt): Likewise. + +Thu Feb 22 15:30:12 1996 Brendan Kehoe + + * xref.c (GNU_xref_member): Only define/set var I if + XREF_SHORT_MEMBER_NAMES is defined, to match when it's actually + used. + (GNU_xref_end_scope): Delete unused fifth arg TRNS. + (GNU_xref_end): Fix call. + * decl.c (poplevel, poplevel_class, finish_method): Fix calls. + * cp-tree.h (GNU_xref_end_scope): Fix prototype. + + * tree.c (build_exception_variant): Delete unused vars I, A, T, + T2, and CNAME. + (layout_vbasetypes): Delete unused var NONVIRTUAL_VAR_SIZE. + (mapcar): Delete unused var CODE. + (build_cplus_new): Delete unused arg WITH_CLEANUP_P. + (break_out_cleanups): Fix call. + (bot_manip): Likewise. + * call.c (build_method_call): Likewise. + * cvt.c (build_up_reference, convert_to_reference, cp_convert): + Likewise. + * typeck.c (unary_complex_lvalue, build_modify_expr, + convert_for_initialization): Likewise. + * typeck2.c (build_functional_cast): Likewise. + * cp-tree.h (build_cplus_new): Fix prototype. + + * repo.c (open_repo_file): Delete unused var Q. + (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. + * cp-tree.h (mark_{decl,class}_instantiated, finish_repo): Add + prototypes. + +Thu Feb 22 14:53:35 1996 Jason Merrill + + * parse.y (pending_inlines): Add function_try_block case. + + * pt.c (unify): Fix for template const parms. + +Thu Feb 22 13:24:15 1996 Brendan Kehoe + + * lex.c (extract_interface_info): Delete forward decl. + (default_copy_constructor_body, default_assign_ref_body): Delete + decls for non-existent functions. + (synth_firstobj, inline_text_firstobjs): Delete unused vars. + (init_lex): Delete setting them. + (cons_up_default_function): Delete unused vars FUNC_BUF, + FUNC_LEN, and COMPLEX. Delete code setting COMPLEX. Delete old + #if 0'd synth code. + (toplevel, expression_obstack): Delete unused extern decls. + (tree_node_kind): Delete unused enum. + (tree_node_counts, tree_node_sizes): Wrap with #ifdef + GATHER_STATISTICS. + (tree_node_kind_names): Delete unused extern decl. + (synth_obstack): Delete unused var. + (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. + (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. + + * search.c: Wrap all of the memoized functions, macros, and + variables inside #ifdef GATHER_STATISTICS. + (lookup_field, lookup_fnfields): Likewise. + (init_search_processing): Likewise. + (reinit_search_statistics): Wrap whole function. + * lex.c (reinit_lang_specific): Wrap call to reinit_search_statistics. + + * decl.c (finish_function): Only call pop_memoized_context if + GATHER_STATISTICS is defined. + (start_function): Likewise for push_memoized_context. + * class.c (pushclass, popclass): Likewise. + + * cp-tree.h (CLASSTYPE_MTABLE_ENTRY): Move definition from here... + * search.c (CLASSTYPE_MTABLE_ENTRY): ... to here. + + * cvt.c (cp_convert): Delete unused local var FORM. + * cp-tree.h (can_convert, can_convert_arg, real_lvalue_p): Add + prototypes. + +Thu Feb 22 13:19:44 1996 Jason Merrill + + * pt.c (do_poplevel): Oops; really return what we get from + poplevel this time. + +Thu Feb 22 11:41:44 1996 Brendan Kehoe + + * cp-tree.h (is_aggr_type): Add prototype. + + * cp-tree.h ({push,pop}_cp_function_context): Add decls. + * method.c ({push,pop}_cp_function_context): Delete decls. + * except.c (start_eh_unwinder, end_eh_unwinder): Declare as void. + (SetUnexpected, SetTerminate): Delete unused vars. + (init_exception_processing): Don't set SetUnexpected or + SetTerminate. Don't set SET_UNEXPECTED_FNDECL or SET_TERMINATE_FNDECL. + (output_exception_table_entry): Delete unused array LABEL. + (expand_internal_throw): Delete unused var PARAMS. + (expand_start_catch_block): Delete unused var CLEANUP. + (emit_exception_table): Delete unused var EH_NODE_DECL. + (expand_builtin_throw): Delete unused vars UNWIND_AND_THROW and + GOTO_UNWIND_AND_THROW. Don't set them. + (end_eh_unwinder): Add top decl. + (pop_rtl_from_perm): Delete unused decl of PERMANENT_OBSTACK. + (exception_section, push_rtl_perm, do_function_call, + lang_interim_eh, push_eh_cleanup, eh_outer_context, + expand_end_eh_spec, end_eh_unwinder): Declare as static. + (saved_pc, saved_throw_type, saved_throw_value, saved_cleanup, + throw_used): Likewise. + * cp-tree.h (expand_end_eh_spec): Delete prototype. + + * search.c (dfs_mark, dfs_mark_vtable_path, + dfs_unmark_vtable_path, dfs_mark_new_vtable, + dfs_unmark_new_vtable, dfs_clear_search_slot, + dfs_search_slot_nonempty_p, bfs_markedp, bfs_unmarkedp, + bfs_marked_vtable_pathp, bfs_unmarked_vtable_pathp, + bfs_marked_new_vtablep, bfs_unmarked_new_vtablep): #if 0 unused + functions. + (n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1, + n_calls_lookup_fnfields, n_calls_lookup_fnfields_1, + n_calls_get_base_type, n_outer_fields_searched, n_contexts_saved): + Only define #ifdef GATHER_STATISTICS. + (reinit_search_statistics): Only init some vars if GATHER_STATISTICS + is defined. + (vbase_decl): Delete var definition. + (init_search): Delete old decl. + (init_vbase_pointers): Delete building of VBASE_DECL, since it's + never actually used. + (expand_indirect_vtbls_init): Delete init of VBASE_DECL. + (get_base_distance_recursive): Delete unused fourth arg + BASETYPE_PATH. Fix call . + (get_base_distance): Fix call. + (push_class_decls): Delete unused var ID. + (make_memoized_table_entry): Declare as static. + (breadth_first_search): Declare as static. + (tree_has_any_destructor_p): Declare as static. + (pop_class_decls): Delete unused arg pop_class_decls. + * class.c (popclass): Fix call to pop_class_decls. + * cp-tree.h (make_memoized_table_entry, breadth_first_search, + tree_has_any_destructor_p): Delete prototypes. + + * rtti.c (build_ptmf_desc): Delete unused arg TYPE. + (build_t_desc): Fix call. Delete unused vars ELEMS and TT. + (build_dynamic_cast): Delete unused local vars TMP1 and RETVAL. + (build_user_desc): Delete unused var T. + (build_class_desc): Delete unused vars T and OFF. + (build_t_desc): Delete unused var NAME_STRING. + (build_headof): Make static. + (get_bad_cast_node): Likewise. + (get_def_to_follow): Likewise. + * cp-tree.h (init_type_desc): Add prototype. + (build_headof): Remove prototype. + +Thu Feb 22 00:54:22 1996 Jason Merrill + + * pt.c (tsubst): Only look for matching decls at file scope for + non-member functions. - * cp-decl.c (is_anon_name): new function, check whether the name - is anonymous name generated by compiler. - * cp-decl.c (grokdeclarator): allow nested SCOPE_REF - * cp-spew.c (hack_more_ids): handle nested type in template. - * cp-parse.y : handle nested type reference in uninstantiated - template. - * cp-call.c (build_method_call): handle uninstantiated template - case. - * cp-pt.c (search_nested_type_in_tmpl): new function, search nested - type in template. - * cp-pt.c (lookup_nested_type_by_name): new function, lookup nested - type by name. - * cp-pt.c (tsubst): handle nested type search by name. + * call.c (build_scoped_method_call): Handle scoped destructor + calls in templates. -Mon Jan 10 14:32:18 1994 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (*_top_level): Also save previous_class_values. - * cp-init.c (build_member_call): Propagate qualifiers to new type. + * pt.c (tsubst_expr): Support do {} while loops. + * parse.y (simple_stmt): Likewise. + * tree.def: Likewise. - * cp-call.c (build_method_call): Count functions the new way. + * method.c (build_overload_identifier): For a class nested in a + template class, don't mangle in the template parms from our + context. -Fri Jan 7 19:03:26 1994 Jason Merrill (jason@deneb.cygnus.com) + * lex.c, cp-tree.h: Remove support for template instantiations in + the pending_inlines code. + * pt.c: Remove dead functions and unused arguments. + (uses_template_parms): TYPENAME_TYPEs always use template parms. + * parse.y: Stop passing anything to end_template_decl. + * tree.c (print_lang_statistics): Only print tinst info #ifdef + GATHER_STATISTICS. + +Wed Feb 21 16:57:33 1996 Brendan Kehoe + + * 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. + (sort_member_init): Delete unused var FIELDS_TO_UNMARK. + (emit_base_init): Delete unused local var BASE. Delete extern + decl of IN_CHARGE_IDENTIFIER. + (build_delete): Delete unused local var VIRTUAL_SIZE. + + * init.c (build_vec_delete): Delete unused third arg ELT_SIZE. + (build_delete): Fix call. + * decl2.c (delete_sanity): Likewise. + * cp-tree.h (build_vec_delete): Update prototype. + + * typeck.c (common_base_type): Delete unused var TMP. + (build_binary_op): Delete local var ARGS_SAVE. + (build_array_ref): Delete unused var ITYPE. + (c_expand_return): Delete unused var USE_TEMP. + + * typeck.c (compexcepttypes): Delete unused arg STRICT. + (comptypes): Fix calls. + * decl.c (duplicate_decls): Likewise. + * cp-tree.h (compexcepttypes): Delete extra arg. + + * decl2.c (check_classfn): Delete unused second arg CNAME. + * decl.c (start_decl, grokfndecl): Fix calls. + * init.c (do_friend): Likewise. + * cp-tree.h (check_classfn): Update prototype. + + * cp-tree.h (signature_error, import_export_vtable, + append_signature_fields, id_in_current_class, mark_used, + copy_assignment_arg_p): Add decls. + * decl2.c (mark_used): Delete decl. + + * class.c (n_*): Wrap with #ifdef GATHER_STATISTICS. + + * class.c (get_vtable_entry): Diable 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. + (overrides): Delete unused vars RETTYPE and BASE_RETTYPE. + (modify_one_vtable): Delete unused var OLD_RTTI. + (finish_struct_anon): Delete unused vars OFFSET and X. + (finish_struct_bits): Delete unused var METHOD_VEC. + (get_basefndecls): Delete unused var PURPOSE. Delete unused + for-scope local variable METHODS. + + * call.c (user_harshness): Delete unused/unneeded arg PARM. + (ideal_candidate): Delete unused args BASETYPE and PARMS. + (build_method_call): Delete unused args passed into ideal_candidate. + (build_overload_call_real): Likewise. Delete unused var OVERLOAD_NAME. + * cp-tree.h (synthesize_method): Add decl. + + * decl.c (note_level_for_for): Give void return type. + (pushdecl_nonclass_level): Likewise. + (finish_function): Delete unused vars VFIELDS and ALLOCATED_THIS. + (poplevel): Delete unused var IMPLICIT_TRY_BLOCK. + (suspend_binding_level): Delete unused var LEVEL. + (duplicate_decls): Delete unused var CTYPE. + (duplicate_decls): Delete unused var PREVIOUS_C_DECL. + (init_decl_processing): Delete unused vars FLOAT_ENDLINK and + PTR_ENDLINK. + (grokdeclarator): Delete unused var C. + (grokdeclarator): Delete unused var SIZE_VARIES. + (grokparms): Delete unused var SAW_VOID. + (start_function): Delete unused var OLDDECL. + (cplus_expand_expr_stmt): Delete unused var + REMOVE_IMPLICIT_IMMEDIATELY. + + * cp-tree.h (pushdecl_nonclass_level): Fix prototype. + + * Makefile.in (CONFLICTS): Update to 12 shift/reduce. + +Wed Feb 21 00:06:17 1996 Jason Merrill + + * tree.c (build_min): Set TREE_COMPLEXITY to lineno. + (build_min_nt): Likewise. + * pt.c (do_pushlevel): Emit line note. + (do_poplevel): Return what we get from poplevel. + (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. + (finish_file): Call it to do interface handling for statics. + * pt.c (tsubst_copy): Call mark_used on variables and functions + used here. - * cp-decl.c (pushtag): Set DECL_ASSEMBLER_NAME for nested classes, - too. + * decl2.c (finish_file): Don't emit statics we can't generate. + * pt.c (instantiate_decl): Don't set interface on instantiations + we can't generate. -Tue Jan 4 16:45:51 1994 Kung Hsu (kung@cirdan.cygnus.com) + * cp-tree.h (struct tinst_level): Change 'classname' to 'decl'. + * tree.c (print_lang_statistics): Print max template depth. + * pt.c (push_tinst_level): Dump entire instantiation context. + (instantiate_class_template): Use it and pop_tinst_level. + (instantiate_decl): Likewise. - * cp-parse.y: change to handle whether to globalize nested class. - * cp-decl.c(xref_tag, maybe_globalize_type): Ditto. + * call.c class.c cp-tree.h decl.c decl2.c error.c lex.c method.c + pt.c ptree.c tree.def: Remove all traces of UNINSTANTIATED_P_TYPE. -Mon Jan 3 22:22:32 1994 Gerald Baumgartner (gb@cygnus.com) +Tue Feb 20 18:21:51 1996 Jason Merrill - * Makefile.in cp-call.c cp-class.c cp-cvt.c cp-decl.c cp-decl2.c - cp-error.c cp-init.c cp-lex.c cp-lex.h cp-method.c cp-parse.y - cp-spew.c cp-tree.c cp-tree.h cp-type2.c cp-typeck.c cp-xref.c - gplus.gperf toplev.c: Incorporated C++ signature extension. - * cp-sig.c: New file, contains most of signature processing. - * cp-hash.h: Regenerated from gplus.gperf. + * call.c class.c cp-tree.h cvt.c decl.c decl2.c error.c expr.c + init.c lex.c method.c parse.y pt.c repo.c search.c spew.c tree.c + tree.def typeck.c typeck2.c xref.c: Massive, systemic changes for + the new template implementation. - * gcc.1 g++.1: Added explanation for the `-fhandle-signatures' - and `-fno-handle-signatures' command line flags. +Tue Feb 20 17:14:29 1996 Brendan Kehoe - * gcc.texi: Changed the last-modification date. - * invoke.texi: Added `-fhandle-signatures' in the list of - C++ language options. Added explanation for this option. + * decl2.c (check_cp_case_value): Use STRIP_TYPE_NOPS. -Tue Dec 28 21:10:03 1993 Mike Stump +Thu Feb 15 18:44:42 1996 Mike Stump - * cp-init.c (expand_vec_init): Remove comptypes test, as it is too - harsh here. + * decl.c (cp_finish_decl): Delay emitting the debug information for + a typedef that has been installed as the canonical typedef, if the + type has not yet been defined. -Tue Dec 28 13:42:22 1993 Mike Stump +Thu Feb 15 09:39:08 1996 Jason Merrill - * cp-pt.c (do_pending_expansions): Decide to expand a template - member function, based upon it's class type, not the class type of - the first place it was declared. + * decl2.c (grokfield): Still call pop_nested_class for access decls. -Tue Dec 28 05:42:31 1993 Mike Stump +Wed Feb 14 17:30:04 1996 Brendan Kehoe - * cp-class.c (is_normal): New routine, use to determine when the - given binfo is the normal one. (The one that should have the simple - vtable name.) - * cp-class.c (modify_other_vtable_entries): Use DECL_ASSEMBLER_NAME - to check if two fndecls are `the same'. Sometimes this routine can - modify the main vtable, and normal should be 1, in that case, so use - is_normal() to determine if this is the main vtable for the class. - Don't recurse down virtual bases, as they are shared, and we take - care of them elsewhere. - * cp-class.c (modify_vtable_entries): If we have already updated the - vtable with the new virtual, don't do it again. - * cp-class.c (finish_struct): Set CLASSTYPE_VFIELD_PARENT as - appropriate. Do virtual function overriding in virtual bases, after - normal overriding, so that the base function list in DECL_VINDEX is - not overridden, before we have a chance to run through the list. - Use DECL_ASSEMBLER_NAME to check if two fndecls are `the same'. - Make sure we pass the right address into modify_vtable_entries. - * cp-tree.h (CLASSTYPE_VFIELD_PARENT): New field to indicate which - binfo is the one that has the vtable that we based our vtable on. + * decl.c (lookup_label): Call label_rtx. -Fri Dec 24 09:40:52 1993 Michael Tiemann (tiemann@blues.cygnus.com) + * decl.c (make_binding_level): New function. + (pushlevel, pushlevel_class): Call it instead of explicit + duplicate calls to xmalloc. - * cp-typeck.c (c_expand_start_case): Use default_conversion to - convert expression from reference type if necessary. + * decl.c (init_decl_processing): Delete useless build_pointer_type + call. -Wed Dec 22 17:58:43 1993 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (float_ftype_float, ldouble_ftype_ldouble): Add definitions. + (sizet_ftype_string): Delete variable. + (init_decl_processing): Add built-in functions fabsf, fabsl, + sqrtf, sqrtl, sinf, sin, sinl, cosf, cos, cosl. New local + variable strlen_ftype, used for strlen. - * cp-typeck.c (build_unary_op): Make sure that it's a TREE_LIST before - trying to read its TREE_VALUE. +Wed Feb 14 16:21:25 1996 Jason Merrill - * cp-class.c (finish_struct_methods): Clear DECL_IN_AGGR_P here. - (finish_struct): Instead of here. + * decl.c (push_to_top_level): Start from current_binding_level + again for now; the stl hacks depend on g++ being broken in this + way, and it'll be fixed in the template rewrite. -Tue Dec 21 14:34:25 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * tree.def: Add USING_DECL. + * decl2.c (do_class_using_decl): Implement. + (grokfield): Pass access decls off to do_class_using_decl instead of + grokdeclarator. + * error.c (dump_decl): Handle USING_DECLs. + * decl.c (grokdeclarator): Remove code for handling access decls. + * class.c (finish_struct_1): Adjust accordingly, treat using-decls + as access decls for now. + (finish_struct): Don't check USING_DECLs for other uses of the name. - * cp-tree.c (list_hash_lookup_or_cons): Make sure the type doesn't - have TYPE_PTRMEMFUNC_P set before we try to build its - CLASSTYPE_ID_AS_LIST. - (get_decl_list): Likewise, when trying to read it. + * search.c (get_matching_virtual): Use cp_error_at. - * cp-tree.h (VTABLE_NAME): No def with NO_{DOLLAR,DOT} defined. - (VTABLE_NAME_P): Use it instead of VTABLE_NAME_FORMAT. +Wed Feb 14 10:36:58 1996 Brendan Kehoe -Mon Dec 20 13:35:03 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * typeck.c (comptypes): Default COMP_TYPE_ATTRIBUTES to 1, to + match c-typeck.c. + (self_promoting_args_p): Move the check that TYPE is non-nil + before trying to look at its main variant. + (unsigned_type, signed_type): Add checking of DI/SI/HI/QI nodes. - * cp-typeck.c (rationalize_conditional_expr): New function. - (unary_complex_lvalue): Use it. - (build_modify_expr): Use it, since trying to do an ADDR_EXPR of it - with build_unary_op won't cut it. Don't wrap the COND_EXPR with a - SAVE_EXPR either. + * cp-tree.h (DECL_WAITING_FRIENDS, SET_DECL_WAITING_FRIENDS): + Delete macros. + * init.c (xref_friend, embrace_waiting_friends): Delete functions. + (do_friend): Delete call to xref_friend. + * class.c (finish_struct_1): Delete call to embrace_waiting_friends. - * cp-decl2.c (explicit_warn_return_type): Deleted variable. - (lang_decode_option): Set warn_return_type, not explicit_*, for - -Wreturn-type and -Wall. This is what rest_of_compilation uses to - decide if it should go into jump_optimize or not. - * cp-tree.h (explicit_warn_return_type): Deleted. - * cp-decl.c (grokdeclarator): Use warn_return_type, not explicit_*. - (finish_function): Also complain about no return in a non-void fn if - we're being pedantic (don't rely on use of -Wreturn-type). + * typeck.c (convert_sequence): #if 0 unused function. -Fri Dec 17 15:45:46 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * cp-tree.h (DECL_IN_MEMORY_P): New macro w/ the check that used to + be in decl_in_memory_p. + (decl_in_memory_p): Delete decl. + * expr.c (decl_in_memory_p): Delete fn. + * typeck.c (mark_addressable): Use DECL_IN_MEMORY_P. - * cp-decl.c (grokdeclarator): Forbid declaration of a function as - static if it's being done inside another function. + * decl.c (cp_finish_decl): Use DECL_IN_MEMORY_P. - * cp-search.c (compute_visibility): Check for friendship both ways. +Tue Feb 13 12:51:21 1996 Jason Merrill -Fri Dec 17 14:28:25 1993 Jason Merrill (jason@deneb.cygnus.com) + * class.c (finish_struct_1): Check for a pure-specifier on a + non-virtual function here. - * cp-cvt.c (build_default_binary_type_conversion): Make error - messages more helpful. + * decl2.c (grok_function_init): Don't check whether the function + is virtual here. + (grokfield): Don't call check_for_override here. - * cp-error.c (op_as_string): New function, returns "operator ==" - given EQ_EXPR or suchlike. + * decl.c (push_to_top_level): Start from inner_binding_level, + check class_shadowed in class levels. -Fri Dec 17 13:28:11 1993 Brendan Kehoe (brendan@lisa.cygnus.com) +Mon Feb 12 17:46:59 1996 Mike Stump - * cp-call.c (print_n_candidates): New function. - (build_overload_call_real): Use it when we complain about a call - being ambiguous. + * decl.c (resume_level): Ignore things that don't have names, instead + of core dumping. -Fri Dec 17 12:41:17 1993 Jason Merrill (jason@deneb.cygnus.com) +Mon Feb 12 15:47:44 1996 Brendan Kehoe - * cp-call.c (build_method_call): Fix checking for static call - context. + * decl2.c (grokfield): Set DECL_VINDEX properly for FUNCTION_DECLs. - * cp-method.c (build_opfncall): Call build_indirect_ref on argument - to operator new. +Sat Feb 10 17:59:45 1996 Jason Merrill - * cp-init.c (build_new): Don't mess with rval when building - indirect ref. + * class.c (finish_struct_1): Set DECL_VINDEX properly on a + synthesized dtor. -Thu Dec 16 16:48:05 1993 Kung Hsu (kung@cirdan.cygnus.com) + * parse.y (complete_type_name): Bind global_scope earlier. + (complex_type_name): Likewise. + (qualified_type_name): Remove. - * cp-lex.c (default_assign_ref_body): add check when TYPE_NESTED_ - NAME(type) may not be exist. It's not a problem for old compiler. +Thu Feb 8 15:15:14 1996 Jason Merrill -Thu Dec 16 14:46:06 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (grokfndecl): Move code that looks for virtuals in base + classes... + * class.c (check_for_override): ... to a new function. + (finish_struct_1): Call it. - * cp-tree.h (CLASSTYPE_ALTERS_VISIBILITIES_P): Delete macro, it's - never used for anything. - (struct lang_type, member type_flags): Delete field - `alters_visibility', and up `dummy' by 1. - * cp-class.c (finish_base_struct): Delete code that copies the - setting of CLASSTYPE_ALTERS_VISIBILITIES_P. - (finish_struct): Delete code that sets it. + * cp-tree.h: Declare warn_sign_compare. -Thu Dec 16 14:44:39 1993 Jason Merrill (jason@deneb.cygnus.com) + * typeck.c (build_binary_op_nodefault): Check warn_sign_compare + rather than extra_warnings to decide whether to warn about + comparison of signed and unsigned. - * cp-decl.c, cp-init.c, cp-typeck.c: Fix arguments to - build_method_call that I messed up before. + * decl2.c (lang_decode_option): Handle warn_sign_compare. -Wall + implies -Wsign-compare. -Wall doesn't imply -W. - * cp-search.c (get_base_distance): If protect > 1, allow immediate - private base. +Wed Feb 7 15:27:57 1996 Mike Stump - * cp-class.c (finish_base_struct): Set cant_synth_* correctly. - (finish_struct): Ditto. Well, nigh-correctly; it won't deal - properly with the case where a class contains an object of an - ambiguous base class which has a protected op=. Should be fixed - when the access control code gets overhauled. - (finish_struct_methods): Set TYPE_HAS_NONPUBLIC_* correctly. + * typeck.c (build_component_ref): Fix to handle anon unions in base + classes as well. -Thu Dec 16 12:17:06 1993 Brendan Kehoe (brendan@lisa.cygnus.com) +Wed Feb 7 14:29:12 1996 Brendan Kehoe - * cp-lex.c (real_yylex): Turn the code back on that deals with - __FUNCTION__ and __PRETTY_FUNCTION__. Don't use lookup_name, to - avoid the ambiguity problems that led to it being turned off in the - first place. + * class.c (resolves_to_fixed_type_p): Delete code dealing with + a WITH_CLEANUP_EXPR, since we don't generate them any more. + * cvt.c (build_up_reference): Likewise. + * decl.c (grok_reference_init): Likewise. + (cp_finish_decl): Likewise. + * error.c (dump_expr): Likewise. + * tree.c (real_lvalue_p): Likewise. + (lvalue_p): Likewise. + (build_cplus_new): Likewise. + (unsave_expr_now): Likewise. + * typeck.c (unary_complex_lvalue, build_modify_expr, + c_expand_return): Likewise. - * cp-method.c (hack_identifier): Also check for a TYPE_PTRMEMFUNC_P - to see if something is a method. +Tue Feb 6 13:39:22 1996 Brendan Kehoe -Wed Dec 15 18:35:58 1993 Mike Stump + Make the C++ front-end pay attention to attributes for structures. + * class.c (finish_struct): New argument ATTRIBUTES, passed down into + finish_struct_1. + (finish_struct_1): New argument ATTRIBUTES; call cplus_decl_attributes. + Take out old round_up_size use and setting the DECL_ALIGN possibly + using it. Take out setting of TYPE_ALIGN to round_up_size, which + can override what the attribute set. + * cp-tree.h (finish_struct): Update prototype. + * parse.y (template_instantiate_once): Pass a NULL_TREE for the + attributes to finish_struct. + (structsp): For a CLASS decl, add maybe_attribute to rule and pass that + value down into finish_struct. + * Makefile.in (CONFLICTS): Switch to 7 shift/reduce conflicts. - * cp-typeck.c (build_modify_expr): Avoid error messages on small - enum bit fields. - * cp-typeck.c (convert_for_assignment): Add missing argument to - cp_warning and cp_pedwarn calls. +Tue Feb 6 13:12:15 1996 Per Bothner -Wed Dec 15 18:25:32 1993 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (poplevel): Re-word dead for local handling. + (pushdecl): Remove useless DECL_DEAD_FOR_LOCAL test. + (cp_finish_decl): If is_for_scope, check for duplicates so + we can disable is_for_scope. Otherwise, preserve_temp_slots. - * cp-parse.y (member_init): ANSI C++ doesn't forbid old-style base - initializers; it's just anachronistic. + * lex.c (do_identifier): Use global binding in preference of + dead for local variable. - * cp-decl.c (finish_decl): Don't require external-linkage arrays - to have a complete type at declaration time when pedantic. +Mon Feb 5 17:46:46 1996 Mike Stump -Tue Dec 14 11:37:23 1993 Jason Merrill (jason@deneb.cygnus.com) + * init.c (initializing_context): Handle anon union changes, the + context where fields of anon unions can be initialized now has to be + found by walking up the TYPE_CONTEXT chain. - * cp-decl.c (pushdecl): Don't set DECL_CONTEXT if it's already set. +Fri Feb 2 14:54:04 1996 Doug Evans - * cp-call.c (build_method_call): Don't dereference pointer given - as instance. + * decl.c (start_decl): #ifdef out code to set DECL_COMMON + if ASM_OUTPUT{,_ALIGNED}_BSS is defined. + (obscure_complex_init): If bss is supported, always set + DECL_INITIAL to error_mark_node. - * cp-decl.c (finish_function): Don't pass pointer to - build_method_call. - (finish_function): Ditto. +Thu Feb 1 16:19:56 1996 Brendan Kehoe - * cp-typeck.c (build_x_function_call): Ditto. + * init.c (is_friend): Make sure there's a context before we see if + it's an aggr type. - * cp-method.c (build_component_type_expr): Ditto. +Thu Feb 1 15:44:53 1996 Mike Stump - * cp-init.c (build_member_call): Ditto. - (build_new): Ditto. + * init.c (is_friend): Classes are not friendly with nested classes. -Mon Dec 13 18:04:33 1993 Kung Hsu (kung@cirdan.cygnus.com) +Thu Feb 1 15:27:37 1996 Doug Evans - * cp-decl.c (xref_tag): fix regression created by changes made - in Dec. 7 1993. - * cp-decl.c (xref_defn_tag): fix parallel nested class problem. + * lex.c (check_newline): Pass last character read to HANDLE_PRAGMA, + and record its result. -Fri Dec 10 12:40:25 1993 Brendan Kehoe (brendan@lisa.cygnus.com) +Thu Feb 1 09:27:01 1996 Mike Stump - * cp-call.c (compute_conversion_costs_ansi) [DEBUG_MATCHING]: Print - out the final evaluation of the function, so we can see if ELLIPSIS, - USER, and EVIL were set at the end. + * class.c (finish_struct_anon): Switch around code to not move anon + union elements around, nor mess up their contexts, nor offsets, + instead we now build up the right number of COMPONENT_REFs for all + the anon unions that may be present at build_component_ref time. + * typeck.c (lookup_anon_field): New routine to handle field lookup + on fields without names. We find them, based upon their unique type + instead. + * typeck.c (build_component_ref): Allow FIELD_DECL components. + Handle finding components in anonymous unions, and ensure that a + COMPONENT_REF is built for each level as necessary. - * cp-call.c (convert_harshness_ansi): When the parm isn't an lvalue, - only go for setting TRIVIAL_CODE if we are dealing with types that - are compatible. +Tue Jan 30 18:18:23 1996 Mike Stump -Thu Dec 9 18:27:22 1993 Mike Stump + * cvt.c (build_up_reference): Make the INDIRECT_BIND case come after + code that ensures that copy ctors are used if appropriate. - * cp-decl.c (flag_huge_objects): New flag to allow large objects. - * toplev.c (lang_options): Ditto. - * cp-decl2.c (flag_huge_objects, lang_f_options): Ditto. - * cp-decl.c (delta_type_node): New type for delta entries. - * cp-tree.h (delta_type_node): Ditto. - * cp-decl.c (init_decl_processing): Setup delta_type_node. - * cp-decl.c (init_decl_processing, build_ptrmemfunc_type): Use - delta_type_node instead of short_integer_type_node. - * cp-class.c (build_vtable_entry): Ditto. +Tue Jan 30 17:35:14 1996 Brendan Kehoe -Thu Dec 9 16:19:05 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * init.c (build_vec_delete): Only give an error if base isn't an + error_mark_node. - * cp-tree.h (OPERATOR_TYPENAME_P): Define outside of - NO_{DOLLAR,DOT} macro checks, so it always gets defined. - (VTABLE_NAME_P): Define for NO_DOT && NO_DOLLAR_IN_LABEL. +Mon Jan 29 17:09:06 1996 Mike Stump + + * spew.c (do_aggr): `new struct S;' isn't a forward declaration. + (yylex): If we see `new', keep slurping. + +Thu Jan 25 18:31:36 1996 Mike Stump + + * class.c (finish_struct_1): Move code for handling anon unions... + (finish_struct_anon): to here. Fixup so that we do the offset + calculations right, and so that the fields are physically moved to + the containers's chain. + +Thu Jan 25 18:27:37 1996 Brendan Kehoe + + * decl.c (grokdeclarator): Avoid trying to get an operand off an + identifier node. + +Wed Jan 24 11:25:30 1996 Jim Wilson + + * typeck.c (pointer_int_sum): Use TYPE_PRECISION (sizetype) not + POINTER_SIZE to agree with expr.c. + +Thu Jan 25 13:01:23 1996 Mike Stump + + * search.c (lookup_field): Don't report ambiguities if protect is 0, + instead return NULL_TREE. + +Wed Jan 24 13:01:26 1996 Mike Stump + + * class.c (finish_struct_1): Call warn_hidden if we want warnings + about overloaded virtual functions. + (warn_hidden): New routine to warn of virtual functions that are + hidden by other virtual functions, that are not overridden. + (get_basefndecls): New routine, used by warn_hidden. + (mark_overriders): New routine, used by warn_hidden. + * search.c (get_matching_virtual): Remove old warning that just + isn't very useful. + +Tue Jan 23 12:26:10 1996 Brendan Kehoe + + * decl.c (output_builtin_tdesc_entries): #if 0 the function definition. + + * typeck.c (null_ptr_cst_p): Delete unused fn. + (build_function_call_maybe): Delete unused fn. + + * expr.c (extract_init): #if 0 the code after unconditional return 0 + for now. + + Delete old cadillac code. + * edsel.c: Remove file. + * Make-lang.in (CXX_SRCS): Take edsel.c off the list. + * Makefile.in (CXX_OBJS): Delete edsel.o. + (edsel.o): Delete rule. + * cp-tree.h (flag_cadillac): Delete var decl. + * lang-options.h: Delete "-fcadillac" and "-fno-cadillac". + * decl2.c (flag_cadillac): Delete var definition. + (lang_decode_option): Delete handling of -fcadillac and -fno-cadillac. + (grokfield): Delete code depending on flag_cadillac. + (finish_anon_union): Likewise. + * class.c (finish_struct_1): Likewise. + (pushclass): Likewise. + (popclass): Likewise. + (push_lang_context): Likewise. + (pop_lang_context): Likewise. + * decl.c (init_decl_processing): Likewise. + (start_decl): Likewise. + (cp_finish_decl): Likewise. + (xref_tag): Likewise. + (finish_enum): Likewise. + (start_function): Likewise. + (finish_function): Likewise. + (finish_stmt): Likewise. + * lex.c (lang_init): Likewise. + (check_newline): Likewise. -Wed Dec 8 17:38:06 1993 Mike Stump + * lex.c (do_pending_inlines): Delete synthesized method kludge. - * cp-decl.c (finish_decl): Make sure things that can go into - "common", do go into common, if -fcommon is given. + Delete defunct, ancient garbage collection implementation. + * rtti.c: New file with the RTTI stuff from gc.c. + * gc.c: Removed file (moved the remaining stuff into rtti.c). + * Makefile.in (CXX_OBJS): Replace gc.o with rtti.o. + (rtti.o): New rule, replacing gc.o. + * Make-lang.in (CXX_SRCS): Replace gc.c with rtti.c. + * cp-tree.h: Delete gc-related fn decls. + (DECL_GC_OFFSET): Delete macro. + (flag_gc): Delete extern decl. + * decl.c (current_function_obstack_index): Delete var decl. + (current_function_obstack_usage): Delete var decl. + (start_function): Delete clearing of current_function_obstack_index + and current_function_obstack_usage. + (init_decl_processing): Delete code relying on -fgc. + Delete call to init_gc_processing. + (cp_finish_decl): Delete calls to build_static_gc_entry and + type_needs_gc_entry. Delete gc code setting DECL_GC_OFFSET. + (store_parm_decls): Delete -fgc calls to cp_expand_decl_cleanup + and to expand_expr of a __gc_main call. + (maybe_gc_cleanup): Delete var decl. + (finish_function): Delete call to expand_gc_prologue_and_epilogue. + * decl2.c (flag_gc): Delete var decl. + (lang_f_options): Delete offering of -fgc. + (lang_decode_option): Delete -fgc and -fno-gc handling. + (get_temp_regvar): Delete gc code. + * init.c (build_new): Delete gc code. + * lex.c (init_lex): Delete checking of flag_gc. + + * typeck.c (convert_arguments): Delete gc code. + (build_component_addr): Delete -fgc warning. + (build_modify_expr): Delete gc code. + + * decl2.c (build_push_scope): Delete fn. + * cp-tree.h (build_push_scope): Delete decl. + + * search.c (clear_search_slots): Delete fn. + * cp-tree.h (clear_search_slots): Delete decl. + + * search.c (tree_needs_constructor_p): Delete fn. + * cp-tree.h (tree_needs_constructor_p): Delete decl. + + * tree.c (id_cmp): Delete fn. + + * tree.c (set_fnaddr_from_vtable_entry): Delete fn. + * cp-tree.h (set_fnaddr_from_vtable_entry): Delete decl. + + * tree.c (decl_value_member): Delete fn. + * cp-tree.h (decl_value_member): Delete decl. + + * tree.c (list_hash_lookup_or_cons): Delete fn. + * cp-tree.h (list_hash_lookup_or_cons): Delete decl. + + * method.c (cplus_exception_name): Delete fn. + (EXCEPTION_NAME_{PREFIX, LENGTH}): Delete macros. + + * spew.c (shift_tokens): Delete fn. + +Mon Jan 22 17:49:33 1996 Jason Merrill + + * except.c (init_exception_processing): Pass 1 to needs_pop in calls + to cp_finish_decl. + * parse.y: Likewise. + +Mon Jan 22 17:34:29 1996 Brendan Kehoe + + * tree.c (build_cplus_staticfn_type): Delete function definition; + never used. + * cp-tree.h (build_cplus_staticfn_type): Delete decl. + + * tree.c (virtual_member): Delete function definition; never used. + * cp-tree.h (virtual_member): Delete decl. + +Fri Jan 19 18:03:14 1996 Mike Stump + + * typeck.c (build_component_ref): Handle getting vbase pointers + out of complex multiple inheritance better. + +Fri Jan 19 16:27:40 1996 Mike Stump + + * typeck.c (build_object_ref): Make sure we use the real type, not + any reference type. + +Fri Jan 19 16:01:47 1996 Mike Stump + + * tree.c (build_exception_variant): Don't create new types if we + don't have to, also build new types on the right obstack. + +Fri Jan 19 14:09:44 1996 Jason Merrill -Wed Dec 8 13:01:54 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (store_bindings): Split out from push_to_top_level. + (push_to_top_level): Call it for b->type_shadowed on class binding + levels. - * cp-call.c (print_harshness) [DEBUG_MATCHING]: New function. - (compute_conversion_costs_ansi) [DEBUG_MATCHING]: Print out - argument matching diagnostics to make instantly clear what the - compiler is doing. +Fri Jan 19 13:53:14 1996 Mike Stump - * cp-call.c (convert_harshness_ansi): If the parm isn't an lvalue, - then check to see if the penalty was increased due to - signed/unsigned mismatch, and use a TRIVIAL_CODE if it wasn't. + * search.c (expand_upcast_fixups): Fix so that offsets stored in + vbase_offsets are always right. Fixes a problem where virtual base + upcasting and downcasting could be wrong during conversions on this + during virtual function dispatch at ctor/dtor time when dynamic + vtable fixups for deltas are needed. This only sounds easier than + it is. :-) + (fixup_virtual_upcast_offsets): Change to reflect new calling + convention for expand_upcast_fixups. -Tue Dec 7 18:29:14 1993 Kung Hsu (kung@cirdan.cygnus.com) +Fri Jan 19 12:23:08 1996 Brendan Kehoe - * cp-decl.c (xref_tag, pushtag): Fix nested class search/resolution - problem. + * decl2.c (grokbitfield): Strip the NOPs from WIDTH before we + check that it's usable as the bitfield width. -Tue Dec 7 16:09:34 1993 Jason Merrill (jason@deneb.cygnus.com) +Wed Jan 17 21:22:40 1996 Brendan Kehoe - * cp-class.c (finish_struct): Before synthesizing methods, if no - methods have yet been declared then set nonprivate_method. Don't - set non_private method after synthesizing a method. + * decl2.c (grokfield): Call cplus_decl_attributes with the attrlist. + Pass a null tree to grokdeclarator for its ATTRLIST arg, since it's + only ever used for functions in it. - * cp-lex.c (extract_interface_info): If flag_alt_external_templates - is set, tie emitted code to the location of template instantiation, - rather than definition. +Wed Jan 17 12:10:38 1996 Jason Merrill - * cp-tree.h: Declare flag_alt_external_templates. + * parse.y (qualified_type_name): Use the TYPE_DECL, not the type. + (nested_type): Likewise. + (nested_name_specifier): Use lastiddecl. - * cp-decl2.c (lang_decode_option): Support -falt-external-templates. + * decl.c (grokdeclarator): Adjust accordingly. + * init.c (expand_member_init): Likewise. + * parse.y (base_class): Likewise. + * typeck2.c (build_functional_cast): Likewise. - * toplev.c (lang_options): Ditto. + * typeck2.c (build_functional_cast): Fill in name after we've + checked for non-aggr type. - Mon Oct 4 12:50:02 1993 Chip Salzenberg (chip@fin.uucp) +Wed Jan 17 10:18:01 1996 Mike Stump - [changes propagated from 930810 snapshot] - * cp-decl.c (init_decl_processing): Make long long available for use - as SIZE_TYPE and PTRDIFF_TYPE. - (finish_decl): Allow file-scope static incomplete array. - (grokdeclarator): Don't pass on const and volatile fron function - value type to function type. - Warn here for volatile fn returning non-void type. - * cp-parse.y (attrib): Accept attributes `volatile' with alias - `noreturn', and `const'. - * cp-typeck.c (default_conversion): Don't lose const and volatile. - (build_binary_op_nodefault): Generate pedantic warning for comparison - of complete pointer type with incomplete pointer type. - (build_c_cast): Be careful that null pointer constant be INTEGER_CST. + * decl2.c (warn_pointer_arith): Default to on. -Tue Dec 7 10:46:48 1993 Jason Merrill (jason@deneb.cygnus.com) +Tue Jan 16 12:45:38 1996 Jason Merrill - * cp-init.c (expand_vec_init): When creating a temporary for copying - arrays, use the type of the source, not the target. + * lex.c (is_rid): New function. + * decl.c (grokdeclarator): Diagnose reserved words used as + declarator-ids. - * cp-cvt.c (convert): Pass an argument for errtype to - convert_to_reference. +Tue Jan 16 11:39:40 1996 Jason Merrill - * cp-error.c (dump_expr, COMPONENT_REF & CALL_EXPR): Deal with - methods, -> and `this'. + * tree.c (get_decl_list): Don't lose cv-quals. -Mon Dec 6 17:12:33 1993 Jason Merrill (jason@deneb.cygnus.com) + * decl.c (grokdeclarator): Fix SCOPE_REF handling and diagnose + typespecs used as declarator-ids. - * cp-error.c (parm_as_string): New function; returns `this' or arg - number. Corresponds to %P. - (dump_expr): Deal with method calls. +Tue Jan 16 11:09:42 1996 Mike Stump - * cp-cvt.c (convert_to_reference): Stop using warn_for_assignment. - * cp-typeck.c (convert_for_assignment): Ditto. - (warn_for_assignment): Lose. + * decl.c (poplevel): When poping a level, don't give a warning for + any subblocks that already exist. -Mon Dec 6 11:33:35 1993 Brendan Kehoe (brendan@lisa.cygnus.com) +Tue Jan 16 00:25:33 1996 Jason Merrill - * cp-call.c (ideal_candidate_ansi): Delete code that was never - doing anything useful. Instead, sort once, and DO NOT wipe - out any codes with EVIL_CODE, since that's what we use as a - marker for the end of the list of candidates. + * typeck.c (build_object_ref): Finish what I started. - * cp-cvt.c (convert_to_aggr): Make sure to always set H_LEN. + * parse.y (qualified_type_name): Don't check TYPE_BUILT_IN. -Mon Dec 6 12:49:17 1993 Jason Merrill (jason@deneb.cygnus.com) + * decl2.c (constructor_name_full): Handle TEMPLATE_TYPE_PARMs. - * cp-init.c (get_aggr_from_typedef): New function, like - is_aggr_typedef but returns the _TYPE. + * decl.c (grokdeclarator): Also accept TEMPLATE_TYPE_PARM as a + scope. - * cp-call.c, cp-init.c, cp-method.c: Eradicate err_name. +Mon Jan 15 16:19:32 1996 Jason Merrill -Sun Dec 5 18:12:48 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * decl.c (xref_tag): Handle passing a type in directly. - * cp-lex.c (readescape): Pedwarn when a hex escape is out of range. + * parse.y (qualified_type_name): Pull out the type. + (nested_type): Likewise. + Take types directly instead of as identifiers. + * call.c (build_scoped_method_call): Take types directly instead of + as identifiers. + * decl.c (xref_basetypes): Likewise. + * init.c (expand_member_init): Likewise. + (build_member_call): Likewise. + (build_offset_ref): Likewise. + * typeck2.c (build_scoped_ref): Likewise, remove bogus code. + * method.c (do_build_assign_ref): Likewise. + * decl.c (grokdeclarator): Handle a type appearing as the + declarator-id for constructors. + * method.c (do_build_copy_constructor): current_base_init_list now + uses the types directly, not their names. + * init.c (sort_base_init): Likewise. + (expand_member_init): Likewise. + * init.c (is_aggr_type): New function, like is_aggr_typedef. -Thu Nov 25 23:50:19 1993 Chip Salzenberg (chip@fin.uucp) +Mon Jan 15 08:45:01 1996 Jeffrey A Law - Delay language context change until beginning of next decl. + * tree.c (layout_basetypes): Call build_lang_field_decl instead + of build_lang_decl if first arg is a FIELD_DECL. - * cp-lex.h (c_header_level): Removed. - (pending_lang_change): Declared. - * cp-lex.c (c_header_level): Renamed from in_c_header, made static. - (pending_lang_change): Defined. - (check_newline): Rework code that recognizes line number and - filename changes. Instead of pushing and popping lang context, - increment and decrement pending_lang_change. - (do_pending_lang_change): Push and pop lang context according - to value of pending_lang_change. - * cp-parse.y (extdefs): Use lang_extdef instead of extdef. - (extdef): Same as extdef, but call do_pending_lang_change() first. +Thu Jan 11 14:55:07 1996 Brendan Kehoe -Mon Nov 15 15:39:15 1993 Chip Salzenberg (chip@fin.uucp) + * decl.c (cp_finish_decl): Only clear TREE_USED if DECL_NAME is + non-empty. + * except.c (expand_start_catch_block): Set TREE_USED to avoid + warnings about the catch handler. - * cp-typeck.c (build_binary_op_nodefault): Warn for ordered - compare of ptr with 0 only if pedantic in both cases. +Mon Jan 8 17:35:12 1996 Jason Merrill -Thu Nov 25 13:31:37 1993 Chip Salzenberg (chip@fin.uucp) + * typeck.c (build_modify_expr): Use a COMPOUND_EXPR instead of + expand_target_expr. - Reinstate the below patch, which got lost in the Cygnus merge: - Tue Nov 23 13:59:24 1993 Hallvard B Furuseth (hbf@durin.uio.no) - * cp-parse.y (maybe_type_qual): Don't fail to set $$. +Thu Jan 4 12:30:32 1996 Brendan Kehoe -Wed Nov 17 19:03:30 1993 Chip Salzenberg (chip@fin.uucp) + Fix access control to use trees rather than integers. + * class.c (access_{default, public, protected, private, + default_virtual, public_virtual, private_virtual}_node): Add + definitions. + (init_class_processing): Do creation of those nodes. + * cp-tree.h (access_type): Delete enum decl. + (access_{default, public, protected, private, default_virtual, + public_virtual, private_virtual}_node): Add decls. + (compute_access): Change return type. + * search.c (compute_access): Have tree return type, instead of enum. + (lookup_field): Declare THIS_V and NEW_V to be tree nodes. + * lex.c (real_yylex): Use yylval.ttype for giving the value of the + access_* node for each of RID_{PUBLIC, PRIVATE, PROTECTED}. + * parse.y (VISSPEC): Make ttype rather than itype. + (base_class_access_list): Likewise. + * *.[cy]: Change all refs of `access_public' to `access_public_node', + etc. + * call.c (build_method_call): Make ACCESS be a tree. + * class.c (alter_access, finish_struct_1, filter_struct): Likewise. + * cvt.c (convert_to_aggr): Likewise. + * init.c (build_offset_ref, resolve_offset_ref, build_delete): + Likewise. + * method.c (hack_identifier): Likewise. + * typeck.c (build_component_ref_1, build_component_ref): ): Likewise. - * cp-parse.y (attrib): Allow "ident(ident)" like the C front end. +Thu Jan 4 11:02:20 1996 Mike Stump -Fri Oct 22 20:43:37 1993 Paul Eggert (eggert@twinsun.com) + * typeck.c (pointer_int_sum, pointer_diff): Make code agree with C + frontend, and make it more consistent with respect to + warn_pointer_arith. - * cp-lex.c (real_yylex): Diagnose floating point constants - that are too large. +Tue Jan 2 00:13:38 1996 Rusty Russell -Wed Nov 17 19:10:37 1993 Chip Salzenberg (chip@fin.uucp) + * decl.c (pushdecl): Check for duplicate parameter names. - * cp-type2.c (build_functional_cast): ARM page 16: When a class - and an object, function or enumerator are declared in the same - scope with the same name, the class name is hidden. +Wed Jan 3 09:25:48 1996 Mike Stump -Wed Nov 17 19:07:18 1993 Chip Salzenberg (chip@fin.uucp) + * decl.c (expand_static_init): Call assemble_external for atexit. - * cp-call.c (convert_harshness_ansi): Distinguish float, double, - and long double from each other when overloading. - (compute_conversion_costs_{ansi,old}, build_method_call, - build_overlay_call_real, convert_to_aggr): Always set and - always use H_LEN member of candidate structure. +Wed Jan 3 07:55:19 1996 Mike Stump -Mon Oct 11 23:10:53 1993 Chip Salzenberg (chip@fin.uucp) + * except.c (do_unwind): Remove some generated dead code. + (eh_outer_context): New routine, factor out some common code from + expand_builtin_throw and end_eh_unwinder. Add code to do return + address masking for the PA. + (expand_builtin_throw): Use eh_outer_context instead of open coding + it here. + (end_eh_unwinder): Likewise. + +Tue Jan 2 17:00:56 1996 Mike Stump + + * except.c (expand_throw): Call assemble_external for __empty, if we + use it. - * cp-decl.c (duplicate_decls): Note redeclarations of library - functions, and generate distinct warnings for them. +Thu Dec 28 11:13:15 1995 Mike Stump -Mon Oct 4 12:26:49 1993 Chip Salzenberg (chip@fin.uucp) + * except.c (expand_builtin_throw): Use RETURN_ADDR_OFFSET instead of + NORMAL_RETURN_ADDR_OFFSET. + (end_eh_unwinder): Likewise. - Support format warnings in G++. +Wed Dec 27 22:18:16 1995 Mike Stump - * cp-tree.h: Protect against multiple inclusion. - Declare all public functions in c-common.c (copy from c-tree.h). - (STDIO_PROTO): Define. - (warn_format): Declare. - (record_format_info): Remove declaration. - * cp-decl.c (init_decl_processing): Call init_function_format_info. - * cp-decl2.c (lang_decode_option): Make "-Wall" include warn_format. - * cp-typeck.c (build_function_call_real): Call check_function_format. - (record_format_info): Remove -- obsolete stub. + * gc.c (build_dynamic_cast): Make sure we don't cast away const + when dealing with references, and make sure we handle dynamic + casting to a cv qualified reference. -Sat Jul 24 12:04:29 1993 Chip Salzenberg (chip@fin.uucp) +Thu Dec 21 23:50:35 1995 Mike Stump - * cp-decl.c (duplicate_decls): Don't warn for non-extern var decl - following an extern one (for -Wredundant-decls). - * cp-parse.y (primary): In statement expression case, if compstmt - returns something other than a BLOCK, return it unchanged. + * except.c (struct eh_context): New structure top hold eh context + information. + (push_eh_context): New routine. + (pop_eh_context): Likewise. + * decl.c (push_cp_function_context): Use them. + (pop_cp_function_context): Likewise. -Thu Dec 2 20:44:58 1993 Chip Salzenberg (chip@fin.uucp) +Wed Dec 20 12:42:51 1995 Jason Merrill - * cp-decl.c (warn_extern_redeclared_static): New function made - from code extracted from pushdecl. - (duplicate_decls, pushdecl): Call new function. - (lookup_name_current_level): Allow for IDENTIFIER_GLOBAL_VALUE - to be a TREE_LIST when function is declared in 'extern "C" {}'. + * decl2.c (finish_file): Also prune uninteresting functions in the + inline emission loop. -Fri Dec 3 16:01:10 1993 Jason Merrill (jason@deneb.cygnus.com) +Wed Dec 20 02:32:07 1995 Jeffrey A Law - * cp-class.c (duplicate_tag_error): Use cp_error. - (finish_base_struct): Check for ambiguity with direct base, and don't - generate op= or copy ctor if it exists. + * sig.c (build_signature_table_constructor): Mark functions + in the signature as referenced. -Fri Dec 3 15:32:34 1993 Kung Hsu (kung@cirdan.cygnus.com) +Tue Dec 19 22:36:56 1995 Jason Merrill - * cp-init.c (expand_member_init): when initializer name is null, - don't try to build it now because emit_base_init will handle it. + * decl2.c (finish_file): Do all the vtable/synthesis stuff before + the inline emission stuff. -Fri Dec 3 12:28:59 1993 Jason Merrill (jason@deneb.cygnus.com) +Mon Dec 18 15:51:33 1995 Jason Merrill - * cp-lex.c (init_lex): Initialize input_filename to "" for - code such as ExceptionHandler::operator=. + * cp-tree.h, decl2.c (flag_weak): New flag to control the use of + 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. + * decl2.c, pt.c: s/SUPPORTS_WEAK/flag_weak/. -Fri Dec 3 10:32:08 1993 Jason Merrill (jason@deneb.cygnus.com) +Sun Dec 17 21:13:23 1995 Rusty Russell - * cp-decl.c (grokdeclarator): Don't try to print out dname when - complaining about arrays of references if decl_context==TYPENAME, - since it will be null. + * init.c (expand_member_init): warning for base init after members. - * cp-decl2.c: Default to flag_ansi_overloading. +Fri Dec 15 15:32:18 1995 Jason Merrill -Thu Dec 2 18:05:56 1993 Kung Hsu (kung@cirdan.cygnus.com) + * cvt.c (build_expr_type_conversion): Don't convert to a reference + type. - * cp-call.c (build_method_call): use binfo from instance if it's - different from binfo (basetype_path) passed from above. +Thu Dec 14 16:05:58 1995 Mike Stump + + * method.c (report_type_mismatch): Improve wording for volatile + mismatches. + +Thu Dec 14 14:16:26 1995 Mike Stump + + * init.c (expand_aggr_init_1): Use expand_aggr_init_1 instead of + expand_assignment, as the later doesn't handle things that have + 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 + + * g++.c (my_strerror): Return "cannot access" if errno is 0. + (pfatal_with_name, perror_exec): Don't assume that + the returned value from my_strerror contains no '%'s. + (concat): Remove. + (sys_nerror): Declare only if HAVE_STRERROR is not defined. + +Wed Dec 13 16:22:38 1995 Jason Merrill + + Lose CLASSTYPE_METHODS/DECL_NEXT_METHOD chain; make + 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. + * tree.c (tree_copy_lang_decl_for_deferred_output): Likewise. + * cp-tree.h (CLASSTYPE_METHODS): Lose. + (CLASSTYPE_METHOD_VEC): Point to lang_spec->methods instead of + TYPE_METHODS. + (struct lang_decl): Lose next_method field. + (DECL_NEXT_METHOD): Lose. + * class.c (finish_struct_methods): Don't mess with TYPE_METHODS. + (finish_struct): Just use TYPE_METHODS; we don't need fn_fields + anymore. + (finish_struct_methods): Don't mess with the TREE_CHAINs in + fn_fields. -Thu Dec 2 12:48:36 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * search.c (add_conversions): Don't use TREE_CHAIN to traverse method + vector. -Wed Nov 17 19:14:29 1993 Chip Salzenberg (chip@fin.uucp) + * call.c (build_method_call): Synthesize here even when not inlining. + * typeck.c (build_function_call_real): Likewise. - cp-error.c (dump_expr): Use unsigned chars to output a - TREE_REAL_CST in hex. +Wed Dec 13 15:02:39 1995 Ian Lance Taylor -Thu Dec 2 11:05:48 1993 Jason Merrill (jason@deneb.cygnus.com) + * cp/lex.c (check_newline): If DBX_DEBUGGING_INFO and write_symbols + == DBX_DEBUG, call dbxout_start_new_source_file and + dbxout_resume_previous_source_file when appropriate. - * cp-class.c (finish_struct): Fix typo in setting - cant_synth_asn_ref. +Tue Dec 12 20:38:55 1995 Mike Stump - * cp-tree.h (TYPE_NESTED_NAME): New macro, does - DECL_NESTED_TYPENAME (TYPE_NAME (NODE)). + * except.c (start_anon_func): Push to the top level. + (end_anon_func): Pop from the top level. - * cp-lex.c (default_copy_constructor_body): Change - DECL_NAME (TYPE_NAME (btype)) to TYPE_NESTED_NAME (btype). - (default_assign_ref_body): Ditto. - (default_copy_constructor_body): Call operator= explicitly for - base classes that have no constructor. +Mon Dec 11 18:56:14 1995 Mike Stump -Thu Dec 2 10:47:15 1993 Michael Tiemann (tiemann@blues.cygnus.com) + * cp-tree.h (build_cleanup): New routine to build cleanups. + * decl.c (expand_static_init): Use build_cleanup to build a cleanup + call at ctor time and use atexit to run it later. + * 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 + + * except.c (expand_throw): Ensure that we have cleanups, if we try + and expand cleanups. + +Wed Dec 6 11:48:21 1995 Mike Stump + + * except.c (expand_throw): Add logic to manage dynamic cleanups for + the EH object. + (expand_end_catch_block): Use the magic of expand_goto, instead of + emit_jump so that we get the cleanup for any catch clause parameter + and the cleanup for the exception object. Update to reflect label + changes. + (push_eh_cleanup): New routine to register a cleanup for an + exception object. + (empty_fndecl): Used to default cleanup actions to + nothing. + (init_exception_processing): Setup empty_fndecl. Setup + saved_cleanup. + (expand_start_catch_block): Update to reflect label changes. Call + push_eh_object to register the cleanup for the EH object. + (start_anon_func): New routine to start building lambda expressions + from trees. + (end_anon_func): New routine to end them. + (struct labelNode): Change so that we can use tree labels, or rtx + labels. + (saved_cleanup): Object to check for dynamic cleanups for the + exception handling object. + (push_label_entry): Change so that we can use tree labels, or rtx + labels. + (pop_label_entry): Likewise. + (top_label_entry): Likewise. + (expand_start_all_catch): Use tree label instead of rtx label, so + that we can get the magic of expand_goto. + (expand_end_all_catch): Update to reflect label changes. + + * 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 + building_cleanup logic, as we now use UNSAVE_EXPRs. + * cp-tree.h (unsave_expr): Declare it. + * decl.c (building_cleanup): Remove. + (maybe_build_cleanup): Remove building_cleanup logic, and use + UNSAVE_EXPR instead. + +Sun Dec 3 01:34:58 1995 Mike Stump + + * gc.c (build_t_desc): Update error message to say . + +Thu Nov 30 12:30:05 1995 Brendan Kehoe + + * decl.c (pushdecl): Only warn about shadowing a local variable if + warn_shadow is true. + +Sun Nov 26 16:06:55 1995 Rusty Russell + + * typeck.c (build_binary_op_nodefault): Added warning about + comparisons between different enum types with -Wall, unless + -fenum-int-equiv set. + +Wed Nov 22 15:44:02 1995 Mike Stump + + * class.c (finish_struct_1): Skip down to the inner type in + multidimensional arrays. Ensures ctors will be made for types that + need constructing. + +Wed Nov 22 14:19:22 1995 Mike Stump + + * decl.c (last_dtor_insn): New to track the last compiler generated + insn in a dtor. + (store_parm_decls): Set it. + (finish_function): Use it to see if the dtor is empty. Avoid doing + vtable setup all the time, if we can. + (struct cp_function): Add last_dtor_insn. + (push_cp_function_context): Save it. + (pop_cp_function_context): Restore it. - * cp-call.c (build_method_call): If the instance variable is - converted to error_mark_node when we're trying to convert it to the - base type of a method we're looking up, return error_mark_node. +Wed Nov 22 11:52:19 1995 Paul Russell -Thu Dec 2 10:41:16 1993 Torbjorn Granlund (tege@cygnus.com) + * typeck.c (build_unary_op): Set TREE_NO_UNUSED_WARNING to avoid + warnings. - * cp-typeck.c (build_binary_op_nodefault): In *_DIV_EXPR *_MOD_EXPR - cases, tests for unsigned operands by peeking inside a NOP_EXPR. +Tue Nov 21 17:15:23 1995 Mike Stump -Wed Dec 1 13:33:34 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + * typeck.c (expand_target_expr): Make sure targets get put into the + current temp_slot_level, so that the free_temp_slots call will reuse + them. - * cp-call.c (compute_conversion_costs_ansi): Use the size of struct - harshness_code, not the size of short, for clearing out the - ansi_harshness. +Tue Nov 21 13:32:03 1995 Mike Stump - * cp-call.c (print_candidates): New function. - (build_method_call): When we had some candidates, but didn't get a - usable match, don't report that we got an error with the first - candidate. Instead, say there were no matches, and list the - candidates with print_candidates. In the second pass, make sure we - clear out ever_seen, so we can accurately count the number of - functions that qualified. + * class.c (finish_struct_1): Delay delta fixups for virtual bases + until after we have done the hard virtuals, to avoid a bogus `every + virtual function must have a unique final overrider' for virtual + functions that are only overridden by hard virtuals. -Wed Dec 1 09:53:59 1993 Torbjorn Granlund (tege@cygnus.com) +Thu Nov 9 13:35:30 1995 Jason Merrill - * cp-typeck.c (build_binary_op_nodefault): Shorten for *_MOD_EXPR - only if op1 is known to be != -1. - (build_binary_op_nodefault): Handle *_DIV_EXPR likewise. + * pt.c (do_function_instantiation): Don't try to find a file-scope + template for a member function. -Tue Nov 30 14:07:26 1993 Brendan Kehoe (brendan@lisa.cygnus.com) +Tue Nov 14 06:20:35 1995 Mike Stump - * cp-method.c (hack_identifier): If the field itself is private, and - not from a private base class, say so. + * g++.c (main): Add handling of -nodefaultlibs. -Mon Nov 29 03:00:56 1993 Jason Merrill (jason@deneb.cygnus.com) +Mon Nov 13 15:45:34 1995 Mike Stump - * cp-decl.c (grokdeclarator): Always warn on initialization of - const member. + * cp-tree.h (INDIRECT_BIND): Add a way for the frontend to + distinguish between direct bindings of reference variables, and + indirect bindings of reference variables. + * cvt.c (build_up_reference): Use it. + * typeck.c (convert_arguments): Use it to indicate this is an + indirect binding. + * decl.c (cp_finish_decl): Ensure that we reuse stack slots as fast + as they are unused. + (expand_static_init): Likewise. + (cplus_expand_expr_stmt): Likewise. + * decl2.c (finish_file): Likewise. + * init.c (perform_member_init): Likewise. + (emit_base_init): Likewise. + (expand_aggr_vbase_init_1): Likewise. -Wed Nov 24 00:49:35 1993 Jason Merrill (jason@deneb.cygnus.com) +Fri Nov 10 09:18:09 1995 Brendan Kehoe - * cp-class.c (finish_struct): Set TYPE_GETS_CONST_* properly. - (finish_base_struct): Set cant_synth_asn_ref properly. + * decl.c (push_namespace): Rewrite to use build_lang_decl, so we + get a DECL_LANG_SPECIFIC node. + * cp-tree.h (lang_decl_flags): Add new member `level'. + (NAMESPACE_LEVEL): Don't use decl.arguments, instead use the + decl_flags level member. - * cp-lex.c (cons_up_default_function): Add section for operator=. - (default_assign_ref_body): New function, mostly cribbed from - default_copy_constructor_body. +Mon Nov 6 18:36:13 1995 Brendan Kehoe - * cp-class.c (base_info): Add members cant_synth_copy_ctor, - cant_synth_asn_ref, no_const_asn_ref. - (finish_base_struct): Update no_const_asn_ref, note that you should - update cant_synth_*, propagate TYPE_GETS_ASSIGN_REF. - (finish_struct): Add decls for cant_synth_*, no_const_asn_ref, and - initialize them properly. Set no_const_asn_ref properly. Set - cant_synth_* in some of the situations where they should be set. - Propagate TYPE_GETS_ASSIGN_REF. Use cant_synth_copy_ctor. Add call - to cons_up_default_function for operator=. + * call.c (build_method_call): Make sure instance has a + TYPE_LANG_SPECIFIC node before we dive into it. -Tue Nov 23 20:24:58 1993 Mike Stump +Sat Nov 4 20:01:52 1995 Jason Molenda - * cp-cvt.c (convert_force): Add code to perform casting of pointer - to member function types. - * cp-typeck.c (build_ptrmemfunc): Add FORCE parameter to indicate - when the conversion should be done, regardless. - * cp-tree.h (build_ptrmemfunc): Ditto. - * cp-type2.c (digest_init): Ditto. - * cp-typeck.c (convert_for_assignment): Ditto. + * method.c (make_thunk): use TREE_SET_CODE to set thunk's tree code. -Tue Nov 23 18:06:58 1993 Jason Merrill (jason@deneb.cygnus.com) +Thu Nov 2 17:56:57 1995 Mike Stump - * cp-error.c (dump_expr): Do the right thing for variables of - reference type. + * decl.c (duplicate_decls): When smashing decls, smash staticness in + the usual way. - * cp-decl.c (grok_op_properties): Set TYPE_HAS_ASSIGN_REF - and its kin properly. - (xref_tag): Propagate TYPE_GETS_ASSIGN_REF. +Thu Nov 2 16:44:02 1995 Mike Stump -Tue Nov 23 12:26:13 1993 Mike Stump + * decl.c (poplevel): Handle the merging of subblocks of cleanups + when finishing blocks that have already been created (usually due to + the fixup goto code). Fixes bad debugging information. - * cp-method.c (build_opfncall): Don't count pointer to member - functions as aggregates here, as we don't want to look up methods in - them. The compiler would core dump if we did, as they don't have - normal names. - * cp-typeck.c (build_indirect_ref): Improve wording on error - message. +Wed Nov 1 12:33:53 1995 Jason Merrill -Mon Nov 22 14:22:23 1993 Jason Merrill (jason@deneb.cygnus.com) + * method.c (hack_identifier): Don't abort when we get a TREE_LIST + that's not a list of overloaded functions. - * cp-decl.c (grok_op_properties): Allow operator?: with pedwarn - (since it's supported in other compiler bits). +Wed Nov 1 11:38:58 1995 Brendan Kehoe - * cp-method.c (report_type_mismatch): Use cp_error; ignore err_name - argument. + * decl2.c (mark_vtable_entries): Check DECL_LANG_SPECIFIC on fn + before trying to use DECL_ABSTRACT_VIRTUAL_P. - * cp-error.c (dump_function_decl): Don't print return type for - constructors and destructors. +Tue Oct 31 11:56:55 1995 Jason Merrill - * cp-cvt.c (cp_convert_to_pointer): Import code from - convert_to_pointer so we can return error_mark_node in the case of an - error, and to allow more meaningful error messages. - (build_type_conversion): Don't go through void* when trying - to convert to a pointer type. + * decl2.c (mark_used): New function for hooking into setting of + TREE_USED on decls. + * call.c (build_method_call): Use it. + * class.c (instantiate_type): Likewise. + * init.c (build_offset_ref): Likewise. Don't call assemble_external + for all like-named functions. + * method.c (hack_identifier): Likewise. + (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. - * cp-decl.c (grokfndecl): Move call to grok_op_properties back - after grokclassfn so that it's dealing with the right decl. - (grok_op_properties): Don't assert !methodp for op new and op delete. + * decl2.c (grokclassfn): Tweak __in_chrg attributes. - * cp-init.c (build_delete): Don't use TYPE_BUILT_IN (there are now - no uses of it in the compiler). +Thu Oct 26 16:45:58 1995 Brendan Kehoe - * cp-call.c (build_scoped_method_call): Fix for destructors of simple - types. - (build_method_call): Ditto. + * errfn.c: Include stdio.h. + (cp_sprintf): Take out decl of sprintf, and cast sprintf to errorfn*. -Fri Nov 19 12:59:38 1993 Jason Merrill (jason@deneb.cygnus.com) +Wed Oct 25 18:58:41 1995 Mike Stump - * cp-tree.c (count_functions): Abstraction function. + * typeck2.c (digest_init): Always convert initializers to the + right type. - * cp-call.c (build_overload_call_real): Deal with new overloading - properly, remove dead code. +Wed Oct 25 13:25:24 1995 Mike Stump - * gcc.c (default_compilers): Generate and use .ii files in the - intermediate stage of compiling C++ source. + * init.c (member_init_ok_or_else): Don't allow member initializers + for indirect members, as it is invalid. -Fri Nov 19 11:26:09 1993 Jim Wilson (wilson@sphagnum.cygnus.com) +Wed Oct 25 11:35:28 1995 Brendan Kehoe - * cp-expr.c (cplus_expand_expr): Make call_target a valid memory - address before using it, so it can be later safely compared. + * decl.c (grokdeclarator): Don't allow `friend signed ()'. -Fri Nov 12 15:30:27 1993 Jason Merrill (jason@deneb.cygnus.com) +Fri Oct 20 10:30:59 1995 Mike Stump - * cp-pt.c (tsubst): Deal with new overloading. + * parse.y (for.init.statement): Catch compound statements inside for + initializations, if we're being pedantic. - * cp-typeck.c (fntype_p): is the arg function type? - (comp_target_parms): pedwarn on conversion from (anything) to (...). - (build_x_function_call): Deal with new overloading. +Fri Oct 20 10:03:42 1995 Mike Stump - * cp-tree.c (decl_list_length): Deal with new overloading. - (decl_value_member): Like value_member, but for DECL_CHAINs. + * decl.c (lookup_tag): Return NULL_TREE if we don't find what we are + looking for. - * cp-decl.c (duplicate_decls): Deal with new overloading. - (start_decl): Ditto. +Thu Oct 19 14:26:10 1995 Mike Stump - * cp-class.c (instantiate_type): Deal with new overloading. + * error.c (dump_expr): Don't core dump when a boolean expression is + used as a default argument. - * cp-call.c (convert_harshness_ansi): Deal with new overloading. - (convert_harshness_old): Deal with new overloading. - (build_overload_call_real): Ditto. +Thu Oct 19 10:36:30 1995 Jason Merrill -Mon Nov 8 13:50:49 1993 Jason Merrill (jason@deneb.cygnus.com) + * class.c (finish_struct_bits): Check aggregate_value_p instead of + RETURN_IN_MEMORY. - * cp-tree.c (get_unique_fn): New function; returns FUNCTION_DECL - if unambiguous, NULL_TREE otherwise. - (get_first_fn): Returns the first appropriate FUNCTION_DECL. - (is_overloaded_fn): Returns whether or not the passed tree is - a function or list of functions. +Wed Oct 18 18:12:32 1995 Jason Merrill - * cp-init.c (init_init_processing): use `get_first_fn' to find - the FUNCTION_DEFN for new and delete. + * class.c (finish_struct_bits): Also set TREE_ADDRESSABLE on a + BLKmode type that would otherwise be returned in registers. - * cp-decl.c (push_overloaded_decl): Use new overloading strategy, cut - code size in half (I spit on special cases). +Mon Oct 16 12:32:19 1995 Brendan Kehoe -Tue Sep 7 20:03:33 1993 Jason Merrill (jason@deneb.cygnus.com) + * g++.c (WITHLIBC): New macro. + (main): Declare saw_libc. Use WITHLIBC if `-lc' was used; set + saw_libc and pass it at the end if it was set. - * cp-decl.c: Allow references and template type parameters as well +Wed Oct 11 16:30:34 1995 Brendan Kehoe -Local Variables: -eval: (auto-fill-mode) -left-margin: 8 -fill-column: 76 -End: + * parse.y (fn.def1): Call split_specs_attrs in + declmods notype_declarator case. diff --git a/contrib/gcc/cp/Make-lang.in b/contrib/gcc/cp/Make-lang.in index c9d0a39..be02cf1 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 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. #This file is part of GNU CC. @@ -35,7 +35,7 @@ # - making any compiler driver (eg: g++) # - the compiler proper (eg: cc1plus) # - define the names for selecting the language in LANGUAGES. - +# # Extra flags to pass to recursive makes. CXX_FLAGS_TO_PASS = \ "CXX_FOR_BUILD=$(CXX_FOR_BUILD)" \ @@ -45,39 +45,69 @@ CXX_FLAGS_TO_PASS = \ # Actual names to use when installing a native compiler. CXX_INSTALL_NAME = `t='$(program_transform_name)'; echo c++ | sed $$t` GXX_INSTALL_NAME = `t='$(program_transform_name)'; echo g++ | sed $$t` +DEMANGLER_INSTALL_NAME = `t='$(program_transform_name)'; echo c++filt | sed $$t` # Actual names to use when installing a cross-compiler. CXX_CROSS_NAME = `t='$(program_transform_cross_name)'; echo c++ | sed $$t` GXX_CROSS_NAME = `t='$(program_transform_cross_name)'; echo g++ | sed $$t` +DEMANGLER_CROSS_NAME = `t='$(program_transform_cross_name)'; echo c++filt | sed $$t` # The name to use for the demangler program. -DEMANGLER_PROG = c++filt - +DEMANGLER_PROG = c++filt$(exeext) + +# Extra headers to install. +CXX_EXTRA_HEADERS = $(srcdir)/cp/inc/typeinfo $(srcdir)/cp/inc/exception \ + $(srcdir)/cp/inc/new $(srcdir)/cp/inc/new.h + +# Extra code to include in libgcc2. +CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o opnew.o opnewnt.o opvnew.o opvnewnt.o \ + opdel.o opdelnt.o opvdel.o opvdelnt.o exception.o +CXX_LIB2SRCS = $(srcdir)/cp/new.cc $(srcdir)/cp/new1.cc $(srcdir)/cp/new2.cc \ + $(srcdir)/cp/exception.cc $(srcdir)/cp/tinfo.cc \ + $(srcdir)/cp/tinfo2.cc $(srcdir)/cp/tinfo.h +# # Define the names for selecting c++ in LANGUAGES. # Note that it would be nice to move the dependency on g++ # into the C++ rule, but that needs a little bit of work # to do the right thing within all.cross. -C++ c++: cc1plus +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 + # Create the compiler driver for g++. -g++: $(srcdir)/cp/g++.c $(CONFIG_H) $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o $@ $(srcdir)/cp/g++.c $(LIBS) +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) # Create a version of the g++ driver which calls the cross-compiler. -g++-cross: $(srcdir)/cp/g++.c version.o $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o $@ \ - -DGCC_NAME=\"$(GCC_CROSS_NAME)\" $(srcdir)/cp/g++.c version.o $(LIBS) +g++-cross$(exeext): g++$(exeext) + -rm -f g++-cross$(exeext) + cp g++$(exeext) g++-cross$(exeext) cxxmain.o: cplus-dem.c demangle.h rm -f cxxmain.c - ln -s $(srcdir)/cplus-dem.c cxxmain.c > /dev/null 2>&1 \ - || cp $(srcdir)/cplus-dem.c cxxmain.c + $(LN_S) $(srcdir)/cplus-dem.c cxxmain.c $(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DVERSION=\"$(version)\" cxxmain.c - rm -f cxxmain.c $(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LIBS) -o $@ \ @@ -86,26 +116,95 @@ $(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS) CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \ $(srcdir)/cp/except.c $(srcdir)/cp/input.c $(srcdir)/cp/pt.c \ $(srcdir)/cp/spew.c $(srcdir)/cp/xref.c $(srcdir)/cp/class.c \ - $(srcdir)/cp/edsel.c $(srcdir)/cp/expr.c $(srcdir)/cp/lex.c \ + $(srcdir)/cp/expr.c $(srcdir)/cp/lex.c \ $(srcdir)/cp/ptree.c $(srcdir)/cp/tree.c $(srcdir)/cp/cvt.c \ - $(srcdir)/cp/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \ + $(srcdir)/cp/errfn.c $(srcdir)/cp/rtti.c $(srcdir)/cp/method.c \ $(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \ - $(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \ - $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/repo.c + $(srcdir)/cp/error.c $(srcdir)/cp/friend.c $(srcdir)/cp/init.c \ + $(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \ + $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c -cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o - cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus - +cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \ + $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def + cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext) +# # Build hooks: -c++.all.build: g++ $(DEMANGLER_PROG) -c++.all.cross: g++-cross $(DEMANGLER_PROG) -c++.start.encap: g++ +c++.all.build: g++$(exeext) +c++.all.cross: g++-cross$(exeext) $(DEMANGLER_PROG) +c++.start.encap: g++$(exeext) c++.rest.encap: $(DEMANGLER_PROG) c++.info: c++.dvi: - + +# C++ language-support library pieces for libgcc. +tinfo.o: cc1plus$(exeext) $(srcdir)/cp/tinfo.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/cp/tinfo.cc +tinfo2.o: cc1plus$(exeext) $(srcdir)/cp/tinfo2.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/cp/tinfo2.cc +exception.o: cc1plus$(exeext) $(srcdir)/cp/exception.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c -fexceptions $(srcdir)/cp/exception.cc +new.o: cc1plus$(exeext) $(srcdir)/cp/new.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/cp/new.cc +opnew.o: cc1plus$(exeext) $(srcdir)/cp/new1.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(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) \ + -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) \ + -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) \ + -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) \ + -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) \ + -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) \ + -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) \ + -c $(srcdir)/cp/new2.cc -DL_op_vdelnt -o opvdelnt.o + +# We want to update cplib2.txt if any of the source files change... +cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready + case " $(LANGUAGES) " in \ + *" "[cC]"++ "*) \ + echo $(CXX_LIB2FUNCS) > cplib2.new;; \ + *) \ + echo "" > cplib2.new;; \ + esac + 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 \ + case " $(LANGUAGES) " in \ + *" "[cC]"++ "*) \ + echo $(CXX_LIB2FUNCS) > cplib2.new;; \ + *) \ + echo "" > cplib2.new;; \ + esac; \ + if cmp -s cplib2.new cplib2.txt; then true; else \ + touch cplib2.ready; \ + fi; \ + rm -f cplib2.new; \ + else true ; \ + fi + @if [ -f cplib2.ready ]; then true; else \ + touch cplib2.ready; \ + fi +# # Install hooks: # cc1plus is installed elsewhere as part of $(COMPILERS). @@ -121,17 +220,24 @@ c++.install-common: $(INSTALL_PROGRAM) g++-cross$(exeext) $(bindir)/$(GXX_CROSS_NAME)$(exeext); \ chmod a+x $(bindir)/$(GXX_CROSS_NAME)$(exeext); \ rm -f $(bindir)/$(CXX_CROSS_NAME)$(exeext); \ - ln $(bindir)/$(GXX_CROSS_NAME)$(exeext) $(bindir)/$(CXX_CROSS_NAME)$(exeext) \ - > /dev/null 2>&1 \ - || cp $(bindir)/$(GXX_CROSS_NAME)$(exeext) $(bindir)/$(CXX_CROSS_NAME)$(exeext) ; \ + $(LN) $(bindir)/$(GXX_CROSS_NAME)$(exeext) $(bindir)/$(CXX_CROSS_NAME)$(exeext); \ else \ rm -f $(bindir)/$(GXX_INSTALL_NAME)$(exeext); \ $(INSTALL_PROGRAM) g++$(exeext) $(bindir)/$(GXX_INSTALL_NAME)$(exeext); \ chmod a+x $(bindir)/$(GXX_INSTALL_NAME)$(exeext); \ rm -f $(bindir)/$(CXX_INSTALL_NAME)$(exeext); \ - ln $(bindir)/$(GXX_INSTALL_NAME)$(exeext) $(bindir)/$(CXX_INSTALL_NAME)$(exeext) \ - > /dev/null 2>&1 \ - || cp $(bindir)/$(GXX_INSTALL_NAME)$(exeext) $(bindir)/$(CXX_INSTALL_NAME)$(exeext) ; \ + $(LN) $(bindir)/$(GXX_INSTALL_NAME)$(exeext) $(bindir)/$(CXX_INSTALL_NAME)$(exeext); \ + fi ; \ + if [ x$(DEMANGLER_PROG) != x ] && [ -x "$(DEMANGLER_PROG)" ]; then \ + if [ -f g++-cross$(exeext) ] ; then \ + rm -f $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \ + $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \ + chmod a+x $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \ + else \ + rm -f $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \ + $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \ + chmod a+x $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \ + fi ; \ fi ; \ fi @@ -155,9 +261,11 @@ c++.uninstall: -rm -rf $(bindir)/$(CXX_CROSS_NAME)$(exeext) -rm -rf $(bindir)/$(GXX_INSTALL_NAME)$(exeext) -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) - +# # Clean hooks: # A lot of the ancillary files are deleted by the main makefile. # We just have to delete files specific to us. @@ -165,33 +273,41 @@ c++.uninstall: c++.mostlyclean: -rm -f cp/*$(objext) $(DEMANGLER_PROG) c++.clean: + -rm -f cplib2.txt cplib2.ready 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 - +# # Stage hooks: # The main makefile has already created stage?/cp. -c++.stage1: +c++.stage1: stage1-start -mv cp/*$(objext) stage1/cp -c++.stage2: +c++.stage2: stage2-start -mv cp/*$(objext) stage2/cp -c++.stage3: +c++.stage3: stage3-start -mv cp/*$(objext) stage3/cp -c++.stage4: +c++.stage4: stage4-start -mv cp/*$(objext) stage4/cp - +# # Maintenance hooks: # This target creates the files that can be rebuilt, but go in the # distribution anyway. It then copies the files to the distdir directory. c++.distdir: mkdir tmp/cp + mkdir tmp/cp/inc cd cp ; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) parse.c hash.h cd cp; \ for file in *[0-9a-zA-Z+]; do \ - ln $$file ../tmp/cp >/dev/null 2>&1 || cp $$file ../tmp/cp; \ + $(LN) $$file ../tmp/cp; \ + done + cd cp/inc; \ + for file in *[0-9a-zA-Z+]; do \ + ln $$file ../../tmp/cp/inc >/dev/null 2>&1 \ + || cp $$file ../../tmp/cp/inc; \ done diff --git a/contrib/gcc/cp/Makefile.in b/contrib/gcc/cp/Makefile.in index 11466b2..8d7098d 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-4, 1995 Free Software Foundation, Inc. +# Copyright (C) 1987, 88, 90-5, 1998 Free Software Foundation, Inc. #This file is part of GNU CC. @@ -54,10 +54,10 @@ T_CFLAGS = X_CPPFLAGS = T_CPPFLAGS = -CC = cc -BISON = bison +CC = @CC@ +BBISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi` BISONFLAGS = -LEX = flex +LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi` LEXFLAGS = AR = ar AR_FLAGS = rc @@ -83,14 +83,21 @@ GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) # These are used because `configure' appends `cross-make' # to the makefile when making a cross-compiler. -target= ... `configure' substitutes actual target name here. -xmake_file= ... `configure' substitutes actual x- file name here. -tmake_file= ... `configure' substitutes actual t- file name here. +# We don't use cross-make. Instead we use the tools +# from the build tree, if they are available. +# program_transform_name and objdir are set by configure.in. +program_transform_name = +objdir = . + +target=@target@ +xmake_file=@dep_host_xmake_file@ +tmake_file=@dep_tmake_file@ #version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c` #mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c` # Directory where sources are, from where we are. -srcdir = . +srcdir = @srcdir@ +VPATH = @srcdir@ # Additional system libraries to link with. CLIB= @@ -113,16 +120,21 @@ all: all.indirect # sed inserts variable overrides after the following line. ####target overrides +@target_overrides@ ####host overrides +@host_overrides@ ####cross overrides +@cross_defines@ +@cross_overrides@ ####build overrides - +@build_overrides@ +# # Now figure out from those variables how to compile and link. -all.indirect: Makefile ../cc1plus +all.indirect: Makefile ../cc1plus$(exeext) # IN_GCC tells obstack.h that we are using gcc's file. -INTERNAL_CFLAGS = $(CROSS) -DIN_GCC +INTERNAL_CFLAGS = $(CROSS) -DIN_GCC @extra_c_flags@ # This is the variable actually used when we compile. ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS) @@ -150,33 +162,37 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config .c.o: $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< +# The only suffixes we want for implicit rules are .c and .o. +.SUFFIXES: +.SUFFIXES: .c .o + # This tells GNU make version 3 not to export all the variables # defined in this file into the environment. .NOEXPORT: - +# # Lists of files for various purposes. # Language-specific object files for g++ CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \ - class.o decl2.o error.o gc.o lex.o parse.o ptree.o spew.o typeck.o cvt.o \ - edsel.o except.o init.o method.o search.o tree.o xref.o repo.o + class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \ + except.o friend.o init.o method.o search.o semantics.o tree.o xref.o \ + repo.o @extra_cxx_objs@ # Language-independent object files. OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o -compiler: ../cc1plus -../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS) - rm -f ../cc1plus$(exeext) +compiler: ../cc1plus$(exeext) +../cc1plus$(exeext): $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ $(CXX_OBJS) $(OBJS) $(LIBS) Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure cd ..; $(SHELL) config.status -native: config.status ../cc1plus - +native: config.status ../cc1plus$(exeext) +# # Compiling object files from source files. # Note that dependencies on obstack.h are not written @@ -188,15 +204,18 @@ RTL_H = $(srcdir)/../rtl.h $(srcdir)/../rtl.def \ $(srcdir)/../machmode.h $(srcdir)/../machmode.def TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \ $(srcdir)/../machmode.h $(srcdir)/../machmode.def -CXX_TREE_H = $(TREE_H) cp-tree.h tree.def +CXX_TREE_H = $(TREE_H) cp-tree.h cp-tree.def PARSE_H = $(srcdir)/parse.h PARSE_C = $(srcdir)/parse.c +EXPR_H = $(srcdir)/../expr.h ../insn-codes.h -parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h +parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h \ + $(srcdir)/../except.h $(srcdir)/../output.h $(srcdir)/../system.h \ + $(srcdir)/../toplev.h $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \ `echo $(PARSE_C) | sed 's,^\./,,'` -CONFLICTS = expect 5 shift/reduce conflicts and 38 reduce/reduce conflicts. +CONFLICTS = expect 26 shift/reduce conflicts and 42 reduce/reduce conflicts. $(PARSE_H) : $(PARSE_C) $(PARSE_C) : $(srcdir)/parse.y @echo $(CONFLICTS) @@ -221,35 +240,61 @@ $(srcdir)/hash.h: $(srcdir)/gxx.gperf >$(srcdir)/hash.h spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \ - $(PARSE_H) $(srcdir)/../flags.h lex.h + $(PARSE_H) $(srcdir)/../flags.h lex.h $(srcdir)/../system.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 + $(PARSE_H) input.c $(srcdir)/../flags.h hash.h lex.h \ + $(srcdir)/../c-pragma.h $(srcdir)/../system.h $(srcdir)/../toplev.h \ + $(srcdir)/../output.h decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ - lex.h decl.h $(srcdir)/../stack.h + lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \ + $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ - lex.h decl.h -typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h -typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) -class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h -call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h class.h -init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) -method.o : method.c $(CONFIG_H) $(CXX_TREE_H) class.h -cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) class.h -search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h -tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h -ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) -gc.o : gc.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h -except.o : except.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_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 +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 +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) \ + $(srcdir)/../system.h $(srcdir)/../toplev.h +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 +search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \ + $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.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 +rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ + $(srcdir)/../system.h $(srcdir)/../toplev.h +except.o : except.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \ + $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h expr.o : expr.c $(CONFIG_H) $(CXX_TREE_H) $(RTL_H) $(srcdir)/../flags.h \ - $(srcdir)/../expr.h ../insn-codes.h -edsel.o : edsel.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h -xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h -pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H) -error.o : error.c $(CONFIG_H) $(CXX_TREE_H) -errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H) -sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h -repo.o : repo.c $(CONFIG_H) $(CXX_TREE_H) - + $(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h +xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h \ + $(srcdir)/../system.h $(srcdir)/../toplev.h +pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H) lex.h \ + $(srcdir)/../system.h $(srcdir)/../toplev.h +error.o : error.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \ + $(srcdir)/../toplev.h +errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \ + $(srcdir)/../toplev.h +sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ + $(srcdir)/../system.h $(srcdir)/../toplev.h +repo.o : repo.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \ + $(srcdir)/../toplev.h +semantics.o: semantics.c $(CONFIG_H) $(CXX_TREE_H) lex.h \ + $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h + + +# # These exist for maintenance purposes. # Update the tags table. @@ -263,3 +308,32 @@ 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{\1}?' \ + -e 's?@file{\(comp\.[-a-z+.]*\)}?\1?' \ + -e 's?@file{\(gnu\.[-a-z+.]*\)}?\1?' \ + -e 's?\([.+a-zA-Z0-9-]*@@[.a-zA-Z0-9-]*[a-zA-Z0-9]\)?\1?' \ + $(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 new file mode 100644 index 0000000..9cb7d5b --- /dev/null +++ b/contrib/gcc/cp/NEWS @@ -0,0 +1,226 @@ +*** Changes in EGCS 1.1: + +* Namespaces are fully supported. The library has not yet been converted + to use namespace std, however, and the old std-faking code is still on by + default. To turn it off, you can use -fhonor-std. + +* Massive template improvements: + + member template classes are supported. + + template friends are supported. + + template template parameters are supported. + + local classes in templates are supported. + + lots of bugs fixed. + +* operator new now throws bad_alloc where appropriate. + +* Exception handling is now thread safe, and supports nested exceptions and + placement delete. Exception handling overhead on x86 is much lower with + GNU as 2.9. + +* protected virtual inheritance is now supported. + +* Loops are optimized better; we now move the test to the end in most + cases, like the C frontend does. + +* For class D derived from B which has a member 'int i', &D::i is now of + type 'int B::*' instead of 'int D::*'. + +* An _experimental_ new ABI for g++ can be turned on with -fnew-abi. The + current features of this are more efficient allocation of base classes + (including the empty base optimization), and more compact mangling of C++ + symbol names (which can be turned on separately with -fsquangle). This + ABI is subject to change without notice, so don't use it for anything + that you don't want to rebuild with every release of the compiler. + + As with all ABI-changing flags, this flag is for experts only, as all + code (including the library code in libgcc and libstdc++) must be + compiled with the same ABI. + +*** Changes in EGCS 1.0: + +* A public review copy of the December 1996 Draft of the ISO/ANSI C++ + standard is now available. See + + http://www.cygnus.com/misc/wp/ + + for more information. + +* g++ now uses a new implementation of templates. The basic idea is that + now templates are minimally parsed when seen and then expanded later. + This allows conformant early name binding and instantiation controls, + since instantiations no longer have to go through the parser. + + What you get: + + + Inlining of template functions works without any extra effort or + modifications. + + Instantiations of class templates and methods defined in the class + body are deferred until they are actually needed (unless + -fexternal-templates is specified). + + Nested types in class templates work. + + Static data member templates work. + + Member function templates are now supported. + + Partial specialization of class templates is now supported. + + Explicit specification of template parameters to function templates + is now supported. + + Things you may need to fix in your code: + + + Syntax errors in templates that are never instantiated will now be + diagnosed. + + Types and class templates used in templates must be declared + first, or the compiler will assume they are not types, and fail. + + Similarly, nested types of template type parameters must be tagged + with the 'typename' keyword, except in base lists. In many cases, + but not all, the compiler will tell you where you need to add + 'typename'. For more information, see + + http://www.cygnus.com/misc/wp/dec96pub/template.html#temp.res + + + Guiding declarations are no longer supported. Function declarations, + including friend declarations, do not refer to template instantiations. + You can restore the old behavior with -fguiding-decls until you fix + your code. + + Other features: + + + Default function arguments in templates will not be evaluated (or + checked for semantic validity) unless they are needed. Default + arguments in class bodies will not be parsed until the class + definition is complete. + + The -ftemplate-depth-NN flag can be used to increase the maximum + recursive template instantiation depth, which defaults to 17. If you + need to use this flag, the compiler will tell you. + + Explicit instantiation of template constructors and destructors is + now supported. For instance: + + template A::A(const A&); + + Still not supported: + + + Member class templates. + + Template friends. + +* Exception handling support has been significantly improved and is on by + default. The compiler supports two mechanisms for walking back up the + call stack; one relies on static information about how registers are + saved, and causes no runtime overhead for code that does not throw + exceptions. The other mechanism uses setjmp and longjmp equivalents, and + can result in quite a bit of runtime overhead. You can determine which + mechanism is the default for your target by compiling a testcase that + uses exceptions and doing an 'nm' on the object file; if it uses __throw, + it's using the first mechanism. If it uses __sjthrow, it's using the + second. + + You can turn EH support off with -fno-exceptions. + +* RTTI support has been rewritten to work properly and is now on by default. + This means code that uses virtual functions will have a modest space + overhead. You can use the -fno-rtti flag to disable RTTI support. + +* On ELF systems, duplicate copies of symbols with 'initialized common' + linkage (such as template instantiations, vtables, and extern inlines) + will now be discarded by the GNU linker, so you don't need to use -frepo. + This support requires GNU ld from binutils 2.8 or later. + +* The overload resolution code has been rewritten to conform to the latest + C++ Working Paper. Built-in operators are now considered as candidates + in operator overload resolution. Function template overloading chooses + the more specialized template, and handles base classes in type deduction + and guiding declarations properly. In this release the old code can + still be selected with -fno-ansi-overloading, although this is not + supported and will be removed in a future release. + +* Standard usage syntax for the std namespace is supported; std is treated + as an alias for global scope. General namespaces are still not supported. + +* New flags: + + + New warning -Wno-pmf-conversion (don't warn about + converting from a bound member function pointer to function + pointer). + + + A flag -Weffc++ has been added for violations of some of the style + guidelines in Scott Meyers' _Effective C++_ books. + + + -Woverloaded-virtual now warns if a virtual function in a base + class is hidden in a derived class, rather than warning about + virtual functions being overloaded (even if all of the inherited + signatures are overridden) as it did before. + + + -Wall no longer implies -W. The new warning flag, -Wsign-compare, + included in -Wall, warns about dangerous comparisons of signed and + unsigned values. Only the flag is new; it was previously part of + -W. + + + The new flag, -fno-weak, disables the use of weak symbols. + +* Synthesized methods are now emitted in any translation units that need + an out-of-line copy. They are no longer affected by #pragma interface + or #pragma implementation. + +* __FUNCTION__ and __PRETTY_FUNCTION__ are now treated as variables by the + parser; previously they were treated as string constants. So code like + `printf (__FUNCTION__ ": foo")' must be rewritten to + `printf ("%s: foo", __FUNCTION__)'. This is necessary for templates. + +* local static variables in extern inline functions will be shared between + translation units. + +* -fvtable-thunks is supported for all targets, and is the default for + Linux with glibc 2.x (also called libc 6.x). + +* bool is now always the same size as another built-in type. Previously, + a 64-bit RISC target using a 32-bit ABI would have 32-bit pointers and a + 64-bit bool. This should only affect Irix 6, which was not supported in + 2.7.2. + +* new (nothrow) is now supported. + +* Synthesized destructors are no longer made virtual just because the class + already has virtual functions, only if they override a virtual destructor + in a base class. The compiler will warn if this affects your code. + +* The g++ driver now only links against libstdc++, not libg++; it is + functionally identical to the c++ driver. + +* (void *)0 is no longer considered a null pointer constant; NULL in + is now defined as __null, a magic constant of type (void *) + normally, or (size_t) with -ansi. + +* The name of a class is now implicitly declared in its own scope; A::A + refers to A. + +* Local classes are now supported. + +* __attribute__ can now be attached to types as well as declarations. + +* The compiler no longer emits a warning if an ellipsis is used as a + function's argument list. + +* Definition of nested types outside of their containing class is now + supported. For instance: + + struct A { + struct B; + B* bp; + }; + + struct A::B { + int member; + }; + +* On the HPPA, some classes that do not define a copy constructor + will be passed and returned in memory again so that functions + returning those types can be inlined. + +*** The g++ team thanks everyone that contributed to this release, + but especially: + +* Joe Buck , the maintainer of the g++ FAQ. +* Brendan Kehoe , who coordinates testing of g++. +* Jason Merrill , the g++ maintainer. +* Mark Mitchell , who implemented member function + templates and explicit qualification of function templates. +* Mike Stump , the previous g++ maintainer, who did most of + the exception handling work. diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c index 3f293ac..e65898e 100644 --- a/contrib/gcc/cp/call.c +++ b/contrib/gcc/cp/call.c @@ -1,7 +1,7 @@ /* Functions related to invoking methods and overloaded functions. - Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) and - hacked by Brendan Kehoe (brendan@cygnus.com). + modified by Brendan Kehoe (brendan@cygnus.com). This file is part of GNU CC. @@ -21,2973 +21,4496 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* High-level class interface. */ +/* High-level class interface. */ #include "config.h" +#include "system.h" #include "tree.h" -#include #include "cp-tree.h" -#include "class.h" #include "output.h" #include "flags.h" +#include "rtl.h" +#include "toplev.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free -extern void sorry (); - extern int inhibit_warnings; -extern int flag_assume_nonnull_objects; extern tree ctor_label, dtor_label; -/* From typeck.c: */ -extern tree unary_complex_lvalue (); +static tree build_new_method_call PROTO((tree, tree, tree, tree, int)); + +static tree build_field_call PROTO((tree, tree, tree, tree)); +static tree find_scoped_type PROTO((tree, tree, tree)); +static struct z_candidate * tourney PROTO((struct z_candidate *)); +static int joust PROTO((struct z_candidate *, struct z_candidate *, int)); +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 *)); +static tree build_object_call PROTO((tree, tree)); +static tree resolve_args PROTO((tree)); +static struct z_candidate * build_user_type_conversion_1 + PROTO ((tree, tree, int)); +static void print_z_candidates PROTO((struct z_candidate *)); +static tree build_this PROTO((tree)); +static struct z_candidate * splice_viable PROTO((struct z_candidate *)); +static int any_viable PROTO((struct z_candidate *)); +static struct z_candidate * add_template_candidate + PROTO((struct z_candidate *, tree, tree, tree, tree, int, + unification_kind_t)); +static struct z_candidate * add_template_candidate_real + PROTO((struct z_candidate *, tree, tree, tree, tree, int, + tree, unification_kind_t)); +static struct z_candidate * add_template_conv_candidate + PROTO((struct z_candidate *, tree, tree, tree, tree)); +static struct z_candidate * add_builtin_candidates + PROTO((struct z_candidate *, enum tree_code, enum tree_code, + tree, tree *, int)); +static struct z_candidate * add_builtin_candidate + PROTO((struct z_candidate *, enum tree_code, enum tree_code, + tree, tree, tree, tree *, tree *, int)); +static int is_complete PROTO((tree)); +static struct z_candidate * build_builtin_candidate + PROTO((struct z_candidate *, tree, tree, tree, tree *, tree *, + int)); +static struct z_candidate * add_conv_candidate + PROTO((struct z_candidate *, tree, tree, tree)); +static struct z_candidate * add_function_candidate + PROTO((struct z_candidate *, tree, tree, int)); +static tree implicit_conversion PROTO((tree, tree, tree, int)); +static tree standard_conversion PROTO((tree, tree, tree)); +static tree reference_binding PROTO((tree, tree, tree, int)); +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*)); -/* Compute the ease with which a conversion can be performed - between an expected and the given type. */ -static struct harshness_code convert_harshness (); +tree +build_vfield_ref (datum, type) + tree datum, type; +{ + tree rval; + int old_assume_nonnull_objects = flag_assume_nonnull_objects; -#define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG)) -#define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG)) -#define QUAL_RETURN(ARG) ((ARG).code = QUAL_CODE, (ARG)) -#define TRIVIAL_RETURN(ARG) ((ARG).code = TRIVIAL_CODE, (ARG)) -#define ZERO_RETURN(ARG) ((ARG).code = 0, (ARG)) + if (datum == error_mark_node) + return error_mark_node; -/* Ordering function for overload resolution. Compare two candidates - by gross quality. */ -int -rank_for_overload (x, y) - struct candidate *x, *y; + /* 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); + + if (! TYPE_USES_COMPLEX_INHERITANCE (type)) + rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (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; +} + +/* Build a call to a member of an object. I.e., one that overloads + operator ()(), or is a pointer-to-function or pointer-to-method. */ + +static tree +build_field_call (basetype_path, instance_ptr, name, parms) + tree basetype_path, instance_ptr, name, parms; { - if (y->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE)) - return y->h.code - x->h.code; - if (x->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE)) - return -1; + tree field, instance; - /* This is set by compute_conversion_costs, for calling a non-const - member function from a const member function. */ - if ((y->harshness[0].code & CONST_CODE) ^ (x->harshness[0].code & CONST_CODE)) - return y->harshness[0].code - x->harshness[0].code; + if (name == ctor_identifier || name == dtor_identifier) + return NULL_TREE; - if (y->h.code & STD_CODE) + if (instance_ptr == current_class_ptr) { - if (x->h.code & STD_CODE) - return y->h.distance - x->h.distance; - return 1; + /* 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; } - if (x->h.code & STD_CODE) - return -1; - return y->h.code - x->h.code; + /* 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 && TREE_CODE (field) == FIELD_DECL) + { + tree basetype; + tree ftype = TREE_TYPE (field); + + if (TREE_CODE (ftype) == REFERENCE_TYPE) + ftype = TREE_TYPE (ftype); + + if (TYPE_LANG_SPECIFIC (ftype)) + { + /* 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 (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; } -/* Compare two candidates, argument by argument. */ -int -rank_for_ideal (x, y) - struct candidate *x, *y; +static tree +find_scoped_type (type, inner_name, inner_types) + tree type, inner_name, inner_types; { - int i; - - if (x->h_len != y->h_len) - abort (); + tree tags = CLASSTYPE_TAGS (type); - for (i = 0; i < x->h_len; i++) + while (tags) { - if (y->harshness[i].code - x->harshness[i].code) - return y->harshness[i].code - x->harshness[i].code; - if ((y->harshness[i].code & STD_CODE) - && (y->harshness[i].distance - x->harshness[i].distance)) - return y->harshness[i].distance - x->harshness[i].distance; - - /* They're both the same code. Now see if we're dealing with an - integral promotion that needs a finer grain of accuracy. */ - if (y->harshness[0].code & PROMO_CODE - && (y->harshness[i].int_penalty ^ x->harshness[i].int_penalty)) - return y->harshness[i].int_penalty - x->harshness[i].int_penalty; + /* The TREE_PURPOSE of an enum tag (which becomes a member of the + enclosing class) is set to the name for the enum type. So, if + inner_name is `bar', and we strike `baz' for `enum bar { baz }', + then this test will be true. */ + if (TREE_PURPOSE (tags) == inner_name) + { + if (inner_types == NULL_TREE) + return TYPE_MAIN_DECL (TREE_VALUE (tags)); + return resolve_scope_to_name (TREE_VALUE (tags), inner_types); + } + tags = TREE_CHAIN (tags); } - return 0; + + /* Look for a TYPE_DECL. */ + for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags)) + if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name) + { + /* Code by raeburn. */ + if (inner_types == NULL_TREE) + return tags; + return resolve_scope_to_name (TREE_TYPE (tags), inner_types); + } + + return NULL_TREE; } -/* TYPE is the type we wish to convert to. PARM is the parameter - we have to work with. We use a somewhat arbitrary cost function - to measure this conversion. */ -static struct harshness_code -convert_harshness (type, parmtype, parm) - register tree type, parmtype; - tree parm; +/* Resolve an expression NAME1::NAME2::...::NAMEn to + the name that names the above nested type. INNER_TYPES + is a chain of nested type names (held together by SCOPE_REFs); + OUTER_TYPE is the type we know to enclose INNER_TYPES. + Returns NULL_TREE if there is an error. */ + +tree +resolve_scope_to_name (outer_type, inner_stuff) + tree outer_type, inner_stuff; { - struct harshness_code h; - register enum tree_code codel; - register enum tree_code coder; - int lvalue; + register tree tmp; + tree inner_name, inner_type; - h.code = 0; - h.distance = 0; - h.int_penalty = 0; + if (outer_type == NULL_TREE && current_class_type != NULL_TREE) + { + /* We first try to look for a nesting in our current class context, + then try any enclosing classes. */ + tree type = current_class_type; + + while (type && (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE)) + { + tree rval = resolve_scope_to_name (type, inner_stuff); -#ifdef GATHER_STATISTICS - n_convert_harshness++; -#endif + if (rval != NULL_TREE) + return rval; + type = DECL_CONTEXT (TYPE_MAIN_DECL (type)); + } + } - if (TREE_CODE (parmtype) == REFERENCE_TYPE) + if (TREE_CODE (inner_stuff) == SCOPE_REF) { - if (parm) - parm = convert_from_reference (parm); - parmtype = TREE_TYPE (parmtype); - lvalue = 1; + inner_name = TREE_OPERAND (inner_stuff, 0); + inner_type = TREE_OPERAND (inner_stuff, 1); } - else if (parm) - lvalue = lvalue_p (parm); else - lvalue = 0; + { + inner_name = inner_stuff; + inner_type = NULL_TREE; + } - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); - if (TYPE_PTRMEMFUNC_P (parmtype)) - parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); + if (outer_type == NULL_TREE) + { + tree x; + /* If we have something that's already a type by itself, + use that. */ + if (IDENTIFIER_HAS_TYPE_VALUE (inner_name)) + { + if (inner_type) + return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name), + inner_type); + return inner_name; + } + + x = lookup_name (inner_name, 0); - codel = TREE_CODE (type); - coder = TREE_CODE (parmtype); + if (x && TREE_CODE (x) == NAMESPACE_DECL) + { + x = lookup_namespace_name (x, inner_type); + return x; + } + return NULL_TREE; + } - if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type)) - return ZERO_RETURN (h); + if (! IS_AGGR_TYPE (outer_type)) + return NULL_TREE; - if (coder == ERROR_MARK) - return EVIL_RETURN (h); + /* Look for member classes or enums. */ + tmp = find_scoped_type (outer_type, inner_name, inner_type); - if (codel == REFERENCE_TYPE) + /* If it's not a type in this class, then go down into the + base classes and search there. */ + if (! tmp && TYPE_BINFO (outer_type)) { - tree ttl, ttr; - int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype); - int volatilep = (parm ? TREE_THIS_VOLATILE (parm) - : TYPE_VOLATILE (parmtype)); - register tree intype = TYPE_MAIN_VARIANT (parmtype); - register enum tree_code form = TREE_CODE (intype); - int penalty = 0; + tree binfos = TYPE_BINFO_BASETYPES (outer_type); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; - ttl = TREE_TYPE (type); + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tmp = resolve_scope_to_name (BINFO_TYPE (base_binfo), inner_stuff); + if (tmp) + return tmp; + } + tmp = NULL_TREE; + } - /* Only allow const reference binding if we were given a parm to deal - with, since it isn't really a conversion. This is a hack to - prevent build_type_conversion from finding this conversion, but - still allow overloading to find it. */ - if (! lvalue && ! (parm && TYPE_READONLY (ttl))) - return EVIL_RETURN (h); + return tmp; +} - if (TYPE_READONLY (ttl) < constp - || TYPE_VOLATILE (ttl) < volatilep) - return EVIL_RETURN (h); +/* Returns nonzero iff the destructor name specified in NAME + (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many + forms... */ - /* When passing a non-const argument into a const reference, dig it a - little, so a non-const reference is preferred over this one. */ - penalty = ((TYPE_READONLY (ttl) > constp) - + (TYPE_VOLATILE (ttl) > volatilep)); +int +check_dtor_name (basetype, name) + tree basetype, name; +{ + name = TREE_OPERAND (name, 0); - ttl = TYPE_MAIN_VARIANT (ttl); + if (TREE_CODE (name) == TYPE_DECL) + name = TREE_TYPE (name); + else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + /* OK */; + else if (TREE_CODE (name) == IDENTIFIER_NODE) + { + if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype)) + || (TREE_CODE (basetype) == ENUMERAL_TYPE + && name == TYPE_IDENTIFIER (basetype))) + name = basetype; + else + name = get_type_value (name); + } + else + my_friendly_abort (980605); + + if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name)) + return 1; + return 0; +} + +/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. + This is how virtual function calls are avoided. */ - if (form == OFFSET_TYPE) +tree +build_scoped_method_call (exp, basetype, name, parms) + tree exp, basetype, name, parms; +{ + /* Because this syntactic form does not allow + a pointer to a base class to be `stolen', + we need not protect the derived->base conversion + that happens here. + + @@ But we do have to check access privileges later. */ + tree binfo, decl; + tree type = TREE_TYPE (exp); + + if (type == error_mark_node + || basetype == error_mark_node) + return error_mark_node; + + if (processing_template_decl) + { + if (TREE_CODE (name) == BIT_NOT_EXPR + && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) { - intype = TREE_TYPE (intype); - form = TREE_CODE (intype); + tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0); + if (type) + name = build_min_nt (BIT_NOT_EXPR, type); } + name = build_min_nt (SCOPE_REF, basetype, name); + return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE); + } + + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); - ttr = intype; + if (TREE_CODE (basetype) == TREE_VEC) + { + binfo = basetype; + basetype = BINFO_TYPE (binfo); + } + else + binfo = NULL_TREE; + + /* Check the destructor call syntax. */ + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + /* We can get here if someone writes their destructor call like + `obj.NS::~T()'; this isn't really a scoped method call, so hand + it off. */ + if (TREE_CODE (basetype) == NAMESPACE_DECL) + return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL); + + if (! check_dtor_name (basetype, name)) + cp_error ("qualified type `%T' does not match destructor name `~%T'", + basetype, TREE_OPERAND (name, 0)); - if (TREE_CODE (ttl) == ARRAY_TYPE && TREE_CODE (ttr) == ARRAY_TYPE) + /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note + that explicit ~int is caught in the parser; this deals with typedefs + and template parms. */ + if (! IS_AGGR_TYPE (basetype)) { - if (comptypes (ttl, ttr, 1)) - return ZERO_RETURN (h); - return EVIL_RETURN (h); + if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype)) + cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')", + exp, basetype, type); + + return cp_convert (void_type_node, exp); } + } - h = convert_harshness (ttl, ttr, NULL_TREE); - if (penalty && h.code == 0) + if (! is_aggr_type (basetype, 1)) + return error_mark_node; + + if (! IS_AGGR_TYPE (type)) + { + cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'", + exp, type); + return error_mark_node; + } + + if (! binfo) + { + binfo = get_binfo (basetype, type, 1); + if (binfo == error_mark_node) + return error_mark_node; + if (! binfo) + error_not_base_type (basetype, type); + } + + if (binfo) + { + if (TREE_CODE (exp) == INDIRECT_REF) + decl = build_indirect_ref + (convert_pointer_to_real + (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR); + else + decl = build_scoped_ref (exp, basetype); + + /* Call to a destructor. */ + if (TREE_CODE (name) == BIT_NOT_EXPR) { - h.code = QUAL_CODE; - h.int_penalty = penalty; + if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl))) + return cp_convert (void_type_node, exp); + + return build_delete (TREE_TYPE (decl), decl, integer_two_node, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, + 0); } - return h; + + /* Call to a method. */ + return build_method_call (decl, name, parms, binfo, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); } + return error_mark_node; +} + +/* We want the address of a function or method. We avoid creating a + pointer-to-member function. */ + +tree +build_addr_func (function) + tree function; +{ + tree type = TREE_TYPE (function); - if (codel == POINTER_TYPE && fntype_p (parmtype)) + /* We have to do these by hand to avoid real pointer to member + functions. */ + if (TREE_CODE (type) == METHOD_TYPE) { - tree p1, p2; - struct harshness_code h1, h2; + tree addr; + + type = build_pointer_type (type); + + if (mark_addressable (function) == 0) + return error_mark_node; + + addr = build1 (ADDR_EXPR, type, function); + + /* Address of a static or external variable or function counts + as a constant */ + if (staticp (function)) + TREE_CONSTANT (addr) = 1; + + function = addr; + } + else + function = default_conversion (function); + + return function; +} + +/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or + POINTER_TYPE to those. Note, pointer to member function types + (TYPE_PTRMEMFUNC_P) must be handled by our callers. */ - /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be. */ - type = TREE_TYPE (type); +tree +build_call (function, result_type, parms) + tree function, result_type, parms; +{ + int is_constructor = 0; + tree tmp; + tree decl; + + function = build_addr_func (function); + + if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) + { + sorry ("unable to call pointer to member function here"); + return error_mark_node; + } - if (coder == POINTER_TYPE) + if (TREE_CODE (function) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) + decl = TREE_OPERAND (function, 0); + else + decl = NULL_TREE; + + if (decl && DECL_CONSTRUCTOR_P (decl)) + is_constructor = 1; + + /* 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. */ + if (! decl || ! DECL_BUILT_IN (decl)) + for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp)) + if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) + && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) { - parmtype = TREE_TYPE (parmtype); - coder = TREE_CODE (parmtype); + tree t = make_node (RTL_EXPR); + TREE_TYPE (t) = TREE_TYPE (TREE_VALUE (tmp)); + RTL_EXPR_RTL (t) = const0_rtx; + RTL_EXPR_SEQUENCE (t) = NULL_RTX; + TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t), + TREE_VALUE (tmp), t); } - if (coder != TREE_CODE (type)) - return EVIL_RETURN (h); + function = build_nt (CALL_EXPR, function, parms, NULL_TREE); + TREE_HAS_CONSTRUCTOR (function) = is_constructor; + TREE_TYPE (function) = result_type; + TREE_SIDE_EFFECTS (function) = 1; + + return function; +} - if (type != parmtype && coder == METHOD_TYPE) - { - tree ttl = TYPE_METHOD_BASETYPE (type); - tree ttr = TYPE_METHOD_BASETYPE (parmtype); +/* Build something of the form ptr->method (args) + or object.method (args). This can also build + calls to constructors, and find friends. - int b_or_d = get_base_distance (ttr, ttl, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (ttl, ttr, 0, 0); - if (b_or_d < 0) - return EVIL_RETURN (h); - h.distance = -b_or_d; - } - else - h.distance = b_or_d; - h.code = STD_CODE; + Member functions always take their class variable + as a pointer. - type = build_function_type - (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); - parmtype = build_function_type - (TREE_TYPE (parmtype), TREE_CHAIN (TYPE_ARG_TYPES (parmtype))); - } + INSTANCE is a class instance. - /* We allow the default conversion between function type - and pointer-to-function type for free. */ - if (comptypes (type, parmtype, 1)) - return h; + NAME is the name of the method desired, usually an IDENTIFIER_NODE. - if (pedantic) - return EVIL_RETURN (h); + PARMS help to figure out what that NAME really refers to. - /* Compare return types. */ - p1 = TREE_TYPE (type); - p2 = TREE_TYPE (parmtype); - h2 = convert_harshness (p1, p2, NULL_TREE); - if (h2.code & EVIL_CODE) - return h2; + BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE + down to the real instance type to use for access checking. We need this + information to get protected accesses correct. This parameter is used + by build_member_call. - h1.code = TRIVIAL_CODE; - h1.distance = 0; + FLAGS is the logical disjunction of zero or more LOOKUP_ + flags. See cp-tree.h for more info. - if (h2.distance != 0) - { - tree binfo; + If this is all OK, calls build_function_call with the resolved + member function. - /* This only works for pointers. */ - if (TREE_CODE (p1) != POINTER_TYPE - && TREE_CODE (p1) != REFERENCE_TYPE) - return EVIL_RETURN (h); + This function must also handle being called to perform + initialization, promotion/coercion of arguments, and + instantiation of default parameters. - p1 = TREE_TYPE (p1); - p2 = TREE_TYPE (p2); - /* Don't die if we happen to be dealing with void*. */ - if (!IS_AGGR_TYPE (p1) || !IS_AGGR_TYPE (p2)) - return EVIL_RETURN (h); - if (h2.distance < 0) - binfo = get_binfo (p2, p1, 0); - else - binfo = get_binfo (p1, p2, 0); + Note that NAME may refer to an instance variable name. If + `operator()()' is defined for the type of that field, then we return + that result. */ - if (! BINFO_OFFSET_ZEROP (binfo)) - { -#if 0 - static int explained = 0; - if (h2.distance < 0) - message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1); - else - message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2); +tree +build_method_call (instance, name, parms, basetype_path, flags) + tree instance, name, parms, basetype_path; + int flags; +{ + tree basetype, instance_ptr; - if (! explained++) - sorry ("(because pointer values change during conversion)"); +#ifdef GATHER_STATISTICS + n_build_method_call++; #endif - return EVIL_RETURN (h); - } + + if (instance == error_mark_node + || name == error_mark_node + || parms == error_mark_node + || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node)) + return error_mark_node; + + if (processing_template_decl) + { + /* 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) + { + tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0); + if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM) + name = build_min_nt (BIT_NOT_EXPR, type); } - h1.code |= h2.code; - if (h2.distance > h1.distance) - h1.distance = h2.distance; + 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); - p1 = TYPE_ARG_TYPES (type); - p2 = TYPE_ARG_TYPES (parmtype); - while (p1 && TREE_VALUE (p1) != void_type_node - && p2 && TREE_VALUE (p2) != void_type_node) + /* get rid of unneeded argument */ + TREE_CHAIN (parms) = NULL_TREE; + if (build_method_call (instance, name, parms, basetype_path, + (LOOKUP_SPECULATIVELY|flags) & ~LOOKUP_COMPLAIN)) { - h2 = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2), - NULL_TREE); - if (h2.code & EVIL_CODE) - return h2; + /* 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 (h2.distance) + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + if (parms) + error ("destructors take no parameters"); + basetype = TREE_TYPE (instance); + if (TREE_CODE (basetype) == REFERENCE_TYPE) + basetype = TREE_TYPE (basetype); + + if (! check_dtor_name (basetype, name)) + cp_error + ("destructor name `~%T' does not match type `%T' of expression", + TREE_OPERAND (name, 0), basetype); + + if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype))) + return cp_convert (void_type_node, instance); + instance = default_conversion (instance); + instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); + return build_delete (build_pointer_type (basetype), + instance_ptr, integer_two_node, + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); + } + + return build_new_method_call (instance, name, parms, basetype_path, flags); +} + +/* New overloading code. */ + +struct z_candidate { + tree fn; + tree convs; + tree second_conv; + int viable; + tree basetype_path; + tree template; + tree warnings; + struct z_candidate *next; +}; + +#define IDENTITY_RANK 0 +#define EXACT_RANK 1 +#define PROMO_RANK 2 +#define STD_RANK 3 +#define PBOOL_RANK 4 +#define USER_RANK 5 +#define ELLIPSIS_RANK 6 +#define BAD_RANK 7 + +#define ICS_RANK(NODE) \ + (ICS_BAD_FLAG (NODE) ? BAD_RANK \ + : ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \ + : ICS_USER_FLAG (NODE) ? USER_RANK \ + : ICS_STD_RANK (NODE)) + +#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE) + +#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE) +#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) +#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE) +#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE) + +#define USER_CONV_CAND(NODE) \ + ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1))) +#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn) + +int +null_ptr_cst_p (t) + tree t; +{ + if (t == null_node + || (integer_zerop (t) && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)) + return 1; + return 0; +} + +static tree +build_conv (code, type, from) + enum tree_code code; + tree type, from; +{ + tree t = build1 (code, type, from); + int rank = ICS_STD_RANK (from); + switch (code) + { + case PTR_CONV: + case PMEM_CONV: + case BASE_CONV: + case STD_CONV: + if (rank < STD_RANK) + rank = STD_RANK; + break; + + case QUAL_CONV: + if (rank < EXACT_RANK) + rank = EXACT_RANK; + + default: + break; + } + ICS_STD_RANK (t) = rank; + ICS_USER_FLAG (t) = ICS_USER_FLAG (from); + ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from); + return t; +} + +static tree +non_reference (t) + tree t; +{ + if (TREE_CODE (t) == REFERENCE_TYPE) + t = TREE_TYPE (t); + return t; +} + +static tree +strip_top_quals (t) + tree t; +{ + if (TREE_CODE (t) == ARRAY_TYPE) + return t; + return TYPE_MAIN_VARIANT (t); +} + +/* Returns the standard conversion path (see [conv]) from type FROM to type + TO, if any. For proper handling of null pointer constants, you must + also pass the expression EXPR to convert from. */ + +static tree +standard_conversion (to, from, expr) + tree to, from, expr; +{ + enum tree_code fcode, tcode; + tree conv; + int fromref = 0; + + if (TREE_CODE (to) == REFERENCE_TYPE) + to = TREE_TYPE (to); + if (TREE_CODE (from) == REFERENCE_TYPE) + { + fromref = 1; + from = TREE_TYPE (from); + } + to = strip_top_quals (to); + from = strip_top_quals (from); + + fcode = TREE_CODE (from); + tcode = TREE_CODE (to); + + conv = build1 (IDENTITY_CONV, from, expr); + + if (fcode == FUNCTION_TYPE) + { + from = build_pointer_type (from); + fcode = TREE_CODE (from); + conv = build_conv (LVALUE_CONV, from, conv); + } + else if (fcode == ARRAY_TYPE) + { + from = build_pointer_type (TREE_TYPE (from)); + fcode = TREE_CODE (from); + conv = build_conv (LVALUE_CONV, from, conv); + } + else if (fromref || (expr && real_lvalue_p (expr))) + conv = build_conv (RVALUE_CONV, from, conv); + + if (from == to) + return conv; + + if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) + && expr && null_ptr_cst_p (expr)) + { + conv = build_conv (STD_CONV, to, conv); + } + else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) + { + 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)) + ; + 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)))); + conv = build_conv (PTR_CONV, from, conv); + } + else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) + { + tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); + 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))) { - /* This only works for pointers and references. */ - if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE - && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE) - return EVIL_RETURN (h); - h2.distance = - h2.distance; + from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); + from = build_pointer_type (from); + conv = build_conv (PMEM_CONV, from, conv); } - - h1.code |= h2.code; - if (h2.distance > h1.distance) - h1.distance = h2.distance; - p1 = TREE_CHAIN (p1); - p2 = TREE_CHAIN (p2); } - if (p1 == p2) - return h1; - if (p2) + else if (IS_AGGR_TYPE (TREE_TYPE (from)) + && IS_AGGR_TYPE (TREE_TYPE (to))) { - if (p1) - return EVIL_RETURN (h); - h1.code |= ELLIPSIS_CODE; - return h1; + 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 = build_pointer_type (from); + conv = build_conv (PTR_CONV, from, conv); + } } - if (p1) + + if (comptypes (from, to, 1)) + /* OK */; + else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from))) + conv = build_conv (QUAL_CONV, to, conv); + else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from))) { - if (TREE_PURPOSE (p1) == NULL_TREE) - h1.code |= EVIL_CODE; - return h1; + conv = build_conv (PTR_CONV, to, conv); + ICS_BAD_FLAG (conv) = 1; } + else + return 0; + + from = to; + } + else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from)) + { + tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from)); + tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to)); + tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn))); + tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn))); + + if (! DERIVED_FROM_P (fbase, tbase) + || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1) + || ! 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)) + return 0; + + from = cp_build_type_variant (tbase, TYPE_READONLY (fbase), + TYPE_VOLATILE (fbase)); + from = build_cplus_method_type (from, TREE_TYPE (fromfn), + TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); + from = build_ptrmemfunc_type (build_pointer_type (from)); + conv = build_conv (PMEM_CONV, from, conv); } - else if (codel == POINTER_TYPE && coder == OFFSET_TYPE) + else if (tcode == BOOLEAN_TYPE) { - tree ttl, ttr; + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE + || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) + return 0; + + conv = build_conv (STD_CONV, to, conv); + if (fcode == POINTER_TYPE + || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK)) + ICS_STD_RANK (conv) = PBOOL_RANK; + } + /* We don't check for ENUMERAL_TYPE here because there are no standard + conversions to enum type. */ + else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE + || tcode == REAL_TYPE) + { + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) + return 0; + conv = build_conv (STD_CONV, to, conv); + + /* Give this a better rank if it's a promotion. */ + if (to == type_promotes_to (from) + && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK) + ICS_STD_RANK (conv) = PROMO_RANK; + } + else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) + && DERIVED_FROM_P (to, from)) + { + if (TREE_CODE (conv) == RVALUE_CONV) + conv = TREE_OPERAND (conv, 0); + conv = build_conv (BASE_CONV, to, conv); + } + else + return 0; - /* Get to the OFFSET_TYPE that this might be. */ - type = TREE_TYPE (type); + return conv; +} + +/* Returns the conversion path from type FROM to reference type TO for + purposes of reference binding. For lvalue binding, either pass a + reference type to FROM or an lvalue expression to EXPR. + + Currently does not distinguish in the generated trees between binding to + an lvalue and a temporary. Should it? */ + +static tree +reference_binding (rto, rfrom, expr, flags) + tree rto, rfrom, expr; + int flags; +{ + tree conv; + int lvalue = 1; + tree to = TREE_TYPE (rto); + tree from = rfrom; + int related; + + if (TREE_CODE (from) == REFERENCE_TYPE) + from = TREE_TYPE (from); + else if (! expr || ! real_lvalue_p (expr)) + lvalue = 0; - if (coder != TREE_CODE (type)) - return EVIL_RETURN (h); + related = (comptypes (TYPE_MAIN_VARIANT (to), + TYPE_MAIN_VARIANT (from), 1) + || (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) + && DERIVED_FROM_P (to, from))); - ttl = TYPE_OFFSET_BASETYPE (type); - ttr = TYPE_OFFSET_BASETYPE (parmtype); + if (lvalue && related + && TYPE_READONLY (to) >= TYPE_READONLY (from) + && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from)) + { + conv = build1 (IDENTITY_CONV, from, expr); - if (ttl == ttr) - h.code = 0; + if (comptypes (TYPE_MAIN_VARIANT (to), + TYPE_MAIN_VARIANT (from), 1)) + conv = build_conv (REF_BIND, rto, conv); else { - int b_or_d = get_base_distance (ttr, ttl, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (ttl, ttr, 0, 0); - if (b_or_d < 0) - return EVIL_RETURN (h); - h.distance = -b_or_d; - } - else - h.distance = b_or_d; - h.code = STD_CODE; + conv = build_conv (REF_BIND, rto, conv); + ICS_STD_RANK (conv) = STD_RANK; } - - /* Now test the OFFSET_TYPE's target compatibility. */ - type = TREE_TYPE (type); - parmtype = TREE_TYPE (parmtype); - } - - if (coder == UNKNOWN_TYPE) - { - if (codel == FUNCTION_TYPE - || codel == METHOD_TYPE - || (codel == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))) - return TRIVIAL_RETURN (h); - return EVIL_RETURN (h); } + else + conv = NULL_TREE; - if (coder == VOID_TYPE) - return EVIL_RETURN (h); - - if (codel == BOOLEAN_TYPE) + if (! conv) { - if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE) - return STD_RETURN (h); - else if (coder == POINTER_TYPE || coder == OFFSET_TYPE) + conv = standard_conversion (to, rfrom, expr); + if (conv) { - /* Make this worse than any conversion to another pointer. - FIXME this is how I think the language should work, but it may not - end up being how the language is standardized (jason 1/30/95). */ - h.distance = 32767; - return STD_RETURN (h); + conv = build_conv (REF_BIND, rto, conv); + + /* Bind directly to a base subobject of a class rvalue. Do it + after building the conversion for proper handling of ICS_RANK. */ + if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) + TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); } - return EVIL_RETURN (h); + if (conv + && ((! (TYPE_READONLY (to) && ! TYPE_VOLATILE (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))))) + ICS_BAD_FLAG (conv) = 1; } - if (INTEGRAL_CODE_P (codel)) - { - /* Control equivalence of ints an enums. */ + return conv; +} - if (codel == ENUMERAL_TYPE - && flag_int_enum_equivalence == 0) - { - /* Enums can be converted to ints, but not vice-versa. */ - if (coder != ENUMERAL_TYPE - || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype)) - return EVIL_RETURN (h); - } +/* Returns the implicit conversion sequence (see [over.ics]) from type FROM + to type TO. The optional expression EXPR may affect the conversion. + FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is + significant. */ - /* else enums and ints (almost) freely interconvert. */ +static tree +implicit_conversion (to, from, expr, flags) + tree to, from, expr; + int flags; +{ + tree conv; + struct z_candidate *cand; - if (INTEGRAL_CODE_P (coder)) - { - if (TYPE_MAIN_VARIANT (type) - == TYPE_MAIN_VARIANT (type_promotes_to (parmtype))) - { - h.code = PROMO_CODE; -#if 0 /* What purpose does this serve? -jason */ - /* A char, short, wchar_t, etc., should promote to an int if - it can handle it, otherwise to an unsigned. So we'll make - an unsigned. */ - if (type != integer_type_node) - h.int_penalty = 1; -#endif - } - else - h.code = STD_CODE; - - return h; - } - else if (coder == REAL_TYPE) - { - h.code = STD_CODE; - h.distance = 0; - return h; - } + if (expr && type_unknown_p (expr)) + { + expr = instantiate_type (to, expr, 0); + if (expr == error_mark_node) + return 0; + from = TREE_TYPE (expr); } - if (codel == REAL_TYPE) + if (TREE_CODE (to) == REFERENCE_TYPE) + conv = reference_binding (to, from, expr, flags); + else + conv = standard_conversion (to, from, expr); + + if (conv) + ; + else if (expr != NULL_TREE + && (IS_AGGR_TYPE (non_reference (from)) + || IS_AGGR_TYPE (non_reference (to))) + && (flags & LOOKUP_NO_CONVERSION) == 0) { - if (coder == REAL_TYPE) - { - if (TYPE_MAIN_VARIANT (type) - == TYPE_MAIN_VARIANT (type_promotes_to (parmtype))) - h.code = PROMO_CODE; - else - h.code = STD_CODE; - - return h; - } - else if (INTEGRAL_CODE_P (coder)) + cand = build_user_type_conversion_1 + (to, expr, LOOKUP_ONLYCONVERTING); + if (cand) + conv = cand->second_conv; + if ((! conv || ICS_BAD_FLAG (conv)) + && TREE_CODE (to) == REFERENCE_TYPE + && (flags & LOOKUP_NO_TEMP_BIND) == 0) { - h.code = STD_CODE; - h.distance = 0; - return h; + cand = build_user_type_conversion_1 + (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING); + if (cand) + { + if (! TYPE_READONLY (TREE_TYPE (to)) + || TYPE_VOLATILE (TREE_TYPE (to))) + ICS_BAD_FLAG (cand->second_conv) = 1; + if (!conv || (ICS_BAD_FLAG (conv) + > ICS_BAD_FLAG (cand->second_conv))) + conv = build_conv (REF_BIND, to, cand->second_conv); + } } } - /* Convert arrays which have not previously been converted. */ -#if 0 - if (codel == ARRAY_TYPE) - codel = POINTER_TYPE; -#endif - if (coder == ARRAY_TYPE) + return conv; +} + +/* Add a new entry to the list of candidates. Used by the add_*_candidate + functions. */ + +static struct z_candidate * +add_candidate (candidates, fn, convs, viable) + struct z_candidate *candidates; + tree fn, convs; + int viable; +{ + struct z_candidate *cand + = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate)); + + cand->fn = fn; + cand->convs = convs; + cand->second_conv = NULL_TREE; + cand->viable = viable; + cand->basetype_path = NULL_TREE; + cand->template = NULL_TREE; + cand->warnings = NULL_TREE; + cand->next = candidates; + + return cand; +} + +/* Create an overload candidate for the function or method FN called with + the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on + to implicit_conversion. */ + +static struct z_candidate * +add_function_candidate (candidates, fn, arglist, flags) + struct z_candidate *candidates; + tree fn, arglist; + int flags; +{ + tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); + int i, len; + tree convs; + tree parmnode = parmlist; + tree argnode = arglist; + int viable = 1; + + /* The `this' and `in_chrg' arguments to constructors are not considered + in overload resolution. */ + if (DECL_CONSTRUCTOR_P (fn)) { - coder = POINTER_TYPE; - if (parm) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) { - parm = decay_conversion (parm); - parmtype = TREE_TYPE (parm); + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); } - else - parmtype = build_pointer_type (TREE_TYPE (parmtype)); } - /* Conversions among pointers */ - if (codel == POINTER_TYPE && coder == POINTER_TYPE) + len = list_length (argnode); + convs = make_scratch_vec (len); + + for (i = 0; i < len; ++i) { - register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)); - int penalty = 4 * (ttl != ttr); + tree arg = TREE_VALUE (argnode); + tree argtype = TREE_TYPE (arg); + tree t; - /* Anything converts to void *. Since this may be `const void *' - (etc.) use VOID_TYPE instead of void_type_node. Otherwise, the - targets must be the same, except that we do allow (at some cost) - conversion between signed and unsigned pointer types. */ + /* 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 ((TREE_CODE (ttl) == METHOD_TYPE - || TREE_CODE (ttl) == FUNCTION_TYPE) - && TREE_CODE (ttl) == TREE_CODE (ttr)) + if (parmnode == void_list_node) + break; + else if (parmnode) + t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); + else { - if (comptypes (ttl, ttr, -1)) - { - h.code = penalty ? STD_CODE : 0; - h.distance = 0; - } - else - h.code = EVIL_CODE; - return h; + t = build1 (IDENTITY_CONV, argtype, arg); + ICS_ELLIPSIS_FLAG (t) = 1; } -#if 1 - if (TREE_CODE (ttl) != VOID_TYPE - && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm))) - { - if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr)) - { - ttl = unsigned_type (ttl); - ttr = unsigned_type (ttr); - penalty = 10; - } - if (comp_target_types (type, parmtype, 1) <= 0) - return EVIL_RETURN (h); - } -#else - if (!(TREE_CODE (ttl) == VOID_TYPE - || TREE_CODE (ttr) == VOID_TYPE - || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr) - && (ttl = unsigned_type (ttl), - ttr = unsigned_type (ttr), - penalty = 10, 0)) - || (comp_target_types (ttl, ttr, 0) > 0))) - return EVIL_RETURN (h); -#endif - - if (penalty == 10 || ttr == ttl) - { - tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype); + if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE + && ! DECL_CONSTRUCTOR_P (fn)) + ICS_THIS_FLAG (t) = 1; - /* If one was unsigned but the other wasn't, then we need to - do a standard conversion from T to unsigned T. */ - if (penalty == 10) - h.code = PROMO_CODE; /* was STD_CODE */ - else - h.code = 0; + TREE_VEC_ELT (convs, i) = t; + if (! t) + break; - /* Note conversion from `T*' to `const T*', - or `T*' to `volatile T*'. */ - if (ttl == ttr - && ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2)) - || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))) - h.code |= QUAL_CODE; + if (ICS_BAD_FLAG (t)) + viable = -1; - h.distance = 0; - return h; - } + if (parmnode) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + } + if (i < len) + viable = 0; - if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE) - { - int b_or_d = get_base_distance (ttl, ttr, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (ttr, ttl, 0, 0); - if (b_or_d < 0) - return EVIL_RETURN (h); - h.distance = -b_or_d; - } - else - h.distance = b_or_d; - h.code = STD_CODE; - return h; - } + /* 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; + } - /* If converting from a `class*' to a `void*', make it - less favorable than any inheritance relationship. */ - if (TREE_CODE (ttl) == VOID_TYPE && IS_AGGR_TYPE (ttr)) - { - h.code = STD_CODE; - h.distance = CLASSTYPE_MAX_DEPTH (ttr)+1; - return h; - } + return add_candidate (candidates, fn, convs, viable); +} - h.code = penalty ? STD_CODE : PROMO_CODE; - /* Catch things like `const char *' -> `const void *' - vs `const char *' -> `void *'. */ - if (ttl != ttr) - { - tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype); - if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2)) - || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))) - h.code |= QUAL_CODE; - } - return h; - } +/* 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. */ - if (codel == POINTER_TYPE && coder == INTEGER_TYPE) +static struct z_candidate * +add_conv_candidate (candidates, fn, obj, arglist) + struct z_candidate *candidates; + tree fn, obj, arglist; +{ + tree totype = TREE_TYPE (TREE_TYPE (fn)); + tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); + int i, len = list_length (arglist) + 1; + tree convs = make_scratch_vec (len); + tree parmnode = parmlist; + tree argnode = arglist; + int viable = 1; + int flags = LOOKUP_NORMAL; + + for (i = 0; i < len; ++i) { - /* This is not a bad match, but don't let it beat - integer-enum combinations. */ - if (parm && integer_zerop (parm)) + tree arg = i == 0 ? obj : TREE_VALUE (argnode); + tree argtype = lvalue_type (arg); + tree t; + + if (i == 0) + t = implicit_conversion (totype, argtype, arg, flags); + else if (parmnode == void_list_node) + break; + else if (parmnode) + t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); + else { - h.code = STD_CODE; - h.distance = 0; - return h; + t = build1 (IDENTITY_CONV, argtype, arg); + ICS_ELLIPSIS_FLAG (t) = 1; } - } - /* C++: Since the `this' parameter of a signature member function - is represented as a signature pointer to handle default implementations - correctly, we can have the case that `type' is a signature pointer - while `parmtype' is a pointer to a signature table. We don't really - do any conversions in this case, so just return 0. */ + TREE_VEC_ELT (convs, i) = t; + if (! t) + break; - if (codel == RECORD_TYPE && coder == POINTER_TYPE - && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype))) - return ZERO_RETURN (h); + if (ICS_BAD_FLAG (t)) + viable = -1; - if (codel == RECORD_TYPE && coder == RECORD_TYPE) - { - int b_or_d = get_base_distance (type, parmtype, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (parmtype, type, 0, 0); - if (b_or_d < 0) - return EVIL_RETURN (h); - h.distance = -b_or_d; - } - else - h.distance = b_or_d; - h.code = STD_CODE; - return h; + if (i == 0) + continue; + + if (parmnode) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); } - return EVIL_RETURN (h); + + if (i < len) + viable = 0; + + for (; parmnode && parmnode != void_list_node; + parmnode = TREE_CHAIN (parmnode)) + if (! TREE_PURPOSE (parmnode)) + { + viable = 0; + break; + } + + return add_candidate (candidates, fn, convs, viable); } -/* A clone of build_type_conversion for checking user-defined conversions in - overload resolution. */ +static struct z_candidate * +build_builtin_candidate (candidates, fnname, type1, type2, + args, argtypes, flags) + struct z_candidate *candidates; + tree fnname, type1, type2, *args, *argtypes; + int flags; -int -user_harshness (type, parmtype, parm) - register tree type, parmtype; - tree parm; { - tree conv; - tree winner = NULL_TREE; - int code; + tree t, convs; + int viable = 1, i; + tree types[2]; - { - tree typename = build_typename_overload (type); - if (lookup_fnfields (TYPE_BINFO (parmtype), typename, 0)) - return 0; - } - - for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv)) - { - struct harshness_code tmp; + types[0] = type1; + types[1] = type2; - if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) - continue; + convs = make_scratch_vec (args[2] ? 3 : (args[1] ? 2 : 1)); - if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE), - tmp.code < USER_CODE && tmp.distance >= 0) + for (i = 0; i < 2; ++i) + { + if (! args[i]) + break; + + t = implicit_conversion (types[i], argtypes[i], args[i], flags); + if (! t) { - if (winner) - return EVIL_CODE; - else - { - winner = conv; - code = tmp.code; - } + viable = 0; + /* We need something for printing the candidate. */ + t = build1 (IDENTITY_CONV, types[i], NULL_TREE); } + else if (ICS_BAD_FLAG (t)) + viable = 0; + TREE_VEC_ELT (convs, i) = t; } - if (winner) - return code; - - return -1; -} - -int -can_convert (to, from) - tree to, from; -{ - struct harshness_code h; - h = convert_harshness (to, from, NULL_TREE); - return h.code < USER_CODE && h.distance >= 0; -} + /* For COND_EXPR we rearranged the arguments; undo that now. */ + if (args[2]) + { + TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1); + TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0); + t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); + if (t) + TREE_VEC_ELT (convs, 0) = t; + else + viable = 0; + } -int -can_convert_arg (to, from, arg) - tree to, from, arg; -{ - struct harshness_code h; - h = convert_harshness (to, from, arg); - return h.code < USER_CODE && h.distance >= 0; + return add_candidate (candidates, fnname, convs, viable); } -#ifdef DEBUG_MATCHING -static char * -print_harshness (h) - struct harshness_code *h; +static int +is_complete (t) + tree t; { - static char buf[1024]; - char tmp[1024]; - - bzero (buf, 1024 * sizeof (char)); - strcat (buf, "codes=["); - if (h->code & EVIL_CODE) - strcat (buf, "EVIL"); - if (h->code & CONST_CODE) - strcat (buf, " CONST"); - if (h->code & ELLIPSIS_CODE) - strcat (buf, " ELLIPSIS"); - if (h->code & USER_CODE) - strcat (buf, " USER"); - if (h->code & STD_CODE) - strcat (buf, " STD"); - if (h->code & PROMO_CODE) - strcat (buf, " PROMO"); - if (h->code & QUAL_CODE) - strcat (buf, " QUAL"); - if (h->code & TRIVIAL_CODE) - strcat (buf, " TRIVIAL"); - if (buf[0] == '\0') - strcat (buf, "0"); - - sprintf (tmp, "] distance=%d int_penalty=%d", h->distance, h->int_penalty); - - strcat (buf, tmp); - - return buf; + return TYPE_SIZE (complete_type (t)) != NULL_TREE; } -#endif - -/* Algorithm: For each argument, calculate how difficult it is to - make FUNCTION accept that argument. If we can easily tell that - FUNCTION won't be acceptable to one of the arguments, then we - don't need to compute the ease of converting the other arguments, - since it will never show up in the intersection of all arguments' - favorite functions. - Conversions between builtin and user-defined types are allowed, but - no function involving such a conversion is preferred to one which - does not require such a conversion. Furthermore, such conversions - must be unique. */ - -void -compute_conversion_costs (function, tta_in, cp, arglen) - tree function; - tree tta_in; - struct candidate *cp; - int arglen; +/* Create any builtin operator overload candidates for the operator in + question given the converted operand types TYPE1 and TYPE2. The other + args are passed through from add_builtin_candidates to + build_builtin_candidate. */ + +static struct z_candidate * +add_builtin_candidate (candidates, code, code2, fnname, type1, type2, + args, argtypes, flags) + struct z_candidate *candidates; + enum tree_code code, code2; + tree fnname, type1, type2, *args, *argtypes; + int flags; { - tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function)); - tree ttf = ttf_in; - tree tta = tta_in; - - /* Start out with no strikes against. */ - int evil_strikes = 0; - int ellipsis_strikes = 0; - int user_strikes = 0; - int b_or_d_strikes = 0; - int easy_strikes = 0; - - int strike_index = 0, win; - struct harshness_code lose; - extern int cp_silent; + switch (code) + { + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + args[1] = integer_zero_node; + type2 = integer_type_node; + break; + default: + break; + } -#ifdef GATHER_STATISTICS - n_compute_conversion_costs++; -#endif + switch (code) + { -#ifndef DEBUG_MATCHING - /* We don't emit any warnings or errors while trying out each candidate. */ - cp_silent = 1; -#endif +/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, + and VQ is either volatile or empty, there exist candidate operator + functions of the form + VQ T& operator++(VQ T&); + T operator++(VQ T&, int); + 5 For every pair T, VQ), where T is an enumeration type or an arithmetic + type other than bool, and VQ is either volatile or empty, there exist + candidate operator functions of the form + VQ T& operator--(VQ T&); + T operator--(VQ T&, int); + 6 For every pair T, VQ), where T is a cv-qualified or cv-unqualified + complete object type, and VQ is either volatile or empty, there exist + candidate operator functions of the form + T*VQ& operator++(T*VQ&); + T*VQ& operator--(T*VQ&); + T* operator++(T*VQ&, int); + T* operator--(T*VQ&, int); */ + + case POSTDECREMENT_EXPR: + case PREDECREMENT_EXPR: + if (TREE_CODE (type1) == BOOLEAN_TYPE) + return candidates; + case POSTINCREMENT_EXPR: + case PREINCREMENT_EXPR: + if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE) + || TYPE_PTROB_P (type1)) + { + type1 = build_reference_type (type1); + break; + } + return candidates; - cp->function = function; - cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE; - cp->u.bad_arg = 0; /* optimistic! */ +/* 7 For every cv-qualified or cv-unqualified complete object type T, there + exist candidate operator functions of the form - cp->h.code = 0; - cp->h.distance = 0; - cp->h.int_penalty = 0; - bzero ((char *) cp->harshness, - (cp->h_len + 1) * sizeof (struct harshness_code)); + T& operator*(T*); - while (ttf && tta) - { - struct harshness_code h; + 8 For every function type T, there exist candidate operator functions of + the form + T& operator*(T*); */ - if (ttf == void_list_node) + case INDIRECT_REF: + if (TREE_CODE (type1) == POINTER_TYPE + && (TYPE_PTROB_P (type1) + || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)) break; + return candidates; - if (type_unknown_p (TREE_VALUE (tta))) - { - /* Must perform some instantiation here. */ - tree rhs = TREE_VALUE (tta); - tree lhstype = TREE_VALUE (ttf); +/* 9 For every type T, there exist candidate operator functions of the form + T* operator+(T*); - /* Keep quiet about possible contravariance violations. */ - int old_inhibit_warnings = inhibit_warnings; - inhibit_warnings = 1; + 10For every promoted arithmetic type T, there exist candidate operator + functions of the form + T operator+(T); + T operator-(T); */ - /* @@ This is to undo what `grokdeclarator' does to - parameter types. It really should go through - something more general. */ + case CONVERT_EXPR: /* unary + */ + if (TREE_CODE (type1) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE) + break; + case NEGATE_EXPR: + if (ARITHMETIC_TYPE_P (type1)) + break; + return candidates; - TREE_TYPE (tta) = unknown_type_node; - rhs = instantiate_type (lhstype, rhs, 0); - inhibit_warnings = old_inhibit_warnings; +/* 11For every promoted integral type T, there exist candidate operator + functions of the form + T operator~(T); */ - if (TREE_CODE (rhs) == ERROR_MARK) - h.code = EVIL_CODE; - else - h = convert_harshness (lhstype, TREE_TYPE (rhs), rhs); + case BIT_NOT_EXPR: + if (INTEGRAL_TYPE_P (type1)) + break; + return candidates; + +/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1 + is the same type as C2 or is a derived class of C2, T is a complete + object type or a function type, and CV1 and CV2 are cv-qualifier-seqs, + there exist candidate operator functions of the form + CV12 T& operator->*(CV1 C1*, CV2 T C2::*); + where CV12 is the union of CV1 and CV2. */ + + case MEMBER_REF: + if (TREE_CODE (type1) == POINTER_TYPE + && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))) + { + tree c1 = TREE_TYPE (type1); + tree c2 = (TYPE_PTRMEMFUNC_P (type2) + ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2))) + : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2))); + + if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1) + && (TYPE_PTRMEMFUNC_P (type2) + || is_complete (TREE_TYPE (TREE_TYPE (type2))))) + break; } - else + return candidates; + +/* 13For every pair of promoted arithmetic types L and R, there exist can- + didate operator functions of the form + LR operator*(L, R); + LR operator/(L, R); + LR operator+(L, R); + LR operator-(L, R); + bool operator<(L, R); + bool operator>(L, R); + bool operator<=(L, R); + bool operator>=(L, R); + bool operator==(L, R); + bool operator!=(L, R); + where LR is the result of the usual arithmetic conversions between + types L and R. + + 14For every pair of types T and I, where T is a cv-qualified or cv- + unqualified complete object type and I is a promoted integral type, + there exist candidate operator functions of the form + T* operator+(T*, I); + T& operator[](T*, I); + T* operator-(T*, I); + T* operator+(I, T*); + T& operator[](I, T*); + + 15For every T, where T is a pointer to complete object type, there exist + candidate operator functions of the form112) + ptrdiff_t operator-(T, T); + + 16For every pointer type T, there exist candidate operator functions of + the form + bool operator<(T, T); + bool operator>(T, T); + bool operator<=(T, T); + bool operator>=(T, T); + bool operator==(T, T); + bool operator!=(T, T); + + 17For every pointer to member type T, there exist candidate operator + functions of the form + bool operator==(T, T); + bool operator!=(T, T); */ + + case MINUS_EXPR: + if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2)) + break; + if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2)) { -#ifdef DEBUG_MATCHING - static tree old_function = NULL_TREE; - - if (!old_function || function != old_function) - { - cp_error ("trying %D", function); - old_function = function; - } - - cp_error (" doing (%T) %E against arg %T", - TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta), - TREE_VALUE (ttf)); -#endif - - h = convert_harshness (TREE_VALUE (ttf), - TREE_TYPE (TREE_VALUE (tta)), - TREE_VALUE (tta)); - -#ifdef DEBUG_MATCHING - cp_error (" evaluated %s", print_harshness (&h)); -#endif + type2 = ptrdiff_type_node; + break; } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + return candidates; - cp->harshness[strike_index] = h; - if ((h.code & EVIL_CODE) - || ((h.code & STD_CODE) && h.distance < 0)) + case EQ_EXPR: + case NE_EXPR: + if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) + || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))) + break; + if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1)) + && null_ptr_cst_p (args[1])) { - cp->u.bad_arg = strike_index; - evil_strikes = 1; + type2 = type1; + break; } - else if (h.code & ELLIPSIS_CODE) - ellipsis_strikes += 1; -#if 0 - /* This is never set by `convert_harshness'. */ - else if (h.code & USER_CODE) + if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)) + && null_ptr_cst_p (args[0])) { - user_strikes += 1; + type1 = type2; + break; } -#endif - else + case LT_EXPR: + case GT_EXPR: + case LE_EXPR: + case GE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + if ((ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))) + break; + if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1])) { - if ((h.code & STD_CODE) && h.distance) - { - if (h.distance > b_or_d_strikes) - b_or_d_strikes = h.distance; - } - else - easy_strikes += (h.code & (STD_CODE|PROMO_CODE|TRIVIAL_CODE)); - cp->h.code |= h.code; - /* Make sure we communicate this. */ - cp->h.int_penalty += h.int_penalty; + type2 = type1; + break; } - - ttf = TREE_CHAIN (ttf); - tta = TREE_CHAIN (tta); - strike_index += 1; - } - - if (tta) - { - /* ran out of formals, and parmlist is fixed size. */ - if (ttf /* == void_type_node */) + if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2)) { - cp->h.code = EVIL_CODE; - cp->u.bad_arg = -1; - cp_silent = 0; - return; + type1 = type2; + break; } - else + return candidates; + + case PLUS_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + case ARRAY_REF: + if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2)) { - struct harshness_code h; - int l = list_length (tta); - ellipsis_strikes += l; - h.code = ELLIPSIS_CODE; - h.distance = 0; - h.int_penalty = 0; - for (; l; --l) - cp->harshness[strike_index++] = h; + type1 = ptrdiff_type_node; + break; } - } - else if (ttf && ttf != void_list_node) - { - /* ran out of actuals, and no defaults. */ - if (TREE_PURPOSE (ttf) == NULL_TREE) + if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2)) { - cp->h.code = EVIL_CODE; - cp->u.bad_arg = -2; - cp_silent = 0; - return; + type2 = ptrdiff_type_node; + break; } - /* Store index of first default. */ - cp->harshness[arglen].distance = strike_index+1; - } - else - cp->harshness[arglen].distance = 0; - - /* Argument list lengths work out, so don't need to check them again. */ - if (evil_strikes) - { - /* We do not check for derived->base conversions here, since in - no case would they give evil strike counts, unless such conversions - are somehow ambiguous. */ + return candidates; + +/* 18For every pair of promoted integral types L and R, there exist candi- + date operator functions of the form + LR operator%(L, R); + LR operator&(L, R); + LR operator^(L, R); + LR operator|(L, R); + L operator<<(L, R); + L operator>>(L, R); + where LR is the result of the usual arithmetic conversions between + types L and R. */ + + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) + break; + return candidates; + +/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration + type, VQ is either volatile or empty, and R is a promoted arithmetic + type, there exist candidate operator functions of the form + VQ L& operator=(VQ L&, R); + VQ L& operator*=(VQ L&, R); + VQ L& operator/=(VQ L&, R); + VQ L& operator+=(VQ L&, R); + VQ L& operator-=(VQ L&, R); + + 20For every pair T, VQ), where T is any type and VQ is either volatile + or empty, there exist candidate operator functions of the form + T*VQ& operator=(T*VQ&, T*); + + 21For every pair T, VQ), where T is a pointer to member type and VQ is + either volatile or empty, there exist candidate operator functions of + the form + VQ T& operator=(VQ T&, T); + + 22For every triple T, VQ, I), where T is a cv-qualified or cv- + unqualified complete object type, VQ is either volatile or empty, and + I is a promoted integral type, there exist candidate operator func- + tions of the form + T*VQ& operator+=(T*VQ&, I); + T*VQ& operator-=(T*VQ&, I); + + 23For every triple L, VQ, R), where L is an integral or enumeration + type, VQ is either volatile or empty, and R is a promoted integral + type, there exist candidate operator functions of the form + + VQ L& operator%=(VQ L&, R); + VQ L& operator<<=(VQ L&, R); + VQ L& operator>>=(VQ L&, R); + VQ L& operator&=(VQ L&, R); + VQ L& operator^=(VQ L&, R); + VQ L& operator|=(VQ L&, R); */ + + case MODIFY_EXPR: + switch (code2) + { + case PLUS_EXPR: + case MINUS_EXPR: + if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + return candidates; + + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) + break; + return candidates; - /* See if any user-defined conversions apply. - But make sure that we do not loop. */ - static int dont_convert_types = 0; + case NOP_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) + || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) + || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) + || ((TYPE_PTRMEMFUNC_P (type1) + || TREE_CODE (type1) == POINTER_TYPE) + && null_ptr_cst_p (args[1]))) + { + type2 = type1; + break; + } + return candidates; - if (dont_convert_types) + default: + my_friendly_abort (367); + } + type1 = build_reference_type (type1); + break; + + case COND_EXPR: + /* Kludge around broken overloading rules whereby + bool ? const char& : enum is ambiguous + (between int and const char&). */ + flags |= LOOKUP_NO_TEMP_BIND; + + /* Extension: Support ?: of enumeral type. Hopefully this will not + be an extension for long. */ + if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2) + break; + else if (TREE_CODE (type1) == ENUMERAL_TYPE + || TREE_CODE (type2) == ENUMERAL_TYPE) + return candidates; + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + if (TREE_CODE (type1) == TREE_CODE (type2) + && (TREE_CODE (type1) == REFERENCE_TYPE + || TREE_CODE (type1) == POINTER_TYPE + || TYPE_PTRMEMFUNC_P (type1) + || IS_AGGR_TYPE (type1))) + break; + if (TREE_CODE (type1) == REFERENCE_TYPE + || TREE_CODE (type2) == REFERENCE_TYPE) + return candidates; + if (((TYPE_PTRMEMFUNC_P (type1) || TREE_CODE (type1) == POINTER_TYPE) + && null_ptr_cst_p (args[1])) + || IS_AGGR_TYPE (type1)) { - cp->h.code = EVIL_CODE; - cp_silent = 0; - return; + type2 = type1; + break; } - - win = 0; /* Only get one chance to win. */ - ttf = TYPE_ARG_TYPES (TREE_TYPE (function)); - tta = tta_in; - strike_index = 0; - evil_strikes = 0; - - while (ttf && tta) + if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE) + && null_ptr_cst_p (args[0])) + || IS_AGGR_TYPE (type2)) { - if (ttf == void_list_node) - break; + type1 = type2; + break; + } + return candidates; - lose = cp->harshness[strike_index]; - if ((lose.code & EVIL_CODE) - || ((lose.code & STD_CODE) && lose.distance < 0)) - { - tree actual_type = TREE_TYPE (TREE_VALUE (tta)); - tree formal_type = TREE_VALUE (ttf); - int extra_conversions = 0; + default: + my_friendly_abort (367); + } - dont_convert_types = 1; + /* If we're dealing with two pointer types, we need candidates + for both of them. */ + if (type2 && type1 != type2 + && TREE_CODE (type1) == TREE_CODE (type2) + && (TREE_CODE (type1) == REFERENCE_TYPE + || (TREE_CODE (type1) == POINTER_TYPE + && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2)) + || TYPE_PTRMEMFUNC_P (type1) + || IS_AGGR_TYPE (type1))) + { + candidates = build_builtin_candidate + (candidates, fnname, type1, type1, args, argtypes, flags); + return build_builtin_candidate + (candidates, fnname, type2, type2, args, argtypes, flags); + } - if (TREE_CODE (formal_type) == REFERENCE_TYPE) - formal_type = TREE_TYPE (formal_type); - if (TREE_CODE (actual_type) == REFERENCE_TYPE) - actual_type = TREE_TYPE (actual_type); + return build_builtin_candidate + (candidates, fnname, type1, type2, args, argtypes, flags); +} - if (formal_type != error_mark_node - && actual_type != error_mark_node) - { - formal_type = TYPE_MAIN_VARIANT (formal_type); - actual_type = TYPE_MAIN_VARIANT (actual_type); - - if (TYPE_HAS_CONSTRUCTOR (formal_type)) - { - /* If it has a constructor for this type, - try to use it. */ - /* @@ There is no way to save this result yet, so - success is a NULL_TREE for now. */ - if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1) - != error_mark_node) - win++; - } - if (TYPE_LANG_SPECIFIC (actual_type) - && TYPE_HAS_CONVERSION (actual_type)) - { - int extra = user_harshness (formal_type, actual_type); - - if (extra == EVIL_CODE) - win += 2; - else if (extra >= 0) - { - win++; - extra_conversions = extra; - } - } - } - dont_convert_types = 0; +tree +type_decays_to (type) + tree type; +{ + if (TREE_CODE (type) == ARRAY_TYPE) + return build_pointer_type (TREE_TYPE (type)); + if (TREE_CODE (type) == FUNCTION_TYPE) + return build_pointer_type (type); + return type; +} - if (win == 1) - { - user_strikes += 1; - cp->harshness[strike_index].code - = USER_CODE | (extra_conversions ? STD_CODE : 0); - win = 0; - } - else - { - if (cp->u.bad_arg > strike_index) - cp->u.bad_arg = strike_index; +/* There are three conditions of builtin candidates: - evil_strikes = win ? 2 : 1; - break; - } - } + 1) bool-taking candidates. These are the same regardless of the input. + 2) pointer-pair taking candidates. These are generated for each type + one of the input types converts to. + 3) arithmetic candidates. According to the WP, we should generate + all of these, but I'm trying not to... */ - ttf = TREE_CHAIN (ttf); - tta = TREE_CHAIN (tta); - strike_index += 1; - } +static struct z_candidate * +add_builtin_candidates (candidates, code, code2, fnname, args, flags) + struct z_candidate *candidates; + enum tree_code code, code2; + tree fnname, *args; + int flags; +{ + int ref1, i; + tree type, argtypes[3], types[2]; + + for (i = 0; i < 3; ++i) + { + if (args[i]) + argtypes[i] = lvalue_type (args[i]); + else + argtypes[i] = NULL_TREE; } - /* Const member functions get a small penalty because defaulting - to const is less useful than defaulting to non-const. */ - /* This is bogus, it does not correspond to anything in the ARM. - This code will be fixed when this entire section is rewritten - to conform to the ARM. (mrs) */ - if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) + switch (code) { - tree this_parm = TREE_VALUE (ttf_in); +/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, + and VQ is either volatile or empty, there exist candidate operator + functions of the form + VQ T& operator++(VQ T&); */ + + case POSTINCREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case PREDECREMENT_EXPR: + case MODIFY_EXPR: + ref1 = 1; + break; + +/* 24There also exist candidate operator functions of the form + bool operator!(bool); + bool operator&&(bool, bool); + bool operator||(bool, bool); */ + + case TRUTH_NOT_EXPR: + return build_builtin_candidate + (candidates, fnname, boolean_type_node, + NULL_TREE, args, argtypes, flags); + + case TRUTH_ORIF_EXPR: + case TRUTH_ANDIF_EXPR: + return build_builtin_candidate + (candidates, fnname, boolean_type_node, + boolean_type_node, args, argtypes, flags); + + case ADDR_EXPR: + case COMPOUND_EXPR: + case COMPONENT_REF: + return candidates; + + default: + ref1 = 0; + } - if (TREE_CODE (this_parm) == RECORD_TYPE /* Is `this' a sig ptr? */ - ? TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (this_parm)))) - : TYPE_READONLY (TREE_TYPE (this_parm))) - { - cp->harshness[0].code |= TRIVIAL_CODE; - ++easy_strikes; - } - else + types[0] = types[1] = NULL_TREE; + + for (i = 0; i < 2; ++i) + { + if (! args[i]) + ; + else if (IS_AGGR_TYPE (argtypes[i])) { - /* Calling a non-const member function from a const member function - is probably invalid, but for now we let it only draw a warning. - We indicate that such a mismatch has occurred by setting the - harshness to a maximum value. */ - if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE - && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in)))))) - cp->harshness[0].code |= CONST_CODE; - } - } - - if (evil_strikes) - cp->h.code = EVIL_CODE; - if (ellipsis_strikes) - cp->h.code |= ELLIPSIS_CODE; - if (user_strikes) - cp->h.code |= USER_CODE; - cp_silent = 0; -#ifdef DEBUG_MATCHING - cp_error ("final eval %s", print_harshness (&cp->h)); -#endif -} + tree convs = lookup_conversions (argtypes[i]); -/* Subroutine of ideal_candidate. See if X or Y is a better match - than the other. */ -static int -strictly_better (x, y) - unsigned short x, y; -{ - unsigned short xor; + if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR) + return candidates; - if (x == y) - return 0; + convs = lookup_conversions (argtypes[i]); - xor = x ^ y; - if (xor >= x || xor >= y) - return 1; - return 0; -} + if (code == COND_EXPR) + { + if (real_lvalue_p (args[i])) + types[i] = scratch_tree_cons + (NULL_TREE, build_reference_type (argtypes[i]), types[i]); -/* When one of several possible overloaded functions and/or methods - can be called, choose the best candidate for overloading. - - BASETYPE is the context from which we start method resolution - or NULL if we are comparing overloaded functions. - CANDIDATES is the array of candidates we have to choose from. - N_CANDIDATES is the length of CANDIDATES. - PARMS is a TREE_LIST of parameters to the function we'll ultimately - choose. It is modified in place when resolving methods. It is not - modified in place when resolving overloaded functions. - LEN is the length of the parameter list. */ - -static struct candidate * -ideal_candidate (basetype, candidates, n_candidates, parms, len) - tree basetype; - struct candidate *candidates; - int n_candidates; - tree parms; - int len; -{ - struct candidate *cp = candidates+n_candidates; - int i, j = -1, best_code; + types[i] = scratch_tree_cons + (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]); + } - /* For each argument, sort the functions from best to worst for the arg. - For each function that's not best for this arg, set its overall - harshness to EVIL so that other args won't like it. The candidate - list for the last argument is the intersection of all the best-liked - functions. */ + else if (! convs) + return candidates; -#if 0 - for (i = 0; i < len; i++) - { - qsort (candidates, n_candidates, sizeof (struct candidate), - rank_for_overload); - best_code = cp[-1].h.code; - - /* To find out functions that are worse than that represented - by BEST_CODE, we can't just do a comparison like h.code>best_code. - The total harshness for the "best" fn may be 8|8 for two args, and - the harshness for the next-best may be 8|2. If we just compared, - that would be checking 8>10, which would lead to the next-best - being disqualified. What we actually want to do is get rid - of functions that are definitely worse than that represented - by best_code, i.e. those which have bits set higher than the - highest in best_code. Sooooo, what we do is clear out everything - represented by best_code, and see if we still come up with something - higher. If so (e.g., 8|8 vs 8|16), it'll disqualify it properly. */ - for (j = n_candidates-2; j >= 0; j--) - if ((candidates[j].h.code & ~best_code) > best_code) - candidates[j].h.code = EVIL_CODE; - } - - if (cp[-1].h.code & EVIL_CODE) - return NULL; -#else - qsort (candidates, n_candidates, sizeof (struct candidate), - rank_for_overload); - best_code = cp[-1].h.code; -#endif + for (; convs; convs = TREE_CHAIN (convs)) + { + type = TREE_TYPE (TREE_TYPE (TREE_VALUE (convs))); + + if (i == 0 && ref1 + && (TREE_CODE (type) != REFERENCE_TYPE + || TYPE_READONLY (TREE_TYPE (type)))) + continue; - /* If they're at least as good as each other, do an arg-by-arg check. */ - if (! strictly_better (cp[-1].h.code, cp[-2].h.code)) - { - int better = 0; - int worse = 0; + if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); - for (j = 0; j < n_candidates; j++) - if (! strictly_better (candidates[j].h.code, best_code)) - break; + type = non_reference (type); + if (i != 0 || ! ref1) + { + type = TYPE_MAIN_VARIANT (type_decays_to (type)); + if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + if (INTEGRAL_TYPE_P (type)) + type = type_promotes_to (type); + } - qsort (candidates+j, n_candidates-j, sizeof (struct candidate), - rank_for_ideal); - for (i = 0; i < len; i++) - { - if (cp[-1].harshness[i].code < cp[-2].harshness[i].code) - better = 1; - else if (cp[-1].harshness[i].code > cp[-2].harshness[i].code) - worse = 1; - else if (cp[-1].harshness[i].code & STD_CODE) - { - /* If it involves a standard conversion, let the - inheritance lattice be the final arbiter. */ - if (cp[-1].harshness[i].distance > cp[-2].harshness[i].distance) - worse = 1; - else if (cp[-1].harshness[i].distance < cp[-2].harshness[i].distance) - better = 1; + if (! value_member (type, types[i])) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); } - else if (cp[-1].harshness[i].code & PROMO_CODE) + } + else + { + if (code == COND_EXPR && real_lvalue_p (args[i])) + types[i] = scratch_tree_cons + (NULL_TREE, build_reference_type (argtypes[i]), types[i]); + type = non_reference (argtypes[i]); + if (i != 0 || ! ref1) { - /* For integral promotions, take into account a finer - granularity for determining which types should be favored - over others in such promotions. */ - if (cp[-1].harshness[i].int_penalty > cp[-2].harshness[i].int_penalty) - worse = 1; - else if (cp[-1].harshness[i].int_penalty < cp[-2].harshness[i].int_penalty) - better = 1; + type = TYPE_MAIN_VARIANT (type_decays_to (type)); + if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + if (INTEGRAL_TYPE_P (type)) + type = type_promotes_to (type); } + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); } + } - if (! better || worse) - return NULL; + for (; types[0]; types[0] = TREE_CHAIN (types[0])) + { + if (types[1]) + for (type = types[1]; type; type = TREE_CHAIN (type)) + candidates = add_builtin_candidate + (candidates, code, code2, fnname, TREE_VALUE (types[0]), + TREE_VALUE (type), args, argtypes, flags); + else + candidates = add_builtin_candidate + (candidates, code, code2, fnname, TREE_VALUE (types[0]), + NULL_TREE, args, argtypes, flags); } - return cp-1; -} -/* Assume that if the class referred to is not in the - current class hierarchy, that it may be remote. - PARENT is assumed to be of aggregate type here. */ -static int -may_be_remote (parent) - tree parent; -{ - if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0) - return 0; + return candidates; +} - if (current_class_type == NULL_TREE) - return 0; - if (parent == current_class_type) - return 0; +/* If TMPL can be successfully instantiated as indicated by + EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES. - if (UNIQUELY_DERIVED_FROM_P (parent, current_class_type)) - return 0; - return 1; -} + TMPL is the template. EXPLICIT_TARGS are any explicit template + arguments. ARGLIST is the arguments provided at the call-site. + The RETURN_TYPE is the desired type for conversion operators. If + OBJ is NULL_TREE, FLAGS are as for add_function_candidate. If an + OBJ is supplied, FLAGS are ignored, and OBJ is as for + add_conv_candidate. */ -tree -build_vfield_ref (datum, type) - tree datum, type; +static struct z_candidate* +add_template_candidate_real (candidates, tmpl, explicit_targs, + arglist, return_type, flags, + obj, strict) + struct z_candidate *candidates; + tree tmpl, explicit_targs, arglist, return_type; + int flags; + tree obj; + unification_kind_t strict; { - tree rval; - int old_assume_nonnull_objects = flag_assume_nonnull_objects; + int ntparms = DECL_NTPARMS (tmpl); + tree targs = make_scratch_vec (ntparms); + struct z_candidate *cand; + int i; + tree fn; - if (datum == error_mark_node) - return error_mark_node; + i = fn_type_unification (tmpl, explicit_targs, targs, arglist, + return_type, strict, NULL_TREE); - /* 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); + if (i != 0) + return candidates; - if (! TYPE_USES_COMPLEX_INHERITANCE (type)) - rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)), - datum, CLASSTYPE_VFIELD (type)); + fn = instantiate_template (tmpl, targs); + if (fn == error_mark_node) + return candidates; + + if (obj != NULL_TREE) + /* Aha, this is a conversion function. */ + cand = add_conv_candidate (candidates, fn, obj, arglist); else - rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0); - flag_assume_nonnull_objects = old_assume_nonnull_objects; + cand = add_function_candidate (candidates, fn, arglist, flags); + if (DECL_TI_TEMPLATE (fn) != tmpl) + /* This situation can occur if a member template of a template + class is specialized. Then, instantiate_template might return + an instantiation of the specialization, in which case the + DECL_TI_TEMPLATE field will point at the original + specialization. For example: + + template struct S { template void f(U); + template <> void f(int) {}; }; + S sd; + sd.f(3); + + Here, TMPL will be template S::f(U). + And, instantiate template will give us the specialization + template <> S::f(int). But, the DECL_TI_TEMPLATE field + for this will point at template template <> S::f(int), + so that we can find the definition. For the purposes of + overload resolution, however, we want the original TMPL. */ + cand->template = tree_cons (tmpl, targs, NULL_TREE); + else + cand->template = DECL_TEMPLATE_INFO (fn); - return rval; + return cand; } -/* Build a call to a member of an object. I.e., one that overloads - operator ()(), or is a pointer-to-function or pointer-to-method. */ -static tree -build_field_call (basetype_path, instance_ptr, name, parms) - tree basetype_path, instance_ptr, name, parms; -{ - tree field, instance; - - if (instance_ptr == current_class_decl) - { - /* 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; - } +static struct z_candidate * +add_template_candidate (candidates, tmpl, explicit_targs, + arglist, return_type, flags, strict) + struct z_candidate *candidates; + tree tmpl, explicit_targs, arglist, return_type; + int flags; + unification_kind_t strict; +{ + return + add_template_candidate_real (candidates, tmpl, explicit_targs, + arglist, return_type, flags, + NULL_TREE, strict); +} - 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 (C_C_D, field, 0); - if (instance == error_mark_node) - return error_mark_node; - if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance)) - && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance))) - return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE); +static struct z_candidate * +add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type) + struct z_candidate *candidates; + tree tmpl, obj, arglist, return_type; +{ + return + add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist, + return_type, 0, obj, DEDUCE_CONV); +} - 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, tree_cons (NULL_TREE, current_class_decl, parms)); - } - } - 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); +static int +any_viable (cands) + struct z_candidate *cands; +{ + for (; cands; cands = cands->next) + if (pedantic ? cands->viable == 1 : cands->viable) + return 1; + return 0; +} - /* This can happen if the reference was ambiguous or for access - violations. */ - if (field == error_mark_node) - return error_mark_node; +static struct z_candidate * +splice_viable (cands) + struct z_candidate *cands; +{ + struct z_candidate **p = &cands; - if (field) + for (; *p; ) { - tree basetype; - tree ftype = TREE_TYPE (field); + if (pedantic ? (*p)->viable == 1 : (*p)->viable) + p = &((*p)->next); + else + *p = (*p)->next; + } - if (TREE_CODE (ftype) == REFERENCE_TYPE) - ftype = TREE_TYPE (ftype); + return cands; +} - if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype)) - { - /* Make the next search for this field very short. */ - basetype = DECL_FIELD_CONTEXT (field); - instance_ptr = convert_pointer_to (basetype, instance_ptr); +static tree +build_this (obj) + tree obj; +{ + /* Fix this to work on non-lvalues. */ + if (IS_SIGNATURE_POINTER (TREE_TYPE (obj)) + || IS_SIGNATURE_REFERENCE (TREE_TYPE (obj))) + return obj; + else + return build_unary_op (ADDR_EXPR, obj, 0); +} - 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 (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) +static void +print_z_candidates (candidates) + struct z_candidate *candidates; +{ + char *str = "candidates are:"; + for (; candidates; candidates = candidates->next) + { + if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) { - error ("invalid call via pointer-to-member function"); - return error_mark_node; + if (candidates->fn == ansi_opname [COND_EXPR]) + cp_error ("%s %D(%T, %T, %T) ", str, candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); + else if (TREE_VEC_LENGTH (candidates->convs) == 2) + cp_error ("%s %D(%T, %T) ", str, candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); + else + cp_error ("%s %D(%T) ", str, candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); } else - return NULL_TREE; + cp_error_at ("%s %+D%s", str, candidates->fn, + candidates->viable == -1 ? " " : ""); + str = " "; } - return NULL_TREE; } -tree -find_scoped_type (type, inner_name, inner_types) - tree type, inner_name, inner_types; -{ - tree tags = CLASSTYPE_TAGS (type); +/* Returns the best overload candidate to perform the requested + conversion. This function is used for three the overloading situations + described in [over.match.copy], [over.match.conv], and [over.match.ref]. + If TOTYPE is a REFERENCE_TYPE, we're trying to find an lvalue binding as + per [dcl.init.ref], so we ignore temporary bindings. */ - while (tags) +static struct z_candidate * +build_user_type_conversion_1 (totype, expr, flags) + tree totype, expr; + int flags; +{ + struct z_candidate *candidates, *cand; + tree fromtype = TREE_TYPE (expr); + tree ctors = NULL_TREE, convs = NULL_TREE, *p; + tree args = NULL_TREE; + tree templates = NULL_TREE; + + if (IS_AGGR_TYPE (totype)) + ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); + if (IS_AGGR_TYPE (fromtype) + && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype))) + convs = lookup_conversions (fromtype); + + candidates = 0; + flags |= LOOKUP_NO_CONVERSION; + + if (ctors) { - /* The TREE_PURPOSE of an enum tag (which becomes a member of the - enclosing class) is set to the name for the enum type. So, if - inner_name is `bar', and we strike `baz' for `enum bar { baz }', - then this test will be true. */ - if (TREE_PURPOSE (tags) == inner_name) + tree t = build_int_2 (0, 0); + TREE_TYPE (t) = build_pointer_type (totype); + args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_VIRTUAL_BASECLASSES (totype)) + args = scratch_tree_cons (NULL_TREE, integer_one_node, args); + args = scratch_tree_cons (NULL_TREE, t, args); + + ctors = TREE_VALUE (ctors); + } + for (; ctors; ctors = OVL_NEXT (ctors)) + { + tree ctor = OVL_CURRENT (ctors); + if (DECL_NONCONVERTING_P (ctor)) + continue; + + if (TREE_CODE (ctor) == TEMPLATE_DECL) { - if (inner_types == NULL_TREE) - return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags))); - return resolve_scope_to_name (TREE_VALUE (tags), inner_types); - } - tags = TREE_CHAIN (tags); + templates = scratch_tree_cons (NULL_TREE, ctor, templates); + candidates = + add_template_candidate (candidates, ctor, + NULL_TREE, args, NULL_TREE, flags, + DEDUCE_CALL); + } + else + candidates = add_function_candidate (candidates, ctor, + args, flags); + + if (candidates) + { + candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); + candidates->basetype_path = TYPE_BINFO (totype); + } } -#if 0 - /* XXX This needs to be fixed better. */ - if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) + if (convs) + args = build_scratch_list (NULL_TREE, build_this (expr)); + + for (; convs; convs = TREE_CHAIN (convs)) { - sorry ("nested class lookup in template type"); - return NULL_TREE; + tree fns = TREE_VALUE (convs); + int convflags = LOOKUP_NO_CONVERSION; + tree ics; + + /* If we are called to convert to a reference type, we are trying to + find an lvalue binding, so don't even consider temporaries. If + we don't find an lvalue binding, the caller will try again to + look for a temporary binding. */ + if (TREE_CODE (totype) == REFERENCE_TYPE) + convflags |= LOOKUP_NO_TEMP_BIND; + + if (TREE_CODE (fns) != TEMPLATE_DECL) + ics = implicit_conversion + (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags); + else + /* We can't compute this yet. */ + ics = error_mark_node; + + if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics)) + /* ignore the near match. */; + else if (ics) + for (; fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + struct z_candidate *old_candidates = candidates; + + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates = + add_template_candidate (candidates, fn, NULL_TREE, + args, totype, flags, + DEDUCE_CONV); + } + else + candidates = add_function_candidate (candidates, fn, + args, flags); + + if (candidates != old_candidates) + { + if (TREE_CODE (fn) == TEMPLATE_DECL) + ics = implicit_conversion + (totype, TREE_TYPE (TREE_TYPE (candidates->fn)), + 0, convflags); + + candidates->second_conv = ics; + candidates->basetype_path = TREE_PURPOSE (convs); + + if (ics == NULL_TREE) + candidates->viable = 0; + else if (candidates->viable == 1 && ICS_BAD_FLAG (ics)) + candidates->viable = -1; + } + } } + + if (! any_viable (candidates)) + { +#if 0 + if (flags & LOOKUP_COMPLAIN) + { + if (candidates && ! candidates->next) + /* say why this one won't work or try to be loose */; + else + cp_error ("no viable candidates"); + } #endif - /* Look for a TYPE_DECL. */ - for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags)) - if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name) - { - /* Code by raeburn. */ - if (inner_types == NULL_TREE) - return DECL_NESTED_TYPENAME (tags); - return resolve_scope_to_name (TREE_TYPE (tags), inner_types); - } + return 0; + } - return NULL_TREE; + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("conversion from `%T' to `%T' is ambiguous", + fromtype, totype); + print_z_candidates (candidates); + } + + cand = candidates; /* any one will do */ + cand->second_conv = build1 (AMBIG_CONV, totype, expr); + ICS_USER_FLAG (cand->second_conv) = 1; + ICS_BAD_FLAG (cand->second_conv) = 1; + + return cand; + } + + for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) + p = &(TREE_OPERAND (*p, 0)); + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && !DECL_INITIAL (cand->fn) + && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE) + add_maybe_template (cand->fn, templates); + + *p = build + (USER_CONV, + (DECL_CONSTRUCTOR_P (cand->fn) + ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))), + expr, build_expr_ptr_wrapper (cand)); + ICS_USER_FLAG (cand->second_conv) = 1; + if (cand->viable == -1) + ICS_BAD_FLAG (cand->second_conv) = 1; + + return cand; } -/* Resolve an expression NAME1::NAME2::...::NAMEn to - the name that names the above nested type. INNER_TYPES - is a chain of nested type names (held together by SCOPE_REFs); - OUTER_TYPE is the type we know to enclose INNER_TYPES. - Returns NULL_TREE if there is an error. */ tree -resolve_scope_to_name (outer_type, inner_stuff) - tree outer_type, inner_stuff; +build_user_type_conversion (totype, expr, flags) + tree totype, expr; + int flags; { - register tree tmp; - tree inner_name, inner_type; + struct z_candidate *cand + = build_user_type_conversion_1 (totype, expr, flags); - if (outer_type == NULL_TREE && current_class_type != NULL_TREE) + if (cand) { - /* We first try to look for a nesting in our current class context, - then try any enclosing classes. */ - tree type = current_class_type; - - while (type && (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE)) - { - tree rval = resolve_scope_to_name (type, inner_stuff); - - if (rval != NULL_TREE) - return rval; - type = DECL_CONTEXT (TYPE_NAME (type)); - } + if (TREE_CODE (cand->second_conv) == AMBIG_CONV) + return error_mark_node; + return convert_from_reference (convert_like (cand->second_conv, expr)); } + return NULL_TREE; +} - if (TREE_CODE (inner_stuff) == SCOPE_REF) - { - inner_name = TREE_OPERAND (inner_stuff, 0); - inner_type = TREE_OPERAND (inner_stuff, 1); - } - else - { - inner_name = inner_stuff; - inner_type = NULL_TREE; - } +/* Do any initial processing on the arguments to a function call. */ - if (outer_type == NULL_TREE) +static tree +resolve_args (args) + tree args; +{ + tree t; + for (t = args; t; t = TREE_CHAIN (t)) { - tree x; - /* If we have something that's already a type by itself, - use that. */ - if (IDENTIFIER_HAS_TYPE_VALUE (inner_name)) + if (TREE_VALUE (t) == error_mark_node) + return error_mark_node; + else if (TREE_CODE (TREE_TYPE (TREE_VALUE (t))) == VOID_TYPE) { - if (inner_type) - return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name), - inner_type); - return inner_name; + error ("invalid use of void expression"); + return error_mark_node; } + else if (TREE_CODE (TREE_VALUE (t)) == OFFSET_REF) + TREE_VALUE (t) = resolve_offset_ref (TREE_VALUE (t)); + } + return args; +} - x = lookup_name (inner_name, 0); +tree +build_new_function_call (fn, args) + tree fn, args; +{ + struct z_candidate *candidates = 0, *cand; + tree explicit_targs = NULL_TREE; + int template_only = 0; - if (x && TREE_CODE (x) == NAMESPACE_DECL) - { - x = lookup_namespace_name (x, inner_type); - return x; - } - return NULL_TREE; + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + { + explicit_targs = TREE_OPERAND (fn, 1); + fn = TREE_OPERAND (fn, 0); + template_only = 1; } - if (! IS_AGGR_TYPE (outer_type)) - return NULL_TREE; + if (really_overloaded_fn (fn)) + { + tree t1; + tree templates = NULL_TREE; + + args = resolve_args (args); + + if (args == error_mark_node) + return error_mark_node; - /* Look for member classes or enums. */ - tmp = find_scoped_type (outer_type, inner_name, inner_type); + for (t1 = fn; t1; t1 = OVL_CHAIN (t1)) + { + tree t = OVL_FUNCTION (t1); + if (TREE_CODE (t) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, t, templates); + candidates = add_template_candidate + (candidates, t, explicit_targs, args, NULL_TREE, + LOOKUP_NORMAL, DEDUCE_CALL); + } + else if (! template_only) + candidates = add_function_candidate + (candidates, t, args, LOOKUP_NORMAL); + } - /* If it's not a type in this class, then go down into the - base classes and search there. */ - if (! tmp && TYPE_BINFO (outer_type)) - { - tree binfos = TYPE_BINFO_BASETYPES (outer_type); - int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + if (! any_viable (candidates)) + { + if (candidates && ! candidates->next) + return build_function_call (candidates->fn, args); + cp_error ("no matching function for call to `%D (%A)'", + DECL_NAME (OVL_FUNCTION (fn)), args); + if (candidates) + print_z_candidates (candidates); + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates); - for (i = 0; i < n_baselinks; i++) + if (cand == 0) { - tree base_binfo = TREE_VEC_ELT (binfos, i); - tmp = resolve_scope_to_name (BINFO_TYPE (base_binfo), inner_stuff); - if (tmp) - return tmp; + cp_error ("call of overloaded `%D (%A)' is ambiguous", + DECL_NAME (OVL_FUNCTION (fn)), args); + print_z_candidates (candidates); + return error_mark_node; } - tmp = NULL_TREE; - } - return tmp; -} + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && ! DECL_INITIAL (cand->fn)) + add_maybe_template (cand->fn, templates); -/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. - This is how virtual function calls are avoided. */ -tree -build_scoped_method_call (exp, scopes, name, parms) - tree exp, scopes, name, parms; -{ - /* Because this syntactic form does not allow - a pointer to a base class to be `stolen', - we need not protect the derived->base conversion - that happens here. - - @@ But we do have to check access privileges later. */ - tree basename = resolve_scope_to_name (NULL_TREE, scopes); - tree basetype, binfo, decl; - tree type = TREE_TYPE (exp); + return build_over_call (cand, args, LOOKUP_NORMAL); + } - if (type == error_mark_node - || basename == NULL_TREE) - return error_mark_node; + /* This is not really overloaded. */ + fn = OVL_CURRENT (fn); - basetype = IDENTIFIER_TYPE_VALUE (basename); + return build_function_call (fn, args); +} - if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); +static tree +build_object_call (obj, args) + tree obj, args; +{ + struct z_candidate *candidates = 0, *cand; + tree fns, convs, mem_args = NULL_TREE; + tree type = TREE_TYPE (obj); + tree templates = NULL_TREE; - /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note - that explicit ~int is caught in the parser; this deals with typedefs - and template parms. */ - if (TREE_CODE (name) == BIT_NOT_EXPR && ! is_aggr_typedef (basename, 0)) + if (TYPE_PTRMEMFUNC_P (type)) { - if (type != basetype) - cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')", - exp, basetype, type); - name = TREE_OPERAND (name, 0); - if (basetype != get_type_value (name)) - cp_error ("qualified type `%T' does not match destructor name `~%T'", - basetype, name); - return convert (void_type_node, exp); + /* It's no good looking for an overloaded operator() on a + pointer-to-member-function. */ + cp_error ("pointer-to-member function %E cannot be called", obj); + cp_error ("without an object; consider using .* or ->*"); + return error_mark_node; } - if (! is_aggr_typedef (basename, 1)) + fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 1); + if (fns == error_mark_node) return error_mark_node; - if (! IS_AGGR_TYPE (type)) - { - cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'", - exp, type); - return error_mark_node; - } + args = resolve_args (args); + + if (args == error_mark_node) + return error_mark_node; - if ((binfo = binfo_or_else (basetype, type))) + if (fns) { - if (binfo == error_mark_node) - return error_mark_node; - if (TREE_CODE (exp) == INDIRECT_REF) - decl = build_indirect_ref (convert_pointer_to (binfo, - build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR); - else - decl = build_scoped_ref (exp, scopes); + tree base = TREE_PURPOSE (fns); + mem_args = scratch_tree_cons (NULL_TREE, build_this (obj), args); - /* Call to a destructor. */ - if (TREE_CODE (name) == BIT_NOT_EXPR) + for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns)) { - /* Explicit call to destructor. */ - name = TREE_OPERAND (name, 0); - if (! (name == constructor_name (TREE_TYPE (decl)) - || TREE_TYPE (decl) == get_type_value (name))) + tree fn = OVL_CURRENT (fns); + if (TREE_CODE (fn) == TEMPLATE_DECL) { - cp_error - ("qualified type `%T' does not match destructor name `~%T'", - TREE_TYPE (decl), name); - return error_mark_node; + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates + = add_template_candidate (candidates, fn, NULL_TREE, + mem_args, NULL_TREE, + LOOKUP_NORMAL, DEDUCE_CALL); } - if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl))) - return convert (void_type_node, exp); - - return build_delete (TREE_TYPE (decl), decl, integer_two_node, - LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, - 0); + else + candidates = add_function_candidate + (candidates, fn, mem_args, LOOKUP_NORMAL); + + if (candidates) + candidates->basetype_path = base; } + } - /* Call to a method. */ - return build_method_call (decl, name, parms, binfo, - LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); + convs = lookup_conversions (type); + + for (; convs; convs = TREE_CHAIN (convs)) + { + tree fns = TREE_VALUE (convs); + tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))); + tree fn; + + if (TREE_CODE (totype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + for (; fns; fns = OVL_NEXT (fn)) + { + fn = OVL_CURRENT (fn); + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates = add_template_conv_candidate (candidates, + fn, + obj, + args, + totype); + } + else + candidates = add_conv_candidate (candidates, fn, obj, args); + + if (candidates) + candidates->basetype_path = TREE_PURPOSE (convs); + } } - return error_mark_node; -} -static void -print_candidates (candidates) - tree candidates; -{ - cp_error_at ("candidates are: %D", TREE_VALUE (candidates)); - candidates = TREE_CHAIN (candidates); + if (! any_viable (candidates)) + { + cp_error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args); + print_z_candidates (candidates); + return error_mark_node; + } + + candidates = splice_viable (candidates); + cand = tourney (candidates); - while (candidates) + if (cand == 0) { - cp_error_at (" %D", TREE_VALUE (candidates)); - candidates = TREE_CHAIN (candidates); + cp_error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args); + print_z_candidates (candidates); + return error_mark_node; } + + if (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); + + /* FIXME */ + return build_function_call (obj, args); } static void -print_n_candidates (candidates, n) - struct candidate *candidates; - int n; +op_error (code, code2, arg1, arg2, arg3, problem) + enum tree_code code, code2; + tree arg1, arg2, arg3; + char *problem; { - int i; + char * opname + = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]); - cp_error_at ("candidates are: %D", candidates[0].function); - for (i = 1; i < n; i++) - cp_error_at (" %D", candidates[i].function); + switch (code) + { + case COND_EXPR: + cp_error ("%s for `%T ? %T : %T'", problem, + error_type (arg1), error_type (arg2), error_type (arg3)); + break; + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + cp_error ("%s for `%T%s'", problem, error_type (arg1), opname); + break; + case ARRAY_REF: + cp_error ("%s for `%T[%T]'", problem, + error_type (arg1), error_type (arg2)); + break; + default: + if (arg2) + cp_error ("%s for `%T %s %T'", problem, + error_type (arg1), opname, error_type (arg2)); + else + cp_error ("%s for `%s%T'", problem, opname, error_type (arg1)); + } } -/* Build something of the form ptr->method (args) - or object.method (args). This can also build - calls to constructors, and find friends. +tree +build_new_op (code, flags, arg1, arg2, arg3) + enum tree_code code; + int flags; + tree arg1, arg2, arg3; +{ + struct z_candidate *candidates = 0, *cand; + tree fns, mem_arglist = NULL_TREE, arglist, fnname; + enum tree_code code2 = NOP_EXPR; + tree templates = NULL_TREE; + tree conv; - Member functions always take their class variable - as a pointer. + if (arg1 == error_mark_node + || arg2 == error_mark_node + || arg3 == error_mark_node) + return error_mark_node; - INSTANCE is a class instance. + /* This can happen if a template takes all non-type parameters, e.g. + undeclared_template<1, 5, 72>a; */ + if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL) + { + cp_error ("`%D' must be declared before use", arg1); + return error_mark_node; + } - NAME is the name of the method desired, usually an IDENTIFIER_NODE. + if (code == MODIFY_EXPR) + { + code2 = TREE_CODE (arg3); + arg3 = NULL_TREE; + fnname = ansi_assopname[code2]; + } + else + fnname = ansi_opname[code]; - PARMS help to figure out what that NAME really refers to. + switch (code) + { + 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; + } - BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE - down to the real instance type to use for access checking. We need this - information to get protected accesses correct. This parameter is used - by build_member_call. + 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; + } - FLAGS is the logical disjunction of zero or more LOOKUP_ - flags. See cp-tree.h for more info. + case CALL_EXPR: + return build_object_call (arg1, arg2); - If this is all OK, calls build_function_call with the resolved - member function. + default: + break; + } - This function must also handle being called to perform - initialization, promotion/coercion of arguments, and - instantiation of default parameters. + /* The comma operator can have void args. */ + if (TREE_CODE (arg1) == OFFSET_REF) + arg1 = resolve_offset_ref (arg1); + if (arg2 && TREE_CODE (arg2) == OFFSET_REF) + arg2 = resolve_offset_ref (arg2); + if (arg3 && TREE_CODE (arg3) == OFFSET_REF) + arg3 = resolve_offset_ref (arg3); - Note that NAME may refer to an instance variable name. If - `operator()()' is defined for the type of that field, then we return - that result. */ -tree -build_method_call (instance, name, parms, basetype_path, flags) - tree instance, name, parms, basetype_path; - int flags; -{ - register tree function, fntype, value_type; - register tree basetype, save_basetype; - register tree baselink, result, method_name, parmtypes, parm; - tree last; - int pass; - enum access_type access = access_public; - - /* Range of cases for vtable optimization. */ - enum vtable_needs { not_needed, maybe_needed, unneeded, needed }; - enum vtable_needs need_vtbl = not_needed; - - char *name_kind; - int ever_seen = 0; - tree instance_ptr = NULL_TREE; - int all_virtual = flag_all_virtual; - int static_call_context = 0; - tree found_fns = NULL_TREE; - - /* Keep track of `const' and `volatile' objects. */ - int constp, volatilep; + if (code == COND_EXPR) + { + if (arg2 == NULL_TREE + || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE + || TREE_CODE (TREE_TYPE (arg3)) == VOID_TYPE + || (! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)) + && ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3)))) + goto builtin; + } + else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) + && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)))) + goto builtin; + + if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) + arg2 = integer_zero_node; + + if (arg2 && arg3) + arglist = scratch_tree_cons (NULL_TREE, arg1, scratch_tree_cons + (NULL_TREE, arg2, build_scratch_list (NULL_TREE, arg3))); + else if (arg2) + arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2)); + else + arglist = build_scratch_list (NULL_TREE, arg1); -#ifdef GATHER_STATISTICS - n_build_method_call++; -#endif + fns = lookup_function_nonclass (fnname, arglist); - if (instance == error_mark_node - || name == error_mark_node - || parms == error_mark_node - || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node)) - return error_mark_node; + if (fns && TREE_CODE (fns) == TREE_LIST) + fns = TREE_VALUE (fns); + for (; fns; fns = OVL_NEXT (fns)) + { + 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, + arglist, TREE_TYPE (fnname), + flags, DEDUCE_CALL); + } + else + candidates = add_function_candidate (candidates, fn, arglist, flags); + } - /* 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) + if (IS_AGGR_TYPE (TREE_TYPE (arg1))) { - tree save_last = TREE_CHAIN (parms); - tree result; - /* get rid of unneeded argument */ - TREE_CHAIN (parms) = NULL_TREE; - result = build_method_call (instance, name, parms, basetype_path, - (LOOKUP_SPECULATIVELY|flags) - &~LOOKUP_COMPLAIN); - /* If it finds a match, return it. */ - if (result) - 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; + fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1); + if (fns == error_mark_node) + return fns; } - /* We already know whether it's needed or not for vec delete. */ - else if (name == ansi_opname[(int) VEC_DELETE_EXPR] - && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance))) - TREE_CHAIN (parms) = NULL_TREE; + else + fns = NULL_TREE; - if (TREE_CODE (name) == BIT_NOT_EXPR) + if (fns) { - flags |= LOOKUP_DESTRUCTOR; - name = TREE_OPERAND (name, 0); - if (parms) - error ("destructors take no parameters"); - basetype = TREE_TYPE (instance); - if (TREE_CODE (basetype) == REFERENCE_TYPE) - basetype = TREE_TYPE (basetype); - if (! ((IS_AGGR_TYPE (basetype) - && name == constructor_name (basetype)) - || basetype == get_type_value (name))) + tree basetype = TREE_PURPOSE (fns); + mem_arglist = scratch_tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist)); + for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns)) { - cp_error ("destructor name `~%D' does not match type `%T' of expression", - name, basetype); - return convert (void_type_node, instance); - } + tree fn = OVL_CURRENT (fns); + tree this_arglist; - if (! TYPE_HAS_DESTRUCTOR (basetype)) - return convert (void_type_node, instance); - instance = default_conversion (instance); - instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); - return build_delete (build_pointer_type (basetype), - instance_ptr, integer_two_node, - LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); + if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + this_arglist = mem_arglist; + else + this_arglist = arglist; + + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + /* A member template. */ + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates + = add_template_candidate (candidates, fn, NULL_TREE, + this_arglist, TREE_TYPE (fnname), + flags, DEDUCE_CALL); + } + else + candidates = add_function_candidate + (candidates, fn, this_arglist, flags); + + if (candidates) + candidates->basetype_path = basetype; + } } { - char *xref_name; - - /* Initialize name for error reporting. */ - if (IDENTIFIER_OPNAME_P (name) && ! IDENTIFIER_TYPENAME_P (name)) + tree args[3]; + + /* Rearrange the arguments for ?: so that add_builtin_candidate only has + to know about two args; a builtin candidate will always have a first + parameter of type bool. We'll handle that in + build_builtin_candidate. */ + if (code == COND_EXPR) { - char *p = operator_name_string (name); - xref_name = (char *)alloca (strlen (p) + 10); - sprintf (xref_name, "operator %s", p); + args[0] = arg2; + args[1] = arg3; + args[2] = arg1; } - else if (TREE_CODE (name) == SCOPE_REF) - xref_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1)); else - xref_name = IDENTIFIER_POINTER (name); + { + args[0] = arg1; + args[1] = arg2; + args[2] = NULL_TREE; + } - GNU_xref_call (current_function_decl, xref_name); + candidates = add_builtin_candidates + (candidates, code, code2, fnname, args, flags); } - if (instance == NULL_TREE) + if (! any_viable (candidates)) { - basetype = NULL_TREE; - /* Check cases where this is really a call to raise - an exception. */ - if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE) + switch (code) { - basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type)); - if (basetype) - basetype = TREE_VALUE (basetype); + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* Look for an `operator++ (int)'. If they didn't have + one, then we fall back to the old way of doing things. */ + if (flags & LOOKUP_COMPLAIN) + cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead", + fnname, opname_tab [code]); + if (code == POSTINCREMENT_EXPR) + code = PREINCREMENT_EXPR; + else + code = PREDECREMENT_EXPR; + return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE); + + /* The caller will deal with these. */ + case ADDR_EXPR: + case COMPOUND_EXPR: + case COMPONENT_REF: + return NULL_TREE; + + default: + break; } - else if (TREE_CODE (name) == SCOPE_REF - && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) + if (flags & LOOKUP_COMPLAIN) { - if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1)) - return error_mark_node; - basetype = purpose_member (TREE_OPERAND (name, 1), - CLASSTYPE_TAGS (IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0)))); - if (basetype) - basetype = TREE_VALUE (basetype); + op_error (code, code2, arg1, arg2, arg3, "no match"); + print_z_candidates (candidates); } + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates); - if (basetype != NULL_TREE) - ; - /* call to a constructor... */ - else if (basetype_path) - basetype = BINFO_TYPE (basetype_path); - else if (IDENTIFIER_HAS_TYPE_VALUE (name)) + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) { - basetype = IDENTIFIER_TYPE_VALUE (name); - name = constructor_name_full (basetype); + op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); + print_z_candidates (candidates); } - else + return error_mark_node; + } + + if (TREE_CODE (cand->fn) == FUNCTION_DECL) + { + extern int warn_synth; + if (warn_synth + && fnname == ansi_opname[MODIFY_EXPR] + && DECL_ARTIFICIAL (cand->fn) + && candidates->next + && ! candidates->next->next) { - tree typedef_name = lookup_name (name, 1); - if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL) - { - /* Canonicalize the typedef name. */ - basetype = TREE_TYPE (typedef_name); - name = TYPE_IDENTIFIER (basetype); - } - else - { - cp_error ("no constructor named `%T' in scope", - name); - return error_mark_node; - } + cp_warning ("using synthesized `%#D' for copy assignment", + cand->fn); + cp_warning_at (" where cfront would use `%#D'", + cand == candidates + ? candidates->next->fn + : candidates->fn); + } + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && ! DECL_INITIAL (cand->fn) + && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE) + add_maybe_template (cand->fn, templates); + + return build_over_call + (cand, + TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE + ? mem_arglist : arglist, + LOOKUP_NORMAL); + } + + /* Check for comparison of different enum types. */ + switch (code) + { + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + if (flag_int_enum_equivalence == 0 + && 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)))) + { + cp_warning ("comparison between `%#T' and `%#T'", + TREE_TYPE (arg1), TREE_TYPE (arg2)); } + break; + default: + break; + } + + /* We need to strip any leading REF_BIND so that bitfields don't cause + errors. This should not remove any important conversions, because + builtins don't apply to class objects directly. */ + conv = TREE_VEC_ELT (cand->convs, 0); + if (TREE_CODE (conv) == REF_BIND) + conv = TREE_OPERAND (conv, 0); + arg1 = convert_like (conv, arg1); + if (arg2) + arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2); + if (arg3) + arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3); + +builtin: + switch (code) + { + case MODIFY_EXPR: + return build_modify_expr (arg1, code2, arg2); + + case INDIRECT_REF: + return build_indirect_ref (arg1, "unary *"); + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + return build_binary_op_nodefault (code, arg1, arg2, code); + + case CONVERT_EXPR: + case NEGATE_EXPR: + case BIT_NOT_EXPR: + case TRUTH_NOT_EXPR: + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + case REALPART_EXPR: + case IMAGPART_EXPR: + return build_unary_op (code, arg1, candidates != 0); + + case ARRAY_REF: + return build_array_ref (arg1, arg2); + + case COND_EXPR: + return build_conditional_expr (arg1, arg2, arg3); + + case MEMBER_REF: + return build_m_component_ref + (build_indirect_ref (arg1, NULL_PTR), arg2); + + /* The caller will deal with these. */ + case ADDR_EXPR: + case COMPONENT_REF: + case COMPOUND_EXPR: + return NULL_TREE; + + default: + my_friendly_abort (367); + return NULL_TREE; + } +} + +/* Build up a call to operator new. This has to be handled differently + from other operators in the way lookup is handled; first members are + considered, then globals. CODE is either NEW_EXPR or VEC_NEW_EXPR. + TYPE is the type to be created. ARGS are any new-placement args. + FLAGS are the usual overloading flags. */ + +tree +build_op_new_call (code, type, args, flags) + enum tree_code code; + tree type, args; + int flags; +{ + tree fnname = ansi_opname[code]; + + 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); + } + else + return build_new_function_call + (lookup_function_nonclass (fnname, args), args); +} + +/* Build a call to operator delete. This has to be handled very specially, + because the restrictions on what signatures match are different from all + other call instances. For a normal delete, only a delete taking (void *) + or (void *, size_t) is accepted. For a placement delete, only an exact + match with the placement new is accepted. + + CODE is either DELETE_EXPR or VEC_DELETE_EXPR. + ADDR is the pointer to be deleted. For placement delete, it is also + used to determine what the corresponding new looked like. + SIZE is the size of the memory block to be deleted. + FLAGS are the usual overloading flags. + PLACEMENT is the corresponding placement new call, or 0. */ + +tree +build_op_delete_call (code, addr, size, flags, placement) + enum tree_code code; + tree addr, size, placement; + int flags; +{ + tree fn, fns, fnname, fntype, argtypes, args, type; + + if (addr == error_mark_node) + return error_mark_node; + + type = TREE_TYPE (TREE_TYPE (addr)); + fnname = ansi_opname[code]; + + if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)) + /* In [class.free] + + If the result of the lookup is ambiguous or inaccessible, or if + the lookup selects a placement deallocation function, the + program is ill-formed. + + Therefore, we ask lookup_fnfields to complain ambout ambiguity. */ + { + fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1); + if (fns == error_mark_node) + return error_mark_node; + } + else + fns = NULL_TREE; - if (! IS_AGGR_TYPE (basetype)) - { - non_aggr_error: - if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK) - cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", - name, instance, basetype); + if (fns == NULL_TREE) + fns = lookup_name_nonclass (fnname); - return error_mark_node; - } + if (placement) + { + /* placement is a CALL_EXPR around an ADDR_EXPR around a function. */ + + /* Extract the function. */ + argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0); + /* Then the second parm type. */ + argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes))); + + /* Also the second argument. */ + args = TREE_CHAIN (TREE_OPERAND (placement, 1)); } - else if (instance == C_C_D || instance == current_class_decl) + else { - /* When doing initialization, we side-effect the TREE_TYPE of - C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */ - basetype = TREE_TYPE (C_C_D); + /* First try it without the size argument. */ + argtypes = void_list_node; + args = NULL_TREE; + } - /* Anything manifestly `this' in constructors and destructors - has a known type, so virtual function tables are not needed. */ - if (TYPE_VIRTUAL_P (basetype) - && !(flags & LOOKUP_NONVIRTUAL)) - need_vtbl = (dtor_label || ctor_label) - ? unneeded : maybe_needed; + argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes); + fntype = build_function_type (void_type_node, argtypes); - /* If `this' is a signature pointer and `name' is not a constructor, - we are calling a signature member function. In that case, set the - `basetype' to the signature type and dereference the `optr' field. */ - if (IS_SIGNATURE_POINTER (basetype) - && TYPE_IDENTIFIER (basetype) != name) - { - basetype = SIGNATURE_TYPE (basetype); - instance_ptr = build_optr_ref (instance); - instance_ptr = convert (build_pointer_type (basetype), instance_ptr); - basetype_path = TYPE_BINFO (basetype); - } - else - { - instance = C_C_D; - instance_ptr = current_class_decl; - basetype_path = TYPE_BINFO (current_class_type); - } - result = build_field_call (basetype_path, instance_ptr, name, parms); + /* Strip const and volatile from addr. */ + if (type != TYPE_MAIN_VARIANT (type)) + addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr); - if (result) - return result; - } - else if (TREE_CODE (instance) == RESULT_DECL) + /* 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); + + if (fn != error_mark_node) { - basetype = TREE_TYPE (instance); - /* Should we ever have to make a virtual function reference - from a RESULT_DECL, know that it must be of fixed type - within the scope of this function. */ - if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype)) - need_vtbl = maybe_needed; - instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance); + if (TREE_CODE (fns) == TREE_LIST) + /* Member functions. */ + enforce_access (TREE_PURPOSE (fns), fn); + return build_function_call (fn, expr_tree_cons (NULL_TREE, addr, args)); } - else + + /* If we are doing placement delete we do nothing if we don't find a + matching op delete. */ + if (placement) + return NULL_TREE; + + /* Normal delete; now try to find a match including the size argument. */ + argtypes = tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, sizetype, void_list_node)); + fntype = build_function_type (void_type_node, argtypes); + + fn = instantiate_type (fntype, fns, 0); + + if (fn != error_mark_node) { - /* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */ - tree inst_ptr_basetype; + if (TREE_CODE (fns) == TREE_LIST) + /* Member functions. */ + enforce_access (TREE_PURPOSE (fns), fn); + return build_function_call + (fn, expr_tree_cons (NULL_TREE, addr, + build_expr_list (NULL_TREE, size))); + } - static_call_context = - (TREE_CODE (instance) == INDIRECT_REF - && TREE_CODE (TREE_OPERAND (instance, 0)) == NOP_EXPR - && TREE_OPERAND (TREE_OPERAND (instance, 0), 0) == error_mark_node); + /* finish_function passes LOOKUP_SPECULATIVELY if we're in a + destructor, in which case the error should be deferred + until someone actually tries to delete one of these. */ + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; - if (TREE_CODE (instance) == OFFSET_REF) - instance = resolve_offset_ref (instance); + cp_error ("no suitable operator delete for `%T'", type); + return error_mark_node; +} - /* the base type of an instance variable is pointer to class */ - basetype = TREE_TYPE (instance); +/* If the current scope isn't allowed to access DECL along + BASETYPE_PATH, give an error. */ - if (TREE_CODE (basetype) == REFERENCE_TYPE) - { - basetype = TREE_TYPE (basetype); - if (! IS_AGGR_TYPE (basetype)) - goto non_aggr_error; - /* Call to convert not needed because we are remaining - within the same type. */ - instance_ptr = build1 (NOP_EXPR, build_pointer_type (basetype), - instance); - inst_ptr_basetype = TYPE_MAIN_VARIANT (basetype); - } - else - { - if (! IS_AGGR_TYPE (basetype) - && ! (TYPE_LANG_SPECIFIC (basetype) - && (IS_SIGNATURE_POINTER (basetype) - || IS_SIGNATURE_REFERENCE (basetype)))) - goto non_aggr_error; - - /* If `instance' is a signature pointer/reference and `name' is - not a constructor, we are calling a signature member function. - In that case set the `basetype' to the signature type. */ - if ((IS_SIGNATURE_POINTER (basetype) - || IS_SIGNATURE_REFERENCE (basetype)) - && TYPE_IDENTIFIER (basetype) != name) - basetype = SIGNATURE_TYPE (basetype); - - if ((IS_SIGNATURE (basetype) - && (instance_ptr = instance)) - || (lvalue_p (instance) - && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0))) - || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance))) - { - if (instance_ptr == error_mark_node) - return error_mark_node; - } - else if (TREE_CODE (instance) == NOP_EXPR - || TREE_CODE (instance) == CONSTRUCTOR) - { - /* A cast is not an lvalue. Initialize a fresh temp - with the value we are casting from, and proceed with - that temporary. We can't cast to a reference type, - so that simplifies the initialization to something - we can manage. */ - tree temp = get_temp_name (TREE_TYPE (instance), 0); - if (IS_AGGR_TYPE (TREE_TYPE (instance))) - expand_aggr_init (temp, instance, 0, flags); - else - { - store_init_value (temp, instance); - expand_decl_init (temp); - } - instance = temp; - instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); - } - else - { - if (TREE_CODE (instance) != CALL_EXPR) - my_friendly_abort (125); - if (TYPE_NEEDS_CONSTRUCTING (basetype)) - instance = build_cplus_new (basetype, instance, 0); - else - { - instance = get_temp_name (basetype, 0); - TREE_ADDRESSABLE (instance) = 1; - } - instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); - } - /* @@ Should we call comp_target_types here? */ - if (IS_SIGNATURE (basetype)) - inst_ptr_basetype = basetype; - else - inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr)); - if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype)) - basetype = inst_ptr_basetype; - else - { - instance_ptr = convert (build_pointer_type (basetype), instance_ptr); - if (instance_ptr == error_mark_node) - return error_mark_node; - } - } +void +enforce_access (basetype_path, decl) + tree basetype_path, decl; +{ + tree access = compute_access (basetype_path, decl); - /* After converting `instance_ptr' above, `inst_ptr_basetype' was - not updated, so we use `basetype' instead. */ - if (basetype_path == NULL_TREE - && IS_SIGNATURE (basetype)) - basetype_path = TYPE_BINFO (basetype); - else if (basetype_path == NULL_TREE || - BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (inst_ptr_basetype)) - basetype_path = TYPE_BINFO (inst_ptr_basetype); + 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) + { + cp_error_at ("`%+#D' %s", decl, + TREE_PROTECTED (decl) ? "is protected" + : "has protected accessibility"); + error ("within this context"); + } +} - result = build_field_call (basetype_path, instance_ptr, name, parms); - if (result) - return result; +/* Perform the conversions in CONVS on the expression EXPR. */ - if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype)) +static tree +convert_like (convs, expr) + tree convs, expr; +{ + if (ICS_BAD_FLAG (convs) + && TREE_CODE (convs) != USER_CONV + && TREE_CODE (convs) != AMBIG_CONV) + { + tree t = convs; + for (; t; t = TREE_OPERAND (t, 0)) { - if (TREE_SIDE_EFFECTS (instance_ptr)) - { - /* This action is needed because the instance is needed - for providing the base of the virtual function table. - Without using a SAVE_EXPR, the function we are building - may be called twice, or side effects on the instance - variable (such as a post-increment), may happen twice. */ - instance_ptr = save_expr (instance_ptr); - instance = build_indirect_ref (instance_ptr, NULL_PTR); - } - else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) + if (TREE_CODE (t) == USER_CONV) { - /* This happens when called for operator new (). */ - instance = build_indirect_ref (instance, NULL_PTR); + expr = convert_like (t, expr); + break; } - - need_vtbl = maybe_needed; + else if (TREE_CODE (t) == AMBIG_CONV) + return convert_like (t, expr); + else if (TREE_CODE (t) == IDENTITY_CONV) + break; } + return convert_for_initialization + (NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL, + "conversion", NULL_TREE, 0); } - if (TYPE_SIZE (basetype) == 0) + switch (TREE_CODE (convs)) { - /* This is worth complaining about, I think. */ - cp_error ("cannot lookup method in incomplete type `%T'", basetype); - return error_mark_node; + case USER_CONV: + { + struct z_candidate *cand + = WRAPPER_PTR (TREE_OPERAND (convs, 1)); + tree fn = cand->fn; + tree args; + + if (DECL_CONSTRUCTOR_P (fn)) + { + tree t = build_int_2 (0, 0); + TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); + + args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + args = scratch_tree_cons (NULL_TREE, integer_one_node, args); + args = scratch_tree_cons (NULL_TREE, t, args); + } + else + args = build_this (expr); + expr = build_over_call (cand, args, LOOKUP_NORMAL); + + /* If this is a constructor or a function returning an aggr type, + we need to build up a TARGET_EXPR. */ + if (DECL_CONSTRUCTOR_P (fn)) + expr = build_cplus_new (TREE_TYPE (convs), expr); + + return expr; + } + case IDENTITY_CONV: + if (type_unknown_p (expr)) + expr = instantiate_type (TREE_TYPE (convs), expr, 1); + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return expr; + case AMBIG_CONV: + /* Call build_user_type_conversion again for the error. */ + return build_user_type_conversion + (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL); + + default: + break; + }; + + expr = convert_like (TREE_OPERAND (convs, 0), expr); + if (expr == error_mark_node) + return error_mark_node; + + switch (TREE_CODE (convs)) + { + case RVALUE_CONV: + if (! IS_AGGR_TYPE (TREE_TYPE (convs))) + return expr; + /* else fall through */ + case BASE_CONV: + { + tree cvt_expr = build_user_type_conversion + (TREE_TYPE (convs), expr, LOOKUP_NORMAL); + if (!cvt_expr) + { + /* This can occur if, for example, the EXPR has incomplete + type. We can't check for that before attempting the + conversion because the type might be an incomplete + array type, which is OK if some constructor for the + destination type takes a pointer argument. */ + if (TYPE_SIZE (TREE_TYPE (expr)) == 0) + { + if (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1)) + incomplete_type_error (expr, TREE_TYPE (expr)); + else + cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'", + expr, TREE_TYPE (expr), TREE_TYPE (convs)); + } + else + cp_error ("could not convert `%E' to `%T'", + expr, TREE_TYPE (convs)); + return error_mark_node; + } + return cvt_expr; + } + + case REF_BIND: + return convert_to_reference + (TREE_TYPE (convs), expr, + CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + error_mark_node); + case LVALUE_CONV: + return decay_conversion (expr); + + default: + break; } + return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT, + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); +} - save_basetype = TYPE_MAIN_VARIANT (basetype); +/* ARG is being passed to a varargs function. Perform any conversions + required. Return the converted value. */ -#if 0 - if (all_virtual == 1 - && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT, - OPERATOR_METHOD_LENGTH) - || instance_ptr == NULL_TREE - || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0))) - all_virtual = 0; +tree +convert_arg_to_ellipsis (arg) + tree arg; +{ + if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE + && (TYPE_PRECISION (TREE_TYPE (arg)) + < TYPE_PRECISION (double_type_node))) + /* Convert `float' to `double'. */ + arg = cp_convert (double_type_node, arg); + else if (IS_AGGR_TYPE (TREE_TYPE (arg)) + && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg))) + cp_warning ("cannot pass objects of type `%T' through `...'", + TREE_TYPE (arg)); + else + /* Convert `short' and `char' to full-size `int'. */ + arg = default_conversion (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. */ + +tree +convert_default_arg (type, arg) + tree type, arg; +{ + arg = break_out_target_exprs (arg); + + if (TREE_CODE (arg) == CONSTRUCTOR) + { + arg = digest_init (type, arg, 0); + arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, + "default argument", 0, 0); + } + else + { + /* This could get clobbered by the following call. */ + if (TREE_HAS_CONSTRUCTOR (arg)) + arg = copy_node (arg); + + arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, + "default argument", 0, 0); +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + arg = default_conversion (arg); #endif + } + + return arg; +} - last = NULL_TREE; - for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm)) +static tree +build_over_call (cand, args, flags) + struct z_candidate *cand; + tree args; + int flags; +{ + tree fn = cand->fn; + tree convs = cand->convs; + tree converted_args = NULL_TREE; + tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree conv, arg, val; + int i = 0; + int is_method = 0; + + /* Give any warnings we noticed during overload resolution. */ + if (cand->warnings) + for (val = cand->warnings; val; val = TREE_CHAIN (val)) + joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1); + + if (DECL_FUNCTION_MEMBER_P (fn)) + enforce_access (cand->basetype_path, fn); + + if (args && TREE_CODE (args) != TREE_LIST) + args = build_scratch_list (NULL_TREE, args); + arg = args; + + /* The implicit parameters to a constructor are not considered by overload + resolution, and must be of the proper type. */ + if (DECL_CONSTRUCTOR_P (fn)) { - tree t = TREE_TYPE (TREE_VALUE (parm)); - if (TREE_CODE (t) == OFFSET_TYPE) + converted_args = expr_tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) { - /* Convert OFFSET_TYPE entities to their normal selves. */ - TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm)); - t = TREE_TYPE (TREE_VALUE (parm)); + converted_args = expr_tree_cons + (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); } - if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF - && TREE_CODE (t) == METHOD_TYPE) + } + /* Bypass access control for 'this' parameter. */ + else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + { + tree parmtype = TREE_VALUE (parm); + tree argtype = TREE_TYPE (TREE_VALUE (arg)); + if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i))) { - TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0); + 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); } -#if 0 - /* This breaks reference-to-array parameters. */ - if (TREE_CODE (t) == ARRAY_TYPE) + converted_args = expr_tree_cons + (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST), + converted_args); + parm = TREE_CHAIN (parm); + arg = TREE_CHAIN (arg); + ++i; + is_method = 1; + } + + for (; arg && parm; + parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i) + { + tree type = TREE_VALUE (parm); + + conv = TREE_VEC_ELT (convs, i); + if (ICS_BAD_FLAG (conv)) { - /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place. - This eliminates needless calls to `compute_conversion_costs'. */ - TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm)); - t = TREE_TYPE (TREE_VALUE (parm)); + tree t = conv; + val = TREE_VALUE (arg); + + for (; t; t = TREE_OPERAND (t, 0)) + { + if (TREE_CODE (t) == USER_CONV + || TREE_CODE (t) == AMBIG_CONV) + { + val = convert_like (t, val); + break; + } + else if (TREE_CODE (t) == IDENTITY_CONV) + break; + } + val = convert_for_initialization + (NULL_TREE, type, val, LOOKUP_NORMAL, + "argument passing", fn, i - is_method); } + else + val = convert_like (conv, TREE_VALUE (arg)); + +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + val = default_conversion (val); #endif - if (t == error_mark_node) - return error_mark_node; - last = build_tree_list (NULL_TREE, t); - parmtypes = chainon (parmtypes, last); + converted_args = expr_tree_cons (NULL_TREE, val, converted_args); } - if (instance && IS_SIGNATURE (basetype)) - { - /* @@ Should this be the constp/volatilep flags for the optr field - of the signature pointer? */ - constp = TYPE_READONLY (basetype); - volatilep = TYPE_VOLATILE (basetype); - parms = tree_cons (NULL_TREE, instance_ptr, parms); - } - else if (instance) - { - /* TREE_READONLY (instance) fails for references. */ - constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr))); - volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (instance_ptr))); - parms = tree_cons (NULL_TREE, instance_ptr, parms); - } - else + /* Default arguments */ + for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm)) { - /* Raw constructors are always in charge. */ - if (TYPE_USES_VIRTUAL_BASECLASSES (basetype) - && ! (flags & LOOKUP_HAS_IN_CHARGE)) + tree arg = TREE_PURPOSE (parm); + + if (DECL_TEMPLATE_INFO (fn)) { - flags |= LOOKUP_HAS_IN_CHARGE; - parms = tree_cons (NULL_TREE, integer_one_node, parms); - parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes); - } + /* This came from a template. Instantiate the default arg here, + not in tsubst. In the case of something like: - constp = 0; - volatilep = 0; - instance_ptr = build_int_2 (0, 0); - TREE_TYPE (instance_ptr) = build_pointer_type (basetype); - parms = tree_cons (NULL_TREE, instance_ptr, parms); - } + template + struct S { + static T t(); + void f(T = t()); + }; + + we must be careful to do name lookup in the scope of + S, rather than in the current class. */ + if (DECL_CLASS_SCOPE_P (fn)) + pushclass (DECL_REAL_CONTEXT (fn), 2); - parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes); + 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); + } - if (last == NULL_TREE) - last = parmtypes; + /* Ellipsis */ + for (; arg; arg = TREE_CHAIN (arg)) + converted_args + = expr_tree_cons (NULL_TREE, + convert_arg_to_ellipsis (TREE_VALUE (arg)), + converted_args); - /* Look up function name in the structure type definition. */ + converted_args = nreverse (converted_args); - if ((IDENTIFIER_HAS_TYPE_VALUE (name) - && ! IDENTIFIER_OPNAME_P (name) - && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)) - && TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE) - || name == constructor_name (basetype)) + /* Avoid actually calling copy constructors and copy assignment operators, + if possible. */ + if (DECL_CONSTRUCTOR_P (fn) + && TREE_VEC_LENGTH (convs) == 1 + && copy_args_p (fn)) { - tree tmp = NULL_TREE; - if (IDENTIFIER_TYPE_VALUE (name) == basetype - || name == constructor_name (basetype)) - tmp = TYPE_BINFO (basetype); + tree targ; + arg = TREE_CHAIN (converted_args); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + arg = TREE_CHAIN (arg); + arg = TREE_VALUE (arg); + + /* Pull out the real argument, disregarding const-correctness. */ + targ = arg; + while (TREE_CODE (targ) == NOP_EXPR + || TREE_CODE (targ) == NON_LVALUE_EXPR + || TREE_CODE (targ) == CONVERT_EXPR) + targ = TREE_OPERAND (targ, 0); + 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)) + targ = NULL_TREE; + } else - tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0); - - if (tmp != NULL_TREE) + targ = NULL_TREE; + + if (targ) + arg = targ; + else + arg = build_indirect_ref (arg, 0); + + /* [class.copy]: the copy constructor is implicitly defined even if + the implementation elided its use. */ + if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn))) + mark_used (fn); + + /* If we're creating a temp and we already have one, don't create a + new one. If we're not creating a temp but we get one, use + INIT_EXPR to collapse the temp into our target. Otherwise, if the + ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a + temp or an INIT_EXPR otherwise. */ + if (integer_zerop (TREE_VALUE (args))) { - name_kind = "constructor"; - - if (TYPE_USES_VIRTUAL_BASECLASSES (basetype) - && ! (flags & LOOKUP_HAS_IN_CHARGE)) + if (! real_lvalue_p (arg)) + return arg; + else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) { - /* Constructors called for initialization - only are never in charge. */ - tree tmplist; - - flags |= LOOKUP_HAS_IN_CHARGE; - tmplist = tree_cons (NULL_TREE, integer_zero_node, - TREE_CHAIN (parms)); - TREE_CHAIN (parms) = tmplist; - tmplist = tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes)); - TREE_CHAIN (parmtypes) = tmplist; + val = build (VAR_DECL, DECL_CONTEXT (fn)); + layout_decl (val, 0); + val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0); + TREE_SIDE_EFFECTS (val) = 1; + return val; } - basetype = BINFO_TYPE (tmp); } - else - name_kind = "method"; + else if (! real_lvalue_p (arg) + || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) + { + 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); + TREE_SIDE_EFFECTS (val) = 1; + return build_unary_op (ADDR_EXPR, val, 0); + } } - else - name_kind = "method"; - - if (basetype_path == NULL_TREE - || BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (basetype)) - basetype_path = TYPE_BINFO (basetype); - result = lookup_fnfields (basetype_path, name, - (flags & LOOKUP_COMPLAIN)); - if (result == error_mark_node) - return error_mark_node; - - -#if 0 - /* Now, go look for this method name. We do not find destructors here. - - Putting `void_list_node' on the end of the parmtypes - fakes out `build_decl_overload' into doing the right thing. */ - TREE_CHAIN (last) = void_list_node; - method_name = build_decl_overload (name, parmtypes, - 1 + (name == constructor_name (save_basetype) - || name == constructor_name_full (save_basetype))); - TREE_CHAIN (last) = NULL_TREE; -#endif - - for (pass = 0; pass < 2; pass++) + else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR] + && copy_args_p (fn) + && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CLASS_CONTEXT (fn))) { - struct candidate *candidates; - struct candidate *cp; - int len; - unsigned best = 1; + tree to = stabilize_reference + (build_indirect_ref (TREE_VALUE (converted_args), 0)); - /* This increments every time we go up the type hierarchy. - The idea is to prefer a function of the derived class if possible. */ - int b_or_d = 0; + arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0); - baselink = result; + /* 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); - if (pass > 0) - { - candidates - = (struct candidate *) alloca ((ever_seen+1) - * sizeof (struct candidate)); - bzero ((char *) candidates, (ever_seen + 1) * sizeof (struct candidate)); - cp = candidates; - len = list_length (parms); - ever_seen = 0; + val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); + TREE_SIDE_EFFECTS (val) = 1; + return val; + } - /* First see if a global function has a shot at it. */ - if (flags & LOOKUP_GLOBAL) - { - tree friend_parms; - tree parm = instance_ptr; + mark_used (fn); - if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE) - parm = convert_from_reference (parm); - else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE) - parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); - else - my_friendly_abort (167); + if (DECL_CLASS_SCOPE_P (fn) && IS_SIGNATURE (DECL_CONTEXT (fn))) + return build_signature_method_call (fn, converted_args); + else if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0) + { + tree t, *p = &TREE_VALUE (converted_args); + tree binfo = get_binfo + (DECL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0); + *p = convert_pointer_to_real (binfo, *p); + if (TREE_SIDE_EFFECTS (*p)) + *p = save_expr (*p); + t = build_pointer_type (TREE_TYPE (fn)); + fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn)); + TREE_TYPE (fn) = t; + } + else if (DECL_INLINE (fn)) + fn = inline_conversion (fn); + else + fn = build_addr_func (fn); - friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms)); + /* Recognize certain built-in functions so we can make tree-codes + other than CALL_EXPR. We do this when it enables fold-const.c + to do something useful. */ - cp->h_len = len; - cp->harshness = (struct harshness_code *) - alloca ((len + 1) * sizeof (struct harshness_code)); + if (TREE_CODE (fn) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL + && DECL_BUILT_IN (TREE_OPERAND (fn, 0))) + switch (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0))) + { + case BUILT_IN_ABS: + case BUILT_IN_LABS: + case BUILT_IN_FABS: + if (converted_args == 0) + return integer_zero_node; + return build_unary_op (ABS_EXPR, TREE_VALUE (converted_args), 0); + default: + break; + } - result = build_overload_call (name, friend_parms, 0, cp); - /* If it turns out to be the one we were actually looking for - (it was probably a friend function), the return the - good result. */ - if (TREE_CODE (result) == CALL_EXPR) - return result; + fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args); + if (TREE_TYPE (fn) == void_type_node) + return fn; + fn = require_complete_type (fn); + if (IS_AGGR_TYPE (TREE_TYPE (fn))) + fn = build_cplus_new (TREE_TYPE (fn), fn); + return convert_from_reference (fn); +} - while ((cp->h.code & EVIL_CODE) == 0) - { - /* non-standard uses: set the field to 0 to indicate - we are using a non-member function. */ - cp->u.field = 0; - if (cp->harshness[len].distance == 0 - && cp->h.code < best) - best = cp->h.code; - cp += 1; - } - } - } +static tree +build_new_method_call (instance, name, args, basetype_path, flags) + tree instance, name, args, basetype_path; + int flags; +{ + struct z_candidate *candidates = 0, *cand; + tree explicit_targs = NULL_TREE; + tree basetype, mem_args = NULL_TREE, fns, instance_ptr; + tree pretty_name; + tree user_args = args; + tree templates = NULL_TREE; + int template_only = 0; + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + explicit_targs = TREE_OPERAND (name, 1); + name = TREE_OPERAND (name, 0); + if (TREE_CODE (name) == TEMPLATE_DECL) + name = DECL_NAME (name); + template_only = 1; + } - while (baselink) - { - /* We have a hit (of sorts). If the parameter list is - "error_mark_node", or some variant thereof, it won't - match any methods. Since we have verified that the is - some method vaguely matching this one (in name at least), - silently return. - - Don't stop for friends, however. */ - basetype_path = TREE_PURPOSE (baselink); + /* If there is an extra argument for controlling virtual bases, + remove it for error reporting. */ + if (flags & LOOKUP_HAS_IN_CHARGE) + user_args = TREE_CHAIN (args); - function = TREE_VALUE (baselink); - if (TREE_CODE (basetype_path) == TREE_LIST) - basetype_path = TREE_VALUE (basetype_path); - basetype = BINFO_TYPE (basetype_path); + args = resolve_args (args); -#if 0 - /* Cast the instance variable if necessary. */ - if (basetype != TYPE_MAIN_VARIANT - (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))))) - { - if (basetype == save_basetype) - TREE_VALUE (parms) = instance_ptr; - else - { - tree type = build_pointer_type - (build_type_variant (basetype, constp, volatilep)); - TREE_VALUE (parms) = convert_force (type, instance_ptr, 0); - } - } + if (args == error_mark_node) + return error_mark_node; - /* FIXME: this is the wrong place to get an error. Hopefully - the access-control rewrite will make this change more cleanly. */ - if (TREE_VALUE (parms) == error_mark_node) - return error_mark_node; -#endif + if (instance == NULL_TREE) + basetype = BINFO_TYPE (basetype_path); + else + { + if (TREE_CODE (instance) == OFFSET_REF) + instance = resolve_offset_ref (instance); + if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) + instance = convert_from_reference (instance); + basetype = TREE_TYPE (instance); - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))) - function = DECL_CHAIN (function); + /* XXX this should be handled before we get here. */ + if (! IS_AGGR_TYPE (basetype) + && ! (TYPE_LANG_SPECIFIC (basetype) + && (IS_SIGNATURE_POINTER (basetype) + || IS_SIGNATURE_REFERENCE (basetype)))) + { + if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node) + cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", + name, instance, basetype); - for (; function; function = DECL_CHAIN (function)) - { -#ifdef GATHER_STATISTICS - n_inner_fields_searched++; -#endif - ever_seen++; - if (pass > 0) - found_fns = tree_cons (NULL_TREE, function, found_fns); + return error_mark_node; + } - /* Not looking for friends here. */ - if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE - && ! DECL_STATIC_FUNCTION_P (function)) - continue; + /* If `instance' is a signature pointer/reference and `name' is + not a constructor, we are calling a signature member function. + In that case set the `basetype' to the signature type. */ + if ((IS_SIGNATURE_POINTER (basetype) + || IS_SIGNATURE_REFERENCE (basetype)) + && TYPE_IDENTIFIER (basetype) != name) + basetype = SIGNATURE_TYPE (basetype); + } -#if 0 - if (pass == 0 - && DECL_ASSEMBLER_NAME (function) == method_name) - goto found; -#endif + if (basetype_path == NULL_TREE) + basetype_path = TYPE_BINFO (basetype); - if (pass > 0) - { - tree these_parms = parms; + if (instance) + { + instance_ptr = build_this (instance); -#ifdef GATHER_STATISTICS - n_inner_fields_searched++; -#endif - cp->h_len = len; - cp->harshness = (struct harshness_code *) - alloca ((len + 1) * sizeof (struct harshness_code)); - - if (DECL_STATIC_FUNCTION_P (function)) - these_parms = TREE_CHAIN (these_parms); - compute_conversion_costs (function, these_parms, cp, len); - - if ((cp->h.code & EVIL_CODE) == 0) - { - cp->u.field = function; - cp->function = function; - cp->basetypes = basetype_path; - - /* Don't allow non-converting constructors to convert. */ - if (flags & LOOKUP_ONLYCONVERTING - && DECL_LANG_SPECIFIC (function) - && DECL_NONCONVERTING_P (function)) - continue; - - /* No "two-level" conversions. */ - if (flags & LOOKUP_NO_CONVERSION - && (cp->h.code & USER_CODE)) - continue; - - cp++; - } - } - } - /* Now we have run through one link's member functions. - arrange to head-insert this link's links. */ - baselink = next_baselink (baselink); - b_or_d += 1; - /* Don't grab functions from base classes. lookup_fnfield will - do the work to get us down into the right place. */ - baselink = NULL_TREE; - } - if (pass == 0) + if (! template_only) { - tree igv = lookup_name_nonclass (name); - - /* No exact match could be found. Now try to find match - using default conversions. */ - if ((flags & LOOKUP_GLOBAL) && igv) - { - if (TREE_CODE (igv) == FUNCTION_DECL) - ever_seen += 1; - else if (TREE_CODE (igv) == TREE_LIST) - ever_seen += count_functions (igv); - } - - if (ever_seen == 0) - { - if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN)) - == LOOKUP_SPECULATIVELY) - return NULL_TREE; - - TREE_CHAIN (last) = void_list_node; - if (flags & LOOKUP_GLOBAL) - cp_error ("no global or member function `%D(%A)' defined", - name, parmtypes); - else - cp_error ("no member function `%T::%D(%A)' defined", - save_basetype, name, TREE_CHAIN (parmtypes)); - return error_mark_node; - } - continue; + /* XXX this should be handled before we get here. */ + fns = build_field_call (basetype_path, instance_ptr, name, args); + if (fns) + return fns; } + } + else + { + instance_ptr = build_int_2 (0, 0); + TREE_TYPE (instance_ptr) = build_pointer_type (basetype); + } - if (cp - candidates != 0) - { - /* Rank from worst to best. Then cp will point to best one. - Private fields have their bits flipped. For unsigned - numbers, this should make them look very large. - If the best alternate has a (signed) negative value, - then all we ever saw were private members. */ - if (cp - candidates > 1) - { - int n_candidates = cp - candidates; - extern int warn_synth; - TREE_VALUE (parms) = instance_ptr; - cp = ideal_candidate (save_basetype, candidates, - n_candidates, parms, len); - if (cp == (struct candidate *)0) - { - if (flags & LOOKUP_COMPLAIN) - { - TREE_CHAIN (last) = void_list_node; - cp_error ("call of overloaded %s `%D(%A)' is ambiguous", - name_kind, name, TREE_CHAIN (parmtypes)); - print_n_candidates (candidates, n_candidates); - } - return error_mark_node; - } - if (cp->h.code & EVIL_CODE) - return error_mark_node; - if (warn_synth - && DECL_NAME (cp->function) == ansi_opname[MODIFY_EXPR] - && DECL_ARTIFICIAL (cp->function) - && n_candidates == 2) - { - cp_warning ("using synthesized `%#D' for copy assignment", - cp->function); - cp_warning_at (" where cfront would use `%#D'", - candidates->function); - } - } - else if (cp[-1].h.code & EVIL_CODE) - { - if (flags & LOOKUP_COMPLAIN) - cp_error ("ambiguous type conversion requested for %s `%D'", - name_kind, name); - return error_mark_node; - } - else - cp--; + pretty_name + = (name == ctor_identifier ? constructor_name (basetype) : name); - /* The global function was the best, so use it. */ - if (cp->u.field == 0) - { - /* We must convert the instance pointer into a reference type. - Global overloaded functions can only either take - aggregate objects (which come for free from references) - or reference data types anyway. */ - TREE_VALUE (parms) = copy_node (instance_ptr); - TREE_TYPE (TREE_VALUE (parms)) = build_reference_type (TREE_TYPE (TREE_TYPE (instance_ptr))); - return build_function_call (cp->function, parms); - } + fns = lookup_fnfields (basetype_path, name, 1); - function = cp->function; - basetype_path = cp->basetypes; - if (! DECL_STATIC_FUNCTION_P (function)) - TREE_VALUE (parms) = cp->arg; - goto found_and_maybe_warn; + if (fns == error_mark_node) + return error_mark_node; + if (fns) + { + tree fn = TREE_VALUE (fns); + if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype) + && ! (flags & LOOKUP_HAS_IN_CHARGE)) + { + flags |= LOOKUP_HAS_IN_CHARGE; + args = scratch_tree_cons (NULL_TREE, integer_one_node, args); } - - if (flags & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY)) + mem_args = scratch_tree_cons (NULL_TREE, instance_ptr, args); + for (; fn; fn = OVL_NEXT (fn)) { - if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN)) - == LOOKUP_SPECULATIVELY) - return NULL_TREE; + tree t = OVL_CURRENT (fn); + tree this_arglist; - if (DECL_STATIC_FUNCTION_P (cp->function)) - parms = TREE_CHAIN (parms); - if (ever_seen) - { - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; - if (static_call_context - && TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE) - cp_error ("object missing in call to `%D'", cp->function); - else if (ever_seen > 1) - { - TREE_CHAIN (last) = void_list_node; - cp_error ("no matching function for call to `%T::%D (%A)%V'", - TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (instance_ptr))), - name, TREE_CHAIN (parmtypes), - TREE_TYPE (TREE_TYPE (instance_ptr))); - TREE_CHAIN (last) = NULL_TREE; - print_candidates (found_fns); - } - else - report_type_mismatch (cp, parms, name_kind); - return error_mark_node; - } + /* We can end up here for copy-init of same or base class. */ + if (name == ctor_identifier + && (flags & LOOKUP_ONLYCONVERTING) + && DECL_NONCONVERTING_P (t)) + continue; + if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE) + this_arglist = mem_args; + else + this_arglist = args; - if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN)) - == LOOKUP_COMPLAIN) + if (TREE_CODE (t) == TEMPLATE_DECL) { - cp_error ("%T has no method named %D", save_basetype, name); - return error_mark_node; + /* A member template. */ + templates = scratch_tree_cons (NULL_TREE, t, templates); + candidates = + add_template_candidate (candidates, t, explicit_targs, + this_arglist, + TREE_TYPE (name), flags, DEDUCE_CALL); } - return NULL_TREE; - } - continue; + else if (! template_only) + candidates = add_function_candidate (candidates, t, + this_arglist, flags); - found_and_maybe_warn: - if ((cp->harshness[0].code & CONST_CODE) - /* 12.1p2: Constructors can be called for const objects. */ - && ! DECL_CONSTRUCTOR_P (cp->function)) - { - if (flags & LOOKUP_COMPLAIN) - { - cp_error_at ("non-const member function `%D'", cp->function); - error ("called for const object at this point in file"); - } - /* Not good enough for a match. */ - else - return error_mark_node; + if (candidates) + candidates->basetype_path = TREE_PURPOSE (fns); } - goto found; } - /* Silently return error_mark_node. */ - return error_mark_node; - - found: - if (flags & LOOKUP_PROTECT) - access = compute_access (basetype_path, function); - if (access == access_private) + if (! any_viable (candidates)) { - if (flags & LOOKUP_COMPLAIN) - { - cp_error_at ("%s `%+#D' is %s", name_kind, function, - TREE_PRIVATE (function) ? "private" - : "from private base class"); - error ("within this context"); - } + /* 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))); + print_z_candidates (candidates); return error_mark_node; } - else if (access == access_protected) + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) { - if (flags & LOOKUP_COMPLAIN) - { - cp_error_at ("%s `%+#D' %s", name_kind, function, - TREE_PROTECTED (function) ? "is protected" - : "has protected accessibility"); - error ("within this context"); - } + cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name, + user_args); + print_z_candidates (candidates); return error_mark_node; } - /* From here on down, BASETYPE is the type that INSTANCE_PTR's - type (if it exists) is a pointer to. */ - - if (DECL_ABSTRACT_VIRTUAL_P (function) - && instance == C_C_D + if (DECL_ABSTRACT_VIRTUAL_P (cand->fn) + && instance == current_class_ref && DECL_CONSTRUCTOR_P (current_function_decl) && ! (flags & LOOKUP_NONVIRTUAL) - && value_member (function, get_abstract_virtuals (basetype))) - cp_error ("abstract virtual `%#D' called from constructor", function); - - if (IS_SIGNATURE (basetype) && static_call_context) - { - cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference", - basetype, name); - return error_mark_node; - } - else if (IS_SIGNATURE (basetype)) - return build_signature_method_call (basetype, instance, function, parms); - - function = DECL_MAIN_VARIANT (function); - /* Declare external function if necessary. */ - assemble_external (function); + && value_member (cand->fn, get_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); + + if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL) + && ((instance == current_class_ref && (dtor_label || ctor_label)) + || resolves_to_fixed_type_p (instance, 0))) + flags |= LOOKUP_NONVIRTUAL; + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && ! DECL_INITIAL (cand->fn)) + add_maybe_template (cand->fn, templates); + + return build_over_call + (cand, + TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args, + flags); +} -#if 1 - /* Is it a synthesized method that needs to be synthesized? */ - if (DECL_ARTIFICIAL (function) && ! flag_no_inline - && ! DECL_INITIAL (function) - /* Kludge: don't synthesize for default args. */ - && current_function_decl) - synthesize_method (function); -#endif +/* Returns non-zero iff standard conversion sequence ICS1 is a proper + subsequence of ICS2. */ - if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function) - && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)) - cp_warning ("inline function `%#D' called before definition", function); +static int +is_subseq (ics1, ics2) + tree ics1, ics2; +{ + /* We can assume that a conversion of the same code + between the same types indicates a subsequence since we only get + here if the types we are converting from are the same. */ - fntype = TREE_TYPE (function); - if (TREE_CODE (fntype) == POINTER_TYPE) - fntype = TREE_TYPE (fntype); - basetype = DECL_CLASS_CONTEXT (function); + while (TREE_CODE (ics1) == RVALUE_CONV + || TREE_CODE (ics1) == LVALUE_CONV) + ics1 = TREE_OPERAND (ics1, 0); - /* If we are referencing a virtual function from an object - of effectively static type, then there is no need - to go through the virtual function table. */ - if (need_vtbl == maybe_needed) + while (1) { - int fixed_type = resolves_to_fixed_type_p (instance, 0); - - if (all_virtual == 1 - && DECL_VINDEX (function) - && may_be_remote (basetype)) - need_vtbl = needed; - else if (DECL_VINDEX (function)) - need_vtbl = fixed_type ? unneeded : needed; - else - need_vtbl = not_needed; + while (TREE_CODE (ics2) == RVALUE_CONV + || TREE_CODE (ics2) == LVALUE_CONV) + ics2 = TREE_OPERAND (ics2, 0); + + if (TREE_CODE (ics2) == USER_CONV + || TREE_CODE (ics2) == AMBIG_CONV + || TREE_CODE (ics2) == IDENTITY_CONV) + /* At this point, ICS1 cannot be a proper subsequence of + ICS2. We can get a USER_CONV when we are comparing the + second standard conversion sequence of two user conversion + sequences. */ + return 0; + + 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)) + return 1; } +} - if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context - && !DECL_CONSTRUCTOR_P (function)) - { - /* Let's be nice to the user for now, and give reasonable - default behavior. */ - instance_ptr = current_class_decl; - if (instance_ptr) - { - if (basetype != current_class_type) - { - tree binfo = get_binfo (basetype, current_class_type, 1); - if (binfo == NULL_TREE) - { - error_not_base_type (function, current_class_type); - return error_mark_node; - } - else if (basetype == error_mark_node) - return error_mark_node; - } - } - /* Only allow a static member function to call another static member - function. */ - else if (DECL_LANG_SPECIFIC (function) - && !DECL_STATIC_FUNCTION_P (function)) - { - cp_error ("cannot call member function `%D' without object", - function); - return error_mark_node; - } - } +/* Returns non-zero iff DERIVED is derived from BASE. The inputs may + be any _TYPE nodes. */ - value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node; +static int +is_properly_derived_from (derived, base) + tree derived; + tree base; +{ + if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived)) + || !IS_AGGR_TYPE_CODE (TREE_CODE (base))) + return 0; - if (TYPE_SIZE (value_type) == 0) - { - if (flags & LOOKUP_COMPLAIN) - incomplete_type_error (0, value_type); - return error_mark_node; - } + /* 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) + && DERIVED_FROM_P (base, derived)); +} - if (DECL_STATIC_FUNCTION_P (function)) - parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), - TREE_CHAIN (parms), function, LOOKUP_NORMAL); - else if (need_vtbl == unneeded) +/* We build the ICS for an implicit object parameter as a pointer + conversion sequence. However, such a sequence should be compared + as if it were a reference conversion sequence. If ICS is the + implicit conversion sequence for an implicit object parameter, + modify it accordingly. */ + +static void +maybe_handle_implicit_object (ics) + tree* ics; +{ + if (ICS_THIS_FLAG (*ics)) { - int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL; - basetype = TREE_TYPE (instance); - if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype) - && TYPE_USES_COMPLEX_INHERITANCE (basetype)) - { - basetype = DECL_CLASS_CONTEXT (function); - instance_ptr = convert_pointer_to (basetype, instance_ptr); - instance = build_indirect_ref (instance_ptr, NULL_PTR); - } - parms = tree_cons (NULL_TREE, instance_ptr, - convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags)); + /* [over.match.funcs] + + For non-static member functions, the type of the + implicit object parameter is "reference to cv X" + where X is the class of which the function is a + member and cv is the cv-qualification on the member + function declaration. */ + tree t = *ics; + if (TREE_CODE (t) == QUAL_CONV) + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == PTR_CONV) + t = TREE_OPERAND (t, 0); + t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE); + t = build_conv (REF_BIND, + build_reference_type (TREE_TYPE (TREE_TYPE (*ics))), + t); + ICS_STD_RANK (t) = ICS_STD_RANK (*ics); + *ics = t; } - else - { - if ((flags & LOOKUP_NONVIRTUAL) == 0) - basetype = DECL_CONTEXT (function); +} - /* First parm could be integer_zerop with casts like - ((Object*)0)->Object::IsA() */ - if (!integer_zerop (TREE_VALUE (parms))) - { - /* Since we can't have inheritance with a union, doing get_binfo - on it won't work. We do all the convert_pointer_to_real - stuff to handle MI correctly...for unions, that's not - an issue, so we must short-circuit that extra work here. */ - tree tmp = TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))); - if (tmp != NULL_TREE && TREE_CODE (tmp) == UNION_TYPE) - instance_ptr = TREE_VALUE (parms); - else - { - tree binfo = get_binfo (basetype, - TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))), - 0); - instance_ptr = convert_pointer_to_real (binfo, TREE_VALUE (parms)); - } - instance_ptr - = convert_pointer_to (build_type_variant (basetype, - constp, volatilep), - instance_ptr); +/* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE + to the type the reference originally referred to, and return 1. + Otherwise, return 0. */ - if (TREE_CODE (instance_ptr) == COND_EXPR) - { - instance_ptr = save_expr (instance_ptr); - instance = build_indirect_ref (instance_ptr, NULL_PTR); - } - else if (TREE_CODE (instance_ptr) == NOP_EXPR - && TREE_CODE (TREE_OPERAND (instance_ptr, 0)) == ADDR_EXPR - && TREE_OPERAND (TREE_OPERAND (instance_ptr, 0), 0) == instance) - ; - /* The call to `convert_pointer_to' may return error_mark_node. */ - else if (TREE_CODE (instance_ptr) == ERROR_MARK) - return instance_ptr; - else if (instance == NULL_TREE - || TREE_CODE (instance) != INDIRECT_REF - || TREE_OPERAND (instance, 0) != instance_ptr) - instance = build_indirect_ref (instance_ptr, NULL_PTR); - } - parms = tree_cons (NULL_TREE, instance_ptr, - convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL)); +static int +maybe_handle_ref_bind (ics, target_type) + tree* ics; + tree* target_type; +{ + if (TREE_CODE (*ics) == REF_BIND) + { + /* [over.ics.rank] + + When a parameter of reference type binds directly + (_dcl.init.ref_) to an argument expression, the implicit + conversion sequence is the identity conversion, unless the + argument expression has a type that is a derived class of the + parameter type, in which case the implicit conversion + sequence is a derived-to-base Conversion. + + If the parameter binds directly to the result of applying a + conversion function to the argument expression, the implicit + conversion sequence is a user-defined conversion sequence + (_over.ics.user_), with the second standard conversion + sequence either an identity conversion or, if the conversion + function returns an entity of a type that is a derived class + of the parameter type, a derived-to-base Conversion. + + When a parameter of reference type is not bound directly to + an argument expression, the conversion sequence is the one + required to convert the argument expression to the underlying + type of the reference according to _over.best.ics_. + Conceptually, this conversion sequence corresponds to + copy-initializing a temporary of the underlying type with the + argument expression. Any difference in top-level + cv-qualification is subsumed by the initialization itself and + does not constitute a conversion. */ + + tree old_ics = *ics; + + *target_type = TREE_TYPE (TREE_TYPE (*ics)); + *ics = TREE_OPERAND (*ics, 0); + if (TREE_CODE (*ics) == IDENTITY_CONV + && is_properly_derived_from (TREE_TYPE (*ics), *target_type)) + *ics = build_conv (BASE_CONV, *target_type, *ics); + ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics); + ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics); + + return 1; } + + return 0; +} -#if 0 - /* Constructors do not overload method calls. */ - else if (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) - && name != TYPE_IDENTIFIER (basetype) - && (TREE_CODE (function) != FUNCTION_DECL - || strncmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)), - OPERATOR_METHOD_FORMAT, - OPERATOR_METHOD_LENGTH)) - && (may_be_remote (basetype) || instance != C_C_D)) - { - tree fn_as_int; +/* Compare two implicit conversion sequences according to the rules set out in + [over.ics.rank]. Return values: - parms = TREE_CHAIN (parms); + 1: ics1 is better than ics2 + -1: ics2 is better than ics1 + 0: ics1 and ics2 are indistinguishable */ - if (!all_virtual && TREE_CODE (function) == FUNCTION_DECL) - fn_as_int = build_unary_op (ADDR_EXPR, function, 0); - else - fn_as_int = convert (TREE_TYPE (default_conversion (function)), DECL_VINDEX (function)); - if (all_virtual == 1) - fn_as_int = convert (integer_type_node, fn_as_int); +static int +compare_ics (ics1, ics2) + tree ics1, ics2; +{ + tree from_type1; + tree from_type2; + tree to_type1; + tree to_type2; + tree deref_from_type1 = NULL_TREE; + tree deref_from_type2; + tree deref_to_type1; + tree deref_to_type2; + + /* REF_BINDING is non-zero if the result of the conversion sequence + is a reference type. In that case TARGET_TYPE is the + type referred to by the reference. */ + int ref_binding1; + int ref_binding2; + tree target_type1; + tree target_type2; + + /* Handle implicit object parameters. */ + maybe_handle_implicit_object (&ics1); + maybe_handle_implicit_object (&ics2); + + /* Handle reference parameters. */ + ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1); + ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2); + + /* [over.ics.rank] + + When comparing the basic forms of implicit conversion sequences (as + defined in _over.best.ics_) + + --a standard conversion sequence (_over.ics.scs_) is a better + conversion sequence than a user-defined conversion sequence + or an ellipsis conversion sequence, and + + --a user-defined conversion sequence (_over.ics.user_) is a + better conversion sequence than an ellipsis conversion sequence + (_over.ics.ellipsis_). */ + if (ICS_RANK (ics1) > ICS_RANK (ics2)) + return -1; + else if (ICS_RANK (ics1) < ICS_RANK (ics2)) + return 1; - result = build_opfncall (METHOD_CALL_EXPR, LOOKUP_NORMAL, instance, fn_as_int, parms); + if (ICS_RANK (ics1) == BAD_RANK) + { + /* Both ICS are bad. We try to make a decision based on what + would have happenned if they'd been good. */ + if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2) + || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2)) + return -1; + else if (ICS_USER_FLAG (ics1) < ICS_USER_FLAG (ics2) + || ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) + return 1; + + /* We couldn't make up our minds; try to figure it out below. */ + } - if (result == NULL_TREE) - { - compiler_error ("could not overload `operator->()(...)'"); - return error_mark_node; - } - else if (result == error_mark_node) - return error_mark_node; + if (ICS_ELLIPSIS_FLAG (ics1)) + /* Both conversions are ellipsis conversions. */ + return 0; -#if 0 - /* Do this if we want the result of operator->() to inherit - the type of the function it is subbing for. */ - TREE_TYPE (result) = value_type; -#endif + /* User-defined conversion sequence U1 is a better conversion sequence + than another user-defined conversion sequence U2 if they contain the + same user-defined conversion operator or constructor and if the sec- + ond standard conversion sequence of U1 is better than the second + standard conversion sequence of U2. */ - return result; + if (ICS_USER_FLAG (ics1)) + { + tree t1, t2; + + for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0)) + if (TREE_CODE (t1) == AMBIG_CONV) + return 0; + for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0)) + if (TREE_CODE (t2) == AMBIG_CONV) + return 0; + + if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) + return 0; + + /* We can just fall through here, after setting up + FROM_TYPE1 and FROM_TYPE2. */ + from_type1 = TREE_TYPE (t1); + from_type2 = TREE_TYPE (t2); } -#endif + else + { + /* We're dealing with two standard conversion sequences. - if (parms == error_mark_node - || (parms && TREE_CHAIN (parms) == error_mark_node)) - return error_mark_node; + [over.ics.rank] + + Standard conversion sequence S1 is a better conversion + sequence than standard conversion sequence S2 if + + --S1 is a proper subsequence of S2 (comparing the conversion + sequences in the canonical form defined by _over.ics.scs_, + excluding any Lvalue Transformation; the identity + conversion sequence is considered to be a subsequence of + any non-identity conversion sequence */ + + from_type1 = ics1; + while (TREE_CODE (from_type1) != IDENTITY_CONV) + from_type1 = TREE_OPERAND (from_type1, 0); + from_type1 = TREE_TYPE (from_type1); + + from_type2 = ics2; + while (TREE_CODE (from_type2) != IDENTITY_CONV) + from_type2 = TREE_OPERAND (from_type2, 0); + from_type2 = TREE_TYPE (from_type2); + } - if (need_vtbl == needed) + if (comptypes (from_type1, from_type2, 1)) { - function = build_vfn_ref (&TREE_VALUE (parms), instance, - DECL_VINDEX (function)); - TREE_TYPE (function) = build_pointer_type (fntype); + if (is_subseq (ics1, ics2)) + return 1; + if (is_subseq (ics2, ics1)) + return -1; } + /* Otherwise, one sequence cannot be a subsequence of the other; they + don't start with the same type. This can happen when comparing the + second standard conversion sequence in two user-defined conversion + sequences. */ - if (TREE_CODE (function) == FUNCTION_DECL) - GNU_xref_call (current_function_decl, - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function))); - - { - int is_constructor; - - if (TREE_CODE (function) == FUNCTION_DECL) - { - is_constructor = DECL_CONSTRUCTOR_P (function); - TREE_USED (function) = 1; - function = default_conversion (function); - } - else - { - is_constructor = 0; - function = default_conversion (function); - } - - result = build_nt (CALL_EXPR, function, parms, NULL_TREE); - - TREE_TYPE (result) = value_type; - TREE_SIDE_EFFECTS (result) = 1; - TREE_HAS_CONSTRUCTOR (result) = is_constructor; - result = convert_from_reference (result); - return result; - } -} + /* [over.ics.rank] -/* Similar to `build_method_call', but for overloaded non-member functions. - The name of this function comes through NAME. The name depends - on PARMS. + Or, if not that, - Note that this function must handle simple `C' promotions, - as well as variable numbers of arguments (...), and - default arguments to boot. + --the rank of S1 is better than the rank of S2 (by the rules + defined below): - If the overloading is successful, we return a tree node which - contains the call to the function. + Standard conversion sequences are ordered by their ranks: an Exact + Match is a better conversion than a Promotion, which is a better + conversion than a Conversion. - If overloading produces candidates which are probable, but not definite, - we hold these candidates. If FINAL_CP is non-zero, then we are free - to assume that final_cp points to enough storage for all candidates that - this function might generate. The `harshness' array is preallocated for - the first candidate, but not for subsequent ones. + Two conversion sequences with the same rank are indistinguishable + unless one of the following rules applies: - Note that the DECL_RTL of FUNCTION must be made to agree with this - function's new name. */ + --A conversion that is not a conversion of a pointer, or pointer + to member, to bool is better than another conversion that is such + a conversion. -tree -build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) - tree fnname, parms; - int flags; - struct candidate *final_cp; - int buildxxx; -{ - /* must check for overloading here */ - tree overload_name, functions, function, parm; - tree parmtypes = NULL_TREE, last = NULL_TREE; - register tree outer; - int length; - int parmlength = list_length (parms); + The ICS_STD_RANK automatically handles the pointer-to-bool rule, + so that we do not have to check it explicitly. */ + if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) + return 1; + else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1)) + return -1; - struct candidate *candidates, *cp; + to_type1 = TREE_TYPE (ics1); + to_type2 = TREE_TYPE (ics2); - if (final_cp) + if (TYPE_PTR_P (from_type1) + && TYPE_PTR_P (from_type2) + && TYPE_PTR_P (to_type1) + && TYPE_PTR_P (to_type2)) { - final_cp[0].h.code = 0; - final_cp[0].h.distance = 0; - final_cp[0].function = 0; - /* end marker. */ - final_cp[1].h.code = EVIL_CODE; + deref_from_type1 = TREE_TYPE (from_type1); + deref_from_type2 = TREE_TYPE (from_type2); + deref_to_type1 = TREE_TYPE (to_type1); + deref_to_type2 = TREE_TYPE (to_type2); } - - for (parm = parms; parm; parm = TREE_CHAIN (parm)) + /* The rules for pointers to members A::* are just like the rules + for pointers A*, except opposite: if B is derived from A then + A::* converts to B::*, not vice versa. For that reason, we + switch the from_ and to_ variables here. */ + else if (TYPE_PTRMEM_P (from_type1) + && TYPE_PTRMEM_P (from_type2) + && TYPE_PTRMEM_P (to_type1) + && TYPE_PTRMEM_P (to_type2)) { - register tree t = TREE_TYPE (TREE_VALUE (parm)); + deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1)); + deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2)); + deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1)); + deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2)); + } + else if (TYPE_PTRMEMFUNC_P (from_type1) + && TYPE_PTRMEMFUNC_P (from_type2) + && TYPE_PTRMEMFUNC_P (to_type1) + && TYPE_PTRMEMFUNC_P (to_type2)) + { + deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1); + deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2); + deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1); + deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2); + } - if (t == error_mark_node) + if (deref_from_type1 != NULL_TREE + && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1)) + && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2))) + { + /* This was one of the pointer or pointer-like conversions. + + [over.ics.rank] + + --If class B is derived directly or indirectly from class A, + conversion of B* to A* is better than conversion of B* to + void*, and conversion of A* to void* is better than + conversion of B* to void*. */ + if (TREE_CODE (deref_to_type1) == VOID_TYPE + && TREE_CODE (deref_to_type2) == VOID_TYPE) { - if (final_cp) - final_cp->h.code = EVIL_CODE; - return error_mark_node; + if (is_properly_derived_from (deref_from_type1, + deref_from_type2)) + return -1; + else if (is_properly_derived_from (deref_from_type2, + deref_from_type1)) + return 1; } - if (TREE_CODE (t) == OFFSET_TYPE) -#if 0 - /* This breaks reference-to-array parameters. */ - || TREE_CODE (t) == ARRAY_TYPE -#endif + 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 (TREE_CODE (deref_to_type2) == VOID_TYPE) + { + if (is_properly_derived_from (deref_from_type1, + deref_to_type1)) + return 1; + } + /* We know that DEREF_TO_TYPE1 is `void' here. */ + else if (is_properly_derived_from (deref_from_type1, + deref_to_type2)) + return -1; + } + } + else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1)) + && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2))) { - /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place. - Also convert OFFSET_TYPE entities to their normal selves. - This eliminates needless calls to `compute_conversion_costs'. */ - TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm)); - t = TREE_TYPE (TREE_VALUE (parm)); + /* [over.ics.rank] + + --If class B is derived directly or indirectly from class A + and class C is derived directly or indirectly from B, + + --conversion of C* to B* is better than conversion of C* to + A*, + + --conversion of B* to A* is better than conversion of C* to + A* */ + if (comptypes (deref_from_type1, deref_from_type2, 1)) + { + if (is_properly_derived_from (deref_to_type1, + deref_to_type2)) + return 1; + else if (is_properly_derived_from (deref_to_type2, + deref_to_type1)) + return -1; + } + else if (comptypes (deref_to_type1, deref_to_type2, 1)) + { + if (is_properly_derived_from (deref_from_type2, + deref_from_type1)) + return 1; + else if (is_properly_derived_from (deref_from_type1, + deref_from_type2)) + return -1; + } } - last = build_tree_list (NULL_TREE, t); - parmtypes = chainon (parmtypes, last); } - if (last) - TREE_CHAIN (last) = void_list_node; - else - parmtypes = void_list_node; - - if (is_overloaded_fn (fnname)) + else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1)) + && comptypes (from_type1, from_type2, 1)) { - functions = fnname; - if (TREE_CODE (fnname) == TREE_LIST) - fnname = TREE_PURPOSE (functions); - else if (TREE_CODE (fnname) == FUNCTION_DECL) - fnname = DECL_NAME (functions); + /* [over.ics.rank] + + --binding of an expression of type C to a reference of type + B& is better than binding an expression of type C to a + reference of type A& + + --conversion of C to B is better than conversion of C to A, */ + if (is_properly_derived_from (from_type1, to_type1) + && is_properly_derived_from (from_type1, to_type2)) + { + if (is_properly_derived_from (to_type1, to_type2)) + return 1; + else if (is_properly_derived_from (to_type2, to_type1)) + return -1; + } } - else - functions = lookup_name_nonclass (fnname); - - if (functions == NULL_TREE) + else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1)) + && comptypes (to_type1, to_type2, 1)) { - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; - if (flags & LOOKUP_COMPLAIN) - error ("only member functions apply"); - if (final_cp) - final_cp->h.code = EVIL_CODE; - return error_mark_node; - } + /* [over.ics.rank] - if (TREE_CODE (functions) == FUNCTION_DECL && ! IDENTIFIER_OPNAME_P (fnname)) - { - functions = DECL_MAIN_VARIANT (functions); - if (final_cp) + --binding of an expression of type B to a reference of type + A& is better than binding an expression of type C to a + reference of type A&, + + --onversion of B to A is better than conversion of C to A */ + if (is_properly_derived_from (from_type1, to_type1) + && is_properly_derived_from (from_type2, to_type1)) { - /* We are just curious whether this is a viable alternative or - not. */ - compute_conversion_costs (functions, parms, final_cp, parmlength); - return functions; + if (is_properly_derived_from (from_type2, from_type1)) + return 1; + else if (is_properly_derived_from (from_type1, from_type2)) + return -1; } - else - return build_function_call_real (functions, parms, 1, flags); } - if (TREE_CODE (functions) == TREE_LIST - && TREE_VALUE (functions) == NULL_TREE) - { - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; + /* [over.ics.rank] + + --S1 and S2 differ only in their qualification conversion and yield + similar types T1 and T2 (_conv.qual_), respectively, and the cv- + qualification signature of type T1 is a proper subset of the cv- + qualification signature of type T2 */ + if (TREE_CODE (ics1) == QUAL_CONV + && TREE_CODE (ics2) == QUAL_CONV + && comptypes (from_type1, from_type2, 1)) + return comp_cv_qual_signature (to_type1, to_type2); + + /* [over.ics.rank] + + --S1 and S2 are reference bindings (_dcl.init.ref_), and the + types to which the references refer are the same type except for + top-level cv-qualifiers, and the type to which the reference + initialized by S2 refers is more cv-qualified than the type to + which the reference initialized by S1 refers */ - if (flags & LOOKUP_COMPLAIN) - cp_error ("function `%D' declared overloaded, but no instances of that function declared", - TREE_PURPOSE (functions)); - if (final_cp) - final_cp->h.code = EVIL_CODE; - return error_mark_node; - } + if (ref_binding1 && ref_binding2 + && comptypes (TYPE_MAIN_VARIANT (to_type1), + TYPE_MAIN_VARIANT (to_type2), 1)) + return comp_cv_qualification (target_type2, target_type1); - length = count_functions (functions); - - if (final_cp) - candidates = final_cp; - else + /* Neither conversion sequence is better than the other. */ + return 0; +} + +/* The source type for this standard conversion sequence. */ + +static tree +source_type (t) + tree t; +{ + for (;; t = TREE_OPERAND (t, 0)) { - candidates - = (struct candidate *)alloca ((length+1) * sizeof (struct candidate)); - bzero ((char *) candidates, (length + 1) * sizeof (struct candidate)); + if (TREE_CODE (t) == USER_CONV + || TREE_CODE (t) == AMBIG_CONV + || TREE_CODE (t) == IDENTITY_CONV) + return TREE_TYPE (t); } + my_friendly_abort (1823); +} + +/* Note a warning about preferring WINNER to LOSER. We do this by storing + a pointer to LOSER and re-running joust to produce the warning if WINNER + is actually used. */ + +static void +add_warning (winner, loser) + struct z_candidate *winner, *loser; +{ + winner->warnings = expr_tree_cons (NULL_PTR, + build_expr_ptr_wrapper (loser), + winner->warnings); +} - cp = candidates; +/* Compare two candidates for overloading as described in + [over.match.best]. Return values: - my_friendly_assert (is_overloaded_fn (functions), 169); + 1: cand1 is better than cand2 + -1: cand2 is better than cand1 + 0: cand1 and cand2 are indistinguishable */ - functions = get_first_fn (functions); +static int +joust (cand1, cand2, warn) + struct z_candidate *cand1, *cand2; + int warn; +{ + int winner = 0; + int i, off1 = 0, off2 = 0, len; + + /* Candidates that involve bad conversions are always worse than those + that don't. */ + if (cand1->viable > cand2->viable) + return 1; + if (cand1->viable < cand2->viable) + 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 + ICSi(F2), and then */ + + /* for some argument j, ICSj(F1) is a better conversion sequence than + ICSj(F2) */ + + /* For comparing static and non-static member functions, we ignore the + implicit object parameter of the non-static function. The WP says to + pretend that the static function has an object parm, but that won't + work with operator overloading. */ + len = TREE_VEC_LENGTH (cand1->convs); + if (len != TREE_VEC_LENGTH (cand2->convs)) + { + if (DECL_STATIC_FUNCTION_P (cand1->fn) + && ! DECL_STATIC_FUNCTION_P (cand2->fn)) + off2 = 1; + else if (! DECL_STATIC_FUNCTION_P (cand1->fn) + && DECL_STATIC_FUNCTION_P (cand2->fn)) + { + off1 = 1; + --len; + } + else + my_friendly_abort (42); + } - /* OUTER is the list of FUNCTION_DECLS, in a TREE_LIST. */ - for (outer = functions; outer; outer = DECL_CHAIN (outer)) + for (i = 0; i < len; ++i) { - int template_cost = 0; - function = outer; - if (TREE_CODE (function) != FUNCTION_DECL - && ! (TREE_CODE (function) == TEMPLATE_DECL - && ! DECL_TEMPLATE_IS_CLASS (function) - && TREE_CODE (DECL_TEMPLATE_RESULT (function)) == FUNCTION_DECL)) + tree t1 = TREE_VEC_ELT (cand1->convs, i+off1); + tree t2 = TREE_VEC_ELT (cand2->convs, i+off2); + int comp = compare_ics (t1, t2); + + if (comp != 0) { - enum tree_code code = TREE_CODE (function); - if (code == TEMPLATE_DECL) - code = TREE_CODE (DECL_TEMPLATE_RESULT (function)); - if (code == CONST_DECL) - cp_error_at - ("enumeral value `%D' conflicts with function of same name", - function); - else if (code == VAR_DECL) + if (warn_sign_promo + && ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK + && TREE_CODE (t1) == STD_CONV + && TREE_CODE (t2) == STD_CONV + && TREE_CODE (TREE_TYPE (t1)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (t2)) == INTEGER_TYPE + && (TYPE_PRECISION (TREE_TYPE (t1)) + == TYPE_PRECISION (TREE_TYPE (t2))) + && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t1, 0))) + || (TREE_CODE (TREE_TYPE (TREE_OPERAND (t1, 0))) + == ENUMERAL_TYPE))) { - if (TREE_STATIC (function)) - cp_error_at - ("variable `%D' conflicts with function of same name", - function); + tree type = TREE_TYPE (TREE_OPERAND (t1, 0)); + tree type1, type2; + struct z_candidate *w, *l; + if (comp > 0) + type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2), + w = cand1, l = cand2; + else + type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1), + w = cand2, l = cand1; + + if (warn) + { + cp_warning ("passing `%T' chooses `%T' over `%T'", + type, type1, type2); + cp_warning (" in call to `%D'", w->fn); + } else - cp_error_at - ("constant field `%D' conflicts with function of same name", - function); + add_warning (w, l); } - else if (code == TYPE_DECL) - continue; - else - my_friendly_abort (2); - error ("at this point in file"); - continue; - } - if (TREE_CODE (function) == TEMPLATE_DECL) - { - int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function)); - tree *targs = (tree *) alloca (sizeof (tree) * ntparms); - int i; - i = type_unification (DECL_TEMPLATE_PARMS (function), targs, - TYPE_ARG_TYPES (TREE_TYPE (function)), - parms, &template_cost, 0); - if (i == 0) - function = instantiate_template (function, targs); + if (winner && comp != winner) + { + winner = 0; + goto tweak; + } + winner = comp; } + } - if (TREE_CODE (function) == TEMPLATE_DECL) + /* warn about confusing overload resolution for user-defined conversions, + either between a constructor and a conversion op, or between two + conversion ops. */ + if (winner && cand1->second_conv + && ((DECL_CONSTRUCTOR_P (cand1->fn) + != 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)))) + { + int comp = compare_ics (cand1->second_conv, cand2->second_conv); + if (comp != winner) { - /* Unconverted template -- failed match. */ - cp->function = function; - cp->u.bad_arg = -4; - cp->h.code = EVIL_CODE; + struct z_candidate *w, *l; + if (winner == 1) + w = cand1, l = cand2; + else + w = cand2, l = cand1; + if (warn) + { + tree source = source_type (TREE_VEC_ELT (w->convs, 0)); + if (! DECL_CONSTRUCTOR_P (w->fn)) + source = TREE_TYPE (source); + cp_warning ("choosing `%D' over `%D'", w->fn, l->fn); + cp_warning (" for conversion from `%T' to `%T'", + source, TREE_TYPE (w->second_conv)); + cp_warning (" because conversion sequence for the argument is better"); + } + else + add_warning (w, l); } - else - { - struct candidate *cp2; - - /* Check that this decl is not the same as a function that's in - the list due to some template instantiation. */ - cp2 = candidates; - while (cp2 != cp) - if (cp2->function == function) - break; - else - cp2 += 1; - if (cp2->function == function) - continue; + } - function = DECL_MAIN_VARIANT (function); + if (winner) + return winner; - /* Can't use alloca here, since result might be - passed to calling function. */ - cp->h_len = parmlength; - cp->harshness = (struct harshness_code *) - oballoc ((parmlength + 1) * sizeof (struct harshness_code)); + /* or, if not that, + F1 is a non-template function and F2 is a template function */ - compute_conversion_costs (function, parms, cp, parmlength); + if (! cand1->template && cand2->template) + return 1; + else if (cand1->template && ! cand2->template) + return -1; + else if (cand1->template && cand2->template) + winner = more_specialized + (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template), + NULL_TREE); + + /* or, if not that, + the context is an initialization by user-defined conversion (see + _dcl.init_ and _over.match.user_) and the standard conversion + sequence from the return type of F1 to the destination type (i.e., + the type of the entity being initialized) is a better conversion + sequence than the standard conversion sequence from the return type + of F2 to the destination type. */ + + if (! winner && cand1->second_conv) + winner = compare_ics (cand1->second_conv, cand2->second_conv); + + /* If the built-in candidates are the same, arbitrarily pick one. */ + if (! winner && cand1->fn == cand2->fn + && 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)) + break; + if (i == TREE_VEC_LENGTH (cand1->convs)) + return 1; - /* Make sure this is clear as well. */ - cp->h.int_penalty += template_cost; + /* Kludge around broken overloading rules whereby + Integer a, b; test ? a : b; is ambiguous, since there's a builtin + that takes references and another that takes values. */ + if (cand1->fn == ansi_opname[COND_EXPR]) + { + tree c1 = TREE_VEC_ELT (cand1->convs, 1); + tree c2 = TREE_VEC_ELT (cand2->convs, 1); + tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1))); + tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2))); - if ((cp[0].h.code & EVIL_CODE) == 0) + if (comptypes (t1, t2, 1)) { - cp[1].h.code = EVIL_CODE; - cp++; + if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND) + return 1; + if (TREE_CODE (c1) != REF_BIND && TREE_CODE (c2) == REF_BIND) + return -1; } } } - if (cp - candidates) +tweak: + + /* Extension: If the worst conversion for one candidate is worse than the + worst conversion for the other, take the first. */ + if (! winner && ! pedantic) { - tree rval = error_mark_node; + int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK; - /* Leave marker. */ - cp[0].h.code = EVIL_CODE; - if (cp - candidates > 1) + for (i = 0; i < len; ++i) { - struct candidate *best_cp - = ideal_candidate (NULL_TREE, candidates, - cp - candidates, parms, parmlength); - if (best_cp == (struct candidate *)0) - { - if (flags & LOOKUP_COMPLAIN) - { - cp_error ("call of overloaded `%D' is ambiguous", fnname); - print_n_candidates (candidates, cp - candidates); - } - return error_mark_node; - } - else - rval = best_cp->function; + if (ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)) > rank1) + rank1 = ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)); + if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2) + rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)); } + + if (rank1 < rank2) + return 1; + if (rank1 > rank2) + return -1; + } + + return winner; +} + +/* Given a list of candidates for overloading, find the best one, if any. + This algorithm has a worst case of O(2n) (winner is last), and a best + case of O(n/2) (totally ambiguous); much better than a sorting + algorithm. */ + +static struct z_candidate * +tourney (candidates) + struct z_candidate *candidates; +{ + struct z_candidate *champ = candidates, *challenger; + int fate; + int champ_compared_to_predecessor = 0; + + /* Walk through the list once, comparing each current champ to the next + candidate, knocking out a candidate or two with each comparison. */ + + for (challenger = champ->next; challenger; ) + { + fate = joust (champ, challenger, 0); + if (fate == 1) + challenger = challenger->next; else { - cp -= 1; - if (cp->h.code & EVIL_CODE) + if (fate == 0) { - if (flags & LOOKUP_COMPLAIN) - error ("type conversion ambiguous"); + champ = challenger->next; + if (champ == 0) + return 0; + champ_compared_to_predecessor = 0; } else - rval = cp->function; + { + champ = challenger; + champ_compared_to_predecessor = 1; + } + + challenger = champ->next; } + } - if (final_cp) - return rval; + /* Make sure the champ is better than all the candidates it hasn't yet + been compared to. */ - return buildxxx ? build_function_call_real (rval, parms, 0, flags) - : build_function_call_real (rval, parms, 1, flags); + for (challenger = candidates; + challenger != champ + && !(champ_compared_to_predecessor && challenger->next == champ); + challenger = challenger->next) + { + fate = joust (champ, challenger, 0); + if (fate != 1) + return 0; } - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; - - if (flags & LOOKUP_COMPLAIN) - report_type_mismatch (cp, parms, "function", - decl_as_string (cp->function, 1)); - - return error_mark_node; + return champ; } -tree -build_overload_call (fnname, parms, flags, final_cp) - tree fnname, parms; - int flags; - struct candidate *final_cp; +int +can_convert (to, from) + tree to, from; { - return build_overload_call_real (fnname, parms, flags, final_cp, 0); + tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL); + return (t && ! ICS_BAD_FLAG (t)); } -tree -build_overload_call_maybe (fnname, parms, flags, final_cp) - tree fnname, parms; - int flags; - struct candidate *final_cp; +int +can_convert_arg (to, from, arg) + tree to, from, arg; { - return build_overload_call_real (fnname, parms, flags, final_cp, 1); + tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); + return (t && ! ICS_BAD_FLAG (t)); } diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c index e289304..8a61bf8 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, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -20,15 +20,16 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* High-level class interface. */ +/* High-level class interface. */ #include "config.h" +#include "system.h" #include "tree.h" -#include #include "cp-tree.h" #include "flags.h" #include "rtl.h" #include "output.h" +#include "toplev.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc @@ -37,7 +38,7 @@ Boston, MA 02111-1307, USA. */ extern struct obstack permanent_obstack; /* This is how we tell when two virtual member functions are really the - same. */ + same. */ #define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL)) extern void set_class_shadows PROTO ((tree)); @@ -72,7 +73,9 @@ struct class_level int unused; }; -tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */ +/* The current_class_ptr is the pointer to the current class. + current_class_ref is the actual current class. */ +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 */ @@ -80,26 +83,76 @@ tree current_class_type; /* _TYPE: the type of the current class */ tree previous_class_type; /* _TYPE: the previous type that was a class */ tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list when leaving an outermost class scope. */ + +struct base_info; + static tree get_vfield_name PROTO((tree)); -tree the_null_vtable_entry; +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)); +static tree get_basefndecls PROTO((tree, tree)); +static void set_rtti_entry PROTO((tree, tree, tree)); +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)); +static void add_virtual_function PROTO((tree *, tree *, int *, tree, tree)); +static tree delete_duplicate_fields_1 PROTO((tree, tree)); +static void delete_duplicate_fields PROTO((tree)); +static void finish_struct_bits PROTO((tree, int)); +static int alter_access PROTO((tree, tree, tree, tree)); +static void handle_using_decl PROTO((tree, tree, tree, tree)); +static int overrides PROTO((tree, tree)); +static int strictly_overrides PROTO((tree, tree)); +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)); +static void modify_all_vtables PROTO((tree, tree, tree)); +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 *)); /* Way of stacking language names. */ tree *current_lang_base, *current_lang_stack; int current_lang_stacksize; /* Names of languages we recognize. */ -tree lang_name_c, lang_name_cplusplus; +tree lang_name_c, lang_name_cplusplus, lang_name_java; tree current_lang_name; -char *dont_allow_type_definitions; - /* When layout out an aggregate type, the size of the basetypes (virtual and non-virtual) is passed to layout_record via this node. */ static tree base_layout_decl; +/* Constants used for access control. */ +tree access_default_node; /* 0 */ +tree access_public_node; /* 1 */ +tree access_protected_node; /* 2 */ +tree access_private_node; /* 3 */ +tree access_default_virtual_node; /* 4 */ +tree access_public_virtual_node; /* 5 */ +tree access_protected_virtual_node; /* 6 */ +tree access_private_virtual_node; /* 7 */ + /* Variables shared between class.c and call.c. */ +#ifdef GATHER_STATISTICS int n_vtables = 0; int n_vtable_entries = 0; int n_vtable_searches = 0; @@ -108,9 +161,11 @@ int n_convert_harshness = 0; int n_compute_conversion_costs = 0; int n_build_method_call = 0; int n_inner_fields_searched = 0; +#endif /* Virtual baseclass things. */ -tree + +static tree build_vbase_pointer (exp, type) tree exp, type; { @@ -118,12 +173,13 @@ build_vbase_pointer (exp, 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), 0, 0); + return build_component_ref (exp, get_identifier (name), NULL_TREE, 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. */ -int + If we are going to be wrong, we must be conservative, and return 0. */ + +static int complete_type_p (expr) tree expr; { @@ -143,20 +199,20 @@ complete_type_p (expr) case CALL_EXPR: if (! TREE_HAS_CONSTRUCTOR (expr)) break; - /* fall through... */ + /* fall through... */ case VAR_DECL: case FIELD_DECL: if (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (expr))) && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type) return 1; - /* fall through... */ + /* fall through... */ case TARGET_EXPR: case PARM_DECL: if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type) return 1; - /* fall through... */ + /* fall through... */ case PLUS_EXPR: default: break; @@ -174,6 +230,7 @@ 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'. */ + tree build_vbase_path (code, type, expr, path, alias_this) enum tree_code code; @@ -183,21 +240,28 @@ build_vbase_path (code, type, expr, path, alias_this) register int changed = 0; tree last = NULL_TREE, last_virtual = NULL_TREE; int nonnull = 0; - int fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull); + int fixed_type_p; tree null_expr = 0, nonnull_expr; tree basetype; tree offset = integer_zero_node; + 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 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) */ + 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. */ + for a testcase. */ fixed_type_p = complete_type_p (expr); +#endif if (!fixed_type_p && TREE_SIDE_EFFECTS (expr)) expr = save_expr (expr); @@ -207,6 +271,7 @@ build_vbase_path (code, type, expr, path, alias_this) { tree reverse_path = NULL_TREE; + push_expression_obstack (); while (path) { tree r = copy_node (path); @@ -215,6 +280,7 @@ build_vbase_path (code, type, expr, path, alias_this) path = BINFO_INHERITANCE_CHAIN (path); } path = reverse_path; + pop_obstacks (); } basetype = BINFO_TYPE (path); @@ -230,11 +296,10 @@ build_vbase_path (code, type, expr, path, alias_this) if (changed) { - extern int flag_assume_nonnull_objects; tree ind; /* We already check for ambiguous things in the caller, just - find a path. */ + find a path. */ if (last) { tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0); @@ -278,7 +343,8 @@ build_vbase_path (code, type, expr, path, alias_this) if (null_expr) { TREE_OPERAND (expr, 2) = nonnull_expr; - TREE_TYPE (TREE_OPERAND (expr, 1)) = TREE_TYPE (nonnull_expr); + TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1)) + = TREE_TYPE (nonnull_expr); } else expr = nonnull_expr; @@ -310,8 +376,11 @@ build_vbase_path (code, type, expr, path, alias_this) if (TREE_INT_CST_LOW (offset)) { /* Bash types to make the backend happy. */ - offset = convert (type, offset); + offset = cp_convert (type, offset); +#if 0 + /* This shouldn't be necessary. (mrs) */ 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. @@ -349,27 +418,20 @@ build_vbase_path (code, type, expr, path, alias_this) /* Virtual function things. */ -/* Virtual functions to be dealt with after laying out our base - classes. We do all overrides after we layout virtual base classes. - */ -static tree pending_hard_virtuals; -static int doing_hard_virtuals; - /* Build an entry in the virtual function table. DELTA is the offset for the `this' pointer. PFN is an ADDR_EXPR containing a pointer to the virtual function. Note that the index (DELTA2) in the virtual function table is always 0. */ -tree + +static tree build_vtable_entry (delta, pfn) tree delta, pfn; { - if (flag_vtable_thunks) { HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta); - extern tree make_thunk (); - if (idelta) + if (idelta && ! DECL_ABSTRACT_VIRTUAL_P (TREE_OPERAND (pfn, 0))) { pfn = build1 (ADDR_EXPR, vtable_entry_type, make_thunk (pfn, idelta)); @@ -384,25 +446,23 @@ build_vtable_entry (delta, pfn) else { extern int flag_huge_objects; - tree elems = tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, integer_zero_node, - build_tree_list (NULL_TREE, pfn))); + tree elems = expr_tree_cons (NULL_TREE, delta, + expr_tree_cons (NULL_TREE, integer_zero_node, + build_expr_list (NULL_TREE, pfn))); tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems); - /* DELTA is constructed by `size_int', which means it may be an - unsigned quantity on some platforms. Therefore, we cannot use - `int_fits_type_p', because when DELTA is really negative, - `force_fit_type' will make it look like a very large number. */ - - if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node)) - < TREE_INT_CST_LOW (delta)) - || (TREE_INT_CST_LOW (delta) - < TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node)))) - if (flag_huge_objects) - sorry ("object size exceeds built-in limit for virtual function table implementation"); - else - sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects"); + /* DELTA used to be constructed by `size_int' and/or size_binop, + which caused overflow problems when it was negative. That should + be fixed now. */ + if (! int_fits_type_p (delta, delta_type_node)) + { + if (flag_huge_objects) + sorry ("object size exceeds built-in limit for virtual function table implementation"); + else + sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects"); + } + TREE_CONSTANT (entry) = 1; TREE_STATIC (entry) = 1; TREE_READONLY (entry) = 1; @@ -416,22 +476,21 @@ build_vtable_entry (delta, pfn) } /* Given an object INSTANCE, return an expression which yields the - virtual function corresponding to INDEX. There are many special - cases for INSTANCE which we take care of here, mainly to avoid - creating extra tree nodes when we don't have to. */ + virtual function vtable element corresponding to INDEX. There are + many special cases for INSTANCE which we take care of here, mainly + to avoid creating extra tree nodes when we don't have to. */ + tree -build_vfn_ref (ptr_to_instptr, instance, idx) - tree *ptr_to_instptr, instance; - tree idx; +build_vtbl_ref (instance, idx) + tree instance, idx; { - extern int building_cleanup; tree vtbl, aref; tree basetype = TREE_TYPE (instance); if (TREE_CODE (basetype) == REFERENCE_TYPE) basetype = TREE_TYPE (basetype); - if (instance == C_C_D) + if (instance == current_class_ref) vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), NULL_PTR); else @@ -479,34 +538,53 @@ build_vfn_ref (ptr_to_instptr, instance, idx) assemble_external (vtbl); aref = build_array_ref (vtbl, idx); - /* Save the intermediate result in a SAVE_EXPR so we don't have to - compute each component of the virtual function pointer twice. */ - if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF) - TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); + return aref; +} +/* Given an object INSTANCE, return an expression which yields the + virtual function corresponding to INDEX. There are many special + cases for INSTANCE which we take care of here, mainly to avoid + creating extra tree nodes when we don't have to. */ + +tree +build_vfn_ref (ptr_to_instptr, instance, idx) + tree *ptr_to_instptr, instance; + tree idx; +{ + tree aref = build_vtbl_ref (instance, idx); + + /* When using thunks, there is no extra delta, and we get the pfn + directly. */ if (flag_vtable_thunks) return aref; - else + + if (ptr_to_instptr) { - if (ptr_to_instptr) - *ptr_to_instptr - = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), - *ptr_to_instptr, - convert (ptrdiff_type_node, - build_component_ref (aref, delta_identifier, 0, 0))); - return build_component_ref (aref, pfn_identifier, 0, 0); + /* Save the intermediate result in a SAVE_EXPR so we don't have to + compute each component of the virtual function pointer twice. */ + if (TREE_CODE (aref) == INDIRECT_REF) + TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); + + *ptr_to_instptr + = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), + *ptr_to_instptr, + cp_convert (ptrdiff_type_node, + build_component_ref (aref, delta_identifier, NULL_TREE, 0))); } + + return build_component_ref (aref, pfn_identifier, NULL_TREE, 0); } /* Return the name of the virtual function table (as an IDENTIFIER_NODE) for the given TYPE. */ + static tree get_vtable_name (type) tree type; { tree type_id = build_typename_overload (type); - char *buf = (char *)alloca (strlen (VTABLE_NAME_FORMAT) - + IDENTIFIER_LENGTH (type_id) + 2); + char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + + IDENTIFIER_LENGTH (type_id) + 2); char *ptr = IDENTIFIER_POINTER (type_id); int i; for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ; @@ -522,10 +600,79 @@ get_vtable_name (type) return get_identifier (buf); } +/* Return the offset to the main vtable for a given base BINFO. */ + +tree +get_vfield_offset (binfo) + tree binfo; +{ + tree tmp + = size_binop (FLOOR_DIV_EXPR, + DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), + size_int (BITS_PER_UNIT)); + tmp = convert (sizetype, tmp); + return size_binop (PLUS_EXPR, tmp, BINFO_OFFSET (binfo)); +} + +/* Get the offset to the start of the original binfo that we derived + this binfo from. If we find TYPE first, return the offset only + that far. The shortened search is useful because the this pointer + on method calling is expected to point to a DECL_CONTEXT (fndecl) + object, and not a baseclass of it. */ + +static tree +get_derived_offset (binfo, type) + tree binfo, type; +{ + tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + tree offset2; + int i; + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + if (BINFO_TYPE (binfo) == type) + break; + binfo = TREE_VEC_ELT (binfos, i); + } + offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + return size_binop (MINUS_EXPR, offset1, offset2); +} + +/* Update the rtti info for this class. */ + +static void +set_rtti_entry (virtuals, offset, type) + tree virtuals, offset, type; +{ + tree vfn; + + if (flag_rtti) + vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type)); + else + vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node); + TREE_CONSTANT (vfn) = 1; + + if (! flag_vtable_thunks) + TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn); + else + { + tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (voff) = 1; + + TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff); + + /* The second slot is for the tdesc pointer when thunks are used. */ + TREE_VALUE (TREE_CHAIN (virtuals)) + = build_vtable_entry (integer_zero_node, vfn); + } +} + /* Build a virtual function for type TYPE. If BINFO is non-NULL, build the vtable starting with the initial approximation that it is the same as the one which is the head of the association list. */ + static tree build_vtable (binfo, type) tree binfo, type; @@ -535,8 +682,15 @@ build_vtable (binfo, type) if (binfo) { + tree offset; + virtuals = copy_list (BINFO_VIRTUALS (binfo)); decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo))); + + /* Now do rtti stuff. */ + offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE); + offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset); + set_rtti_entry (virtuals, offset, type); } else { @@ -552,12 +706,14 @@ build_vtable (binfo, type) /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ import_export_vtable (decl, type, 0); - IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl); + decl = pushdecl_top_level (decl); + SET_IDENTIFIER_GLOBAL_VALUE (name, decl); /* Initialize the association list for this type, based on our first approximation. */ TYPE_BINFO_VTABLE (type) = decl; TYPE_BINFO_VIRTUALS (type) = virtuals; + DECL_ARTIFICIAL (decl) = 1; TREE_STATIC (decl) = 1; #ifndef WRITABLE_VTABLES /* Make them READONLY by default. (mrs) */ @@ -578,124 +734,124 @@ build_vtable (binfo, type) return decl; } -/* Given a base type PARENT, and a derived type TYPE, build - a name which distinguishes exactly the PARENT member of TYPE's type. - - FORMAT is a string which controls how sprintf formats the name - we have generated. +extern tree signed_size_zero_node; - For example, given - - class A; class B; class C : A, B; +/* Give TYPE a new virtual function table which is initialized + with a skeleton-copy of its original initialization. The only + entry that changes is the `delta' entry, so we can really + share a lot of structure. - it is possible to distinguish "A" from "C's A". And given + FOR_TYPE is the derived type which caused this table to + be needed. - class L; - class A : L; class B : L; class C : A, B; + BINFO is the type association which provided TYPE for FOR_TYPE. - it is possible to distinguish "L" from "A's L", and also from - "C's L from A". + The order in which vtables are built (by calling this function) for + an object must remain the same, otherwise a binary incompatibility + can result. */ - Make sure to use the DECL_ASSEMBLER_NAME of the TYPE_NAME of the - type, as template have DECL_NAMEs like: X, whereas the - DECL_ASSEMBLER_NAME is set to be something the assembler can handle. - */ -static tree -build_type_pathname (format, parent, type) - char *format; - tree parent, type; +static void +prepare_fresh_vtable (binfo, for_type) + tree binfo, for_type; { - extern struct obstack temporary_obstack; - char *first, *base, *name; + tree basetype; + tree orig_decl = BINFO_VTABLE (binfo); + tree name; + tree new_decl; + tree offset; + tree path = binfo; + char *buf, *buf2; + char joiner = '_'; int i; - tree id; - - parent = TYPE_MAIN_VARIANT (parent); - /* Remember where to cut the obstack to. */ - first = obstack_base (&temporary_obstack); - - /* Put on TYPE+PARENT. */ - obstack_grow (&temporary_obstack, - TYPE_ASSEMBLER_NAME_STRING (type), - TYPE_ASSEMBLER_NAME_LENGTH (type)); #ifdef JOINER - obstack_1grow (&temporary_obstack, JOINER); -#else - obstack_1grow (&temporary_obstack, '_'); + joiner = JOINER; #endif - obstack_grow0 (&temporary_obstack, - TYPE_ASSEMBLER_NAME_STRING (parent), - TYPE_ASSEMBLER_NAME_LENGTH (parent)); - i = obstack_object_size (&temporary_obstack); - base = obstack_base (&temporary_obstack); - obstack_finish (&temporary_obstack); - - /* Put on FORMAT+TYPE+PARENT. */ - obstack_blank (&temporary_obstack, strlen (format) + i + 1); - name = obstack_base (&temporary_obstack); - sprintf (name, format, base); - id = get_identifier (name); - obstack_free (&temporary_obstack, first); - - return id; -} -/* Update the rtti info for this class. */ -static void -set_rtti_entry (virtuals, offset, type) - tree virtuals, offset, type; -{ - if (! flag_vtable_thunks) - TREE_VALUE (virtuals) - = build_vtable_entry (offset, - (flag_rtti - ? build_t_desc (type, 0) - : integer_zero_node)); - else + basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo)); + + buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype); + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1; + + /* We know that the vtable that we are going to create doesn't exist + yet in the global namespace, and when we finish, it will be + pushed into the global namespace. In complex MI hierarchies, we + have to loop while the name we are thinking of adding is globally + defined, adding more name components to the vtable name as we + loop, until the name is unique. This is because in complex MI + cases, we might have the same base more than once. This means + that the order in which this function is called for vtables must + remain the same, otherwise binary compatibility can be + compromised. */ + + while (1) { - tree vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); - TREE_CONSTANT (vfn) = 1; + char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type) + + 1 + i); + char *new_buf2; - TREE_VALUE (virtuals) - = build_vtable_entry (integer_zero_node, vfn); - /* The second slot is for the tdesc pointer when thunks are used. */ - vfn = flag_rtti - ? build_t_desc (type, 0) - : integer_zero_node; - vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, vfn); - TREE_CONSTANT (vfn) = 1; + sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner, + buf2); + buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + strlen (buf1) + 1); + sprintf (buf, VTABLE_NAME_FORMAT, buf1); + name = get_identifier (buf); - TREE_VALUE (TREE_CHAIN (virtuals)) - = build_vtable_entry (integer_zero_node, vfn); - } -} + /* If this name doesn't clash, then we can use it, otherwise + we add more to the name until it is unique. */ -/* Give TYPE a new virtual function table which is initialized - with a skeleton-copy of its original initialization. The only - entry that changes is the `delta' entry, so we can really - share a lot of structure. + if (! IDENTIFIER_GLOBAL_VALUE (name)) + break; - FOR_TYPE is the derived type which caused this table to - be needed. + /* Set values for next loop through, if the name isn't unique. */ - BINFO is the type association which provided TYPE for FOR_TYPE. */ -static void -prepare_fresh_vtable (binfo, for_type) - tree binfo, for_type; -{ - tree basetype = BINFO_TYPE (binfo); - tree orig_decl = BINFO_VTABLE (binfo); - /* This name is too simplistic. We can have multiple basetypes for - for_type, and we really want different names. (mrs) */ - tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type); - tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); - tree path, offset; - int result; + path = BINFO_INHERITANCE_CHAIN (path); + + /* We better not run out of stuff to make it unique. */ + my_friendly_assert (path != NULL_TREE, 368); + + basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (path)); + + if (for_type == basetype) + { + /* If we run out of basetypes in the path, we have already + found created a vtable with that name before, we now + resort to tacking on _%d to distinguish them. */ + int j = 2; + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i + 1 + 3; + buf1 = (char *) alloca (i); + do { + sprintf (buf1, "%s%c%s%c%d", + TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, + buf2, joiner, j); + buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + + strlen (buf1) + 1); + sprintf (buf, VTABLE_NAME_FORMAT, buf1); + name = get_identifier (buf); + + /* If this name doesn't clash, then we can use it, + otherwise we add something different to the name until + it is unique. */ + } while (++j <= 999 && IDENTIFIER_GLOBAL_VALUE (name)); + + /* Hey, they really like MI don't they? Increase the 3 + above to 6, and the 999 to 999999. :-) */ + my_friendly_assert (j <= 999, 369); + + break; + } + + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i; + new_buf2 = (char *) alloca (i); + sprintf (new_buf2, "%s%c%s", + TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, buf2); + buf2 = new_buf2; + } + new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); /* Remember which class this vtable is really for. */ DECL_CONTEXT (new_decl) = for_type; + DECL_ARTIFICIAL (new_decl) = 1; TREE_STATIC (new_decl) = 1; BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl); DECL_VIRTUAL_P (new_decl) = 1; @@ -709,13 +865,23 @@ prepare_fresh_vtable (binfo, for_type) BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo)); if (TREE_VIA_VIRTUAL (binfo)) - offset = BINFO_OFFSET (binfo_member (BINFO_TYPE (binfo), - CLASSTYPE_VBASECLASSES (for_type))); + { + tree binfo1 = binfo_member (BINFO_TYPE (binfo), + CLASSTYPE_VBASECLASSES (for_type)); + + /* XXX - This should never happen, if it does, the caller should + ensure that the binfo is from for_type's binfos, not from any + base type's. We can remove all this code after a while. */ + if (binfo1 != binfo) + warning ("internal inconsistency: binfo offset error for rtti"); + + offset = BINFO_OFFSET (binfo1); + } else offset = BINFO_OFFSET (binfo); set_rtti_entry (BINFO_VIRTUALS (binfo), - size_binop (MINUS_EXPR, integer_zero_node, offset), + ssize_binop (MINUS_EXPR, integer_zero_node, offset), for_type); #ifdef GATHER_STATISTICS @@ -733,10 +899,12 @@ prepare_fresh_vtable (binfo, for_type) SET_BINFO_NEW_VTABLE_MARKED (binfo); } +#if 0 /* Access the virtual function table entry that logically contains BASE_FNDECL. VIRTUALS is the virtual function table's initializer. We can run off the end, when dealing with virtual destructors in MI situations, return NULL_TREE in that case. */ + static tree get_vtable_entry (virtuals, base_fndecl) tree virtuals, base_fndecl; @@ -757,6 +925,7 @@ get_vtable_entry (virtuals, base_fndecl) } return virtuals; } +#endif /* Put new entry ENTRY into virtual function table initializer VIRTUALS. @@ -776,7 +945,7 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl) TREE_VALUE (old_entry_in_list) = new_entry; /* Now assign virtual dispatch information, if unset. */ - /* We can dispatch this, through any overridden base function. */ + /* We can dispatch this, through any overridden base function. */ if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) { DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl); @@ -784,8 +953,9 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl) } } -/* Access the virtual function table entry i. VIRTUALS is the virtual +/* Access the virtual function table entry N. VIRTUALS is the virtual function table's initializer. */ + static tree get_vtable_entry_n (virtuals, n) tree virtuals; @@ -806,13 +976,17 @@ get_vtable_entry_n (virtuals, n) HAS_VIRTUAL keeps track of how many virtuals there are in our main vtable for the type, and we build upon the PENDING_VIRTUALS list and return it. */ -static tree -add_virtual_function (pending_virtuals, has_virtual, fndecl, t) - tree pending_virtuals; + +static void +add_virtual_function (pv, phv, has_virtual, fndecl, t) + tree *pv, *phv; int *has_virtual; tree fndecl; - tree t; /* Structure type. */ + tree t; /* Structure type. */ { + tree pending_virtuals = *pv; + tree pending_hard_virtuals = *phv; + /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely convert to void *. Make such a conversion here. */ tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl); @@ -835,11 +1009,8 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t) { tree entry; - if (flag_rtti && *has_virtual == 0) - { - /* CLASSTYPE_RTTI is only used as a Boolean (NULL or not). */ - CLASSTYPE_RTTI (t) = integer_one_node; - } + /* We remember that this was the base sub-object for rtti. */ + 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. */ @@ -851,21 +1022,21 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t) /* Build a new INT_CST for this DECL_VINDEX. */ { static tree index_table[256]; - tree index; + tree idx; /* We skip a slot for the offset/tdesc entry. */ int i = ++(*has_virtual); if (i >= 256 || index_table[i] == 0) { - index = build_int_2 (i, 0); + idx = build_int_2 (i, 0); if (i < 256) - index_table[i] = index; + index_table[i] = idx; } else - index = index_table[i]; + idx = index_table[i]; - /* Now assign virtual dispatch information. */ - DECL_VINDEX (fndecl) = index; + /* Now assign virtual dispatch information. */ + DECL_VINDEX (fndecl) = idx; DECL_CONTEXT (fndecl) = t; } entry = build_vtable_entry (integer_zero_node, vfn); @@ -879,7 +1050,8 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t) Deal with this after we have laid out our virtual base classes. */ pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals); } - return pending_virtuals; + *pv = pending_virtuals; + *phv = pending_hard_virtuals; } /* Obstack on which to build the vector of class methods. */ @@ -892,39 +1064,30 @@ extern struct obstack *current_obstack; 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; { - /* We must make a copy of METHOD here, since we must be sure that - we have exclusive title to this method's DECL_CHAIN. */ - tree decl; - push_obstacks (&permanent_obstack, &permanent_obstack); - { - decl = copy_node (method); - if (DECL_RTL (decl) == 0 - && (!processing_template_decl - || !uses_template_parms (decl))) - { - make_function_rtl (decl); - DECL_RTL (method) = DECL_RTL (decl); - } - } if (fields && *fields) - { - /* Take care not to hide destructor. */ - DECL_CHAIN (decl) = DECL_CHAIN (*fields); - DECL_CHAIN (*fields) = decl; - } + *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 (decl)) + if (TYPE_IDENTIFIER (type) == DECL_NAME (method)) { - TREE_VEC_ELT (method_vec, 0) = decl; - TREE_VEC_LENGTH (method_vec) = 1; + /* ??? 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 { @@ -932,9 +1095,9 @@ add_method (type, fields, method) 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 *)); - TREE_VEC_ELT (method_vec, 1) = decl; - TREE_VEC_LENGTH (method_vec) = 2; + 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; @@ -946,14 +1109,13 @@ add_method (type, fields, method) /* 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 (decl)) + if (TYPE_IDENTIFIER (type) == DECL_NAME (method)) { - /* TREE_VEC_ELT (method_vec, 0) = decl; */ - if (decl != TREE_VEC_ELT (method_vec, 0)) - { - DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = decl; - } + 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)); } else { @@ -992,7 +1154,7 @@ add_method (type, fields, method) } obstack_finish (ob); - TREE_VEC_ELT (method_vec, len) = decl; + TREE_VEC_ELT (method_vec, len) = method; TREE_VEC_LENGTH (method_vec) = len + 1; CLASSTYPE_METHOD_VEC (type) = method_vec; @@ -1009,8 +1171,8 @@ add_method (type, fields, method) } } } - DECL_CONTEXT (decl) = type; - DECL_CLASS_CONTEXT (decl) = type; + DECL_CONTEXT (method) = type; + DECL_CLASS_CONTEXT (method) = type; pop_obstacks (); } @@ -1030,6 +1192,7 @@ add_method (type, fields, method) Note that anonymous fields which are not of UNION_TYPE are not duplicates, they are just anonymous fields. This happens when we have unnamed bitfields, for example. */ + static tree delete_duplicate_fields_1 (field, fields) tree field, fields; @@ -1074,13 +1237,25 @@ delete_duplicate_fields_1 (field, fields) || TREE_CODE (x) == CONST_DECL) cp_error_at ("duplicate field `%D' (as enum and non-enum)", x); - else if (TREE_CODE (field) == TYPE_DECL - && TREE_CODE (x) == TYPE_DECL) - cp_error_at ("duplicate nested type `%D'", x); - else if (TREE_CODE (field) == TYPE_DECL - || TREE_CODE (x) == TYPE_DECL) - cp_error_at ("duplicate field `%D' (as type and non-type)", - x); + else if (DECL_DECLARES_TYPE_P (field) + && DECL_DECLARES_TYPE_P (x)) + { + if (comptypes (TREE_TYPE (field), TREE_TYPE (x), 1)) + continue; + cp_error_at ("duplicate nested type `%D'", x); + } + else if (DECL_DECLARES_TYPE_P (field) + || DECL_DECLARES_TYPE_P (x)) + { + /* Hide tag decls. */ + if ((TREE_CODE (field) == TYPE_DECL + && DECL_ARTIFICIAL (field)) + || (TREE_CODE (x) == TYPE_DECL + && DECL_ARTIFICIAL (x))) + continue; + cp_error_at ("duplicate field `%D' (as type and non-type)", + x); + } else cp_error_at ("duplicate member `%D'", x); if (prev == 0) @@ -1103,85 +1278,135 @@ delete_duplicate_fields (fields) TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x)); } -/* Change the access of FDECL to ACCESS in T. - Return 1 if change was legit, otherwise return 0. */ +/* Change the access of FDECL to ACCESS in T. The access to FDECL is + along the path given by BINFO. Return 1 if change was legit, + otherwise return 0. */ + static int -alter_access (t, fdecl, access) +alter_access (t, binfo, fdecl, access) tree t; + tree binfo; tree fdecl; - enum access_type access; + tree access; { tree elem = purpose_member (t, DECL_ACCESS (fdecl)); - if (elem && TREE_VALUE (elem) != (tree)access) + if (elem) { - if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) + if (TREE_VALUE (elem) != access) { - cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl)); + if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) + cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl)); + else + error ("conflicting access specifications for field `%s', ignored", + IDENTIFIER_POINTER (DECL_NAME (fdecl))); } else - error ("conflicting access specifications for field `%s', ignored", - IDENTIFIER_POINTER (DECL_NAME (fdecl))); - } - else if (TREE_PRIVATE (fdecl)) - { - if (access != access_private) - cp_error_at ("cannot make private `%D' non-private", fdecl); - goto alter; - } - else if (TREE_PROTECTED (fdecl)) - { - if (access != access_protected) - cp_error_at ("cannot make protected `%D' non-protected", fdecl); - goto alter; + { + /* They're changing the access to the same thing they changed + it to before. That's OK. */ + ; + } } - /* ARM 11.3: an access declaration may not be used to restrict access - to a member that is accessible in the base class. */ - else if (access != access_public) - cp_error_at ("cannot reduce access of public member `%D'", fdecl); - else if (elem == NULL_TREE) + else { - alter: - DECL_ACCESS (fdecl) = tree_cons (t, (tree)access, - DECL_ACCESS (fdecl)); + enforce_access (binfo, fdecl); + + DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl)); return 1; } return 0; } -/* Return the offset to the main vtable for a given base BINFO. */ -tree -get_vfield_offset (binfo) - tree binfo; -{ - return size_binop (PLUS_EXPR, - size_binop (FLOOR_DIV_EXPR, - DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), - size_int (BITS_PER_UNIT)), - BINFO_OFFSET (binfo)); -} +/* 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. */ -/* Get the offset to the start of the original binfo that we derived - this binfo from. If we find TYPE first, return the offset only - that far. The shortened search is useful because the this pointer - on method calling is expected to point to a DECL_CONTEXT (fndecl) - object, and not a baseclass of it. */ -static tree -get_derived_offset (binfo, type) - tree binfo, type; +void +handle_using_decl (using_decl, t, method_vec, fields) + tree using_decl; + tree t; + tree method_vec; + tree fields; { - tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); - tree offset2; + tree ctype = DECL_INITIAL (using_decl); + tree name = DECL_NAME (using_decl); + tree access + = TREE_PRIVATE (using_decl) ? access_private_node + : TREE_PROTECTED (using_decl) ? access_protected_node + : access_public_node; + tree fdecl, binfo; + tree flist = NULL_TREE; + tree tmp; int i; - while (BINFO_BASETYPES (binfo) - && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + int n_methods; + + binfo = binfo_or_else (ctype, t); + if (! binfo) + return; + + if (name == constructor_name (ctype) + || name == constructor_name_full (ctype)) + cp_error_at ("using-declaration for constructor", using_decl); + + fdecl = lookup_member (binfo, name, 0, 0); + + if (!fdecl) { - tree binfos = BINFO_BASETYPES (binfo); - if (BINFO_TYPE (binfo) == type) - break; - binfo = TREE_VEC_ELT (binfos, i); + cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype); + return; } - offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); - return size_binop (MINUS_EXPR, offset1, offset2); + + /* Functions are represented as TREE_LIST, with the purpose + being the type and the value the functions. Other members + come as themselves. */ + if (TREE_CODE (fdecl) == TREE_LIST) + /* Ignore base type this came from. */ + fdecl = TREE_VALUE (fdecl); + + if (TREE_CODE (fdecl) == OVERLOAD) + { + /* We later iterate over all functions. */ + flist = fdecl; + fdecl = OVL_FUNCTION (flist); + } + + name = DECL_NAME (fdecl); + n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; + for (i = 2; i < n_methods; i++) + if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))) + == name) + { + cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); + cp_error_at (" because of local method `%#D' with same name", + OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); + return; + } + + if (! DECL_LANG_SPECIFIC (fdecl)) + /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return. */ + return; + + for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp)) + if (DECL_NAME (tmp) == name) + { + cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); + cp_error_at (" because of local field `%#D' with same name", tmp); + return; + } + + /* Make type T see field decl FDECL with access ACCESS.*/ + if (flist) + { + while (flist) + { + if (alter_access (t, binfo, OVL_FUNCTION (flist), + access) == 0) + return; + flist = OVL_CHAIN (flist); + } + } + else + alter_access (t, binfo, fdecl, access); } /* If FOR_TYPE needs to reinitialize virtual function table pointers @@ -1202,7 +1427,7 @@ maybe_fixup_vptrs (for_type, binfo, base_init_list) : VF_BASETYPE_VALUE (vfields); tree base_binfo = get_binfo (basetype, for_type, 0); - /* Punt until this is implemented. */ + /* Punt until this is implemented. */ if (1 /* BINFO_MODIFIED (base_binfo) */) { tree base_offset = get_vfield_offset (base_binfo); @@ -1335,10 +1560,13 @@ build_class_init_list (type) } 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; + { + 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; } @@ -1350,12 +1578,10 @@ struct base_info int n_ancestors; tree vfield; tree vfields; + tree rtti; char cant_have_default_ctor; char cant_have_const_ctor; - char cant_synth_copy_ctor; - char cant_synth_asn_ref; char no_const_asn_ref; - char needs_virtual_dtor; }; /* Record information about type T derived from its base classes. @@ -1372,17 +1598,14 @@ struct base_info offsets include that offset in theirs. Returns the index of the first base class to have virtual functions, - or -1 if no such base class. - - Note that at this point TYPE_BINFO (t) != t_binfo. */ + or -1 if no such base class. */ static int -finish_base_struct (t, b, t_binfo) +finish_base_struct (t, b) tree t; struct base_info *b; - tree t_binfo; { - tree binfos = BINFO_BASETYPES (t_binfo); + tree binfos = TYPE_BINFO_BASETYPES (t); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int first_vfn_base_index = -1; bzero ((char *) b, sizeof (struct base_info)); @@ -1392,6 +1615,13 @@ finish_base_struct (t, b, t_binfo) tree base_binfo = TREE_VEC_ELT (binfos, i); tree basetype = BINFO_TYPE (base_binfo); + /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P + here because the case of virtual functions but non-virtual + dtor is handled in finish_struct_1. */ + if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype) + && TYPE_HAS_DESTRUCTOR (basetype)) + cp_warning ("base class `%#T' has a non-virtual destructor", basetype); + /* If the type of basetype is incomplete, then we already complained about that fact (and we should have fixed it up as well). */ @@ -1409,13 +1639,8 @@ finish_base_struct (t, b, t_binfo) TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); } - if (TYPE_HAS_INIT_REF (basetype) - && !TYPE_HAS_CONST_INIT_REF (basetype)) + if (! TYPE_HAS_CONST_INIT_REF (basetype)) b->cant_have_const_ctor = 1; - if (! TYPE_HAS_INIT_REF (basetype) - || (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2 - && ! is_friend_type (t, basetype))) - b->cant_synth_copy_ctor = 1; if (TYPE_HAS_CONSTRUCTOR (basetype) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) @@ -1432,11 +1657,6 @@ finish_base_struct (t, b, t_binfo) if (TYPE_HAS_ASSIGN_REF (basetype) && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) b->no_const_asn_ref = 1; - if (! TYPE_HAS_ASSIGN_REF (basetype) - || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2 - && ! is_friend_type (t, basetype))) - b->cant_synth_asn_ref = 1; b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype); TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); @@ -1448,52 +1668,15 @@ finish_base_struct (t, b, t_binfo) TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); - if (! TREE_VIA_VIRTUAL (base_binfo) -#if 0 - /* This cannot be done, as prepare_fresh_vtable wants to modify - binfos associated with vfields anywhere in the hierarchy, not - just immediate base classes. Due to unsharing, the compiler - might consume 3% more memory on a real program. - */ - && ! BINFO_OFFSET_ZEROP (base_binfo) -#endif - && BINFO_BASETYPES (base_binfo)) - { - tree base_binfos = BINFO_BASETYPES (base_binfo); - tree chain = NULL_TREE; - 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; - } - - /* Completely unshare potentially shared data, and - update what is ours. */ - propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo)); - } - if (! TREE_VIA_VIRTUAL (base_binfo)) CLASSTYPE_N_SUPERCLASSES (t) += 1; if (TYPE_VIRTUAL_P (basetype)) { - /* If there's going to be a destructor needed, make - sure it will be virtual. */ - b->needs_virtual_dtor = 1; + /* Ensure that this is set from at least a virtual base + class. */ + if (b->rtti == NULL_TREE) + b->rtti = CLASSTYPE_RTTI (basetype); /* Don't borrow virtuals from virtual baseclasses. */ if (TREE_VIA_VIRTUAL (base_binfo)) @@ -1507,8 +1690,8 @@ finish_base_struct (t, b, t_binfo) /* Update these two, now that we know what vtable we are going to extend. This is so that we can add virtual functions, and override them properly. */ - BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); - BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); + TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); + TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype)); @@ -1556,8 +1739,8 @@ finish_base_struct (t, b, t_binfo) /* Update these two, now that we know what vtable we are going to extend. This is so that we can add virtual functions, and override them properly. */ - BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); - BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); + TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); + TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); CLASSTYPE_VFIELD (t) = b->vfield; @@ -1583,33 +1766,31 @@ finish_base_struct (t, b, t_binfo) } } - /* Must come after offsets are fixed for all bases. */ + /* 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_binfo, 0, (tree*)0) == -2) + if (get_base_distance (basetype, t, 0, (tree*)0) == -2) { cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity", basetype, t); - b->cant_synth_asn_ref = 1; - b->cant_synth_copy_ctor = 1; } } { - tree v = get_vbase_types (t_binfo); + tree v = get_vbase_types (t); for (; v; v = TREE_CHAIN (v)) { tree basetype = BINFO_TYPE (v); - if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) + 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); - b->cant_synth_asn_ref = 1; - b->cant_synth_copy_ctor = 1; } } } @@ -1630,28 +1811,23 @@ finish_base_struct (t, b, t_binfo) if (b->vfield == 0) /* If all virtual functions come only from virtual baseclasses. */ return -1; - return first_vfn_base_index; -} -static int -typecode_p (type, code) - tree type; - enum tree_code code; -{ - return (TREE_CODE (type) == code - || (TREE_CODE (type) == REFERENCE_TYPE - && TREE_CODE (TREE_TYPE (type)) == code)); + /* Update the rtti base if we have a non-virtual base class version + of it. */ + b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index))); + + return first_vfn_base_index; } /* Set memoizing fields and bits of T (and its variants) for later use. MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */ + static void finish_struct_bits (t, max_has_virtual) tree t; int max_has_virtual; { int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); - tree method_vec = CLASSTYPE_METHOD_VEC (t); /* Fix up variants (if any). */ tree variants = TYPE_NEXT_VARIANT (t); @@ -1670,6 +1846,9 @@ finish_struct_bits (t, max_has_virtual) /* Copy whatever these are holding today. */ TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); + TYPE_FIELDS (variants) = TYPE_FIELDS (t); + TYPE_SIZE (variants) = TYPE_SIZE (t); + TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t); variants = TYPE_NEXT_VARIANT (variants); } @@ -1688,7 +1867,7 @@ finish_struct_bits (t, max_has_virtual) if (might_have_abstract_virtuals) { /* We use error_mark_node from override_one_vtable to signal - an artificial abstract. */ + 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); @@ -1706,12 +1885,7 @@ finish_struct_bits (t, max_has_virtual) { basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); - if (TYPE_HAS_CONVERSION (basetype)) - { - TYPE_HAS_CONVERSION (t) = 1; - TYPE_HAS_INT_CONVERSION (t) |= TYPE_HAS_INT_CONVERSION (basetype); - TYPE_HAS_REAL_CONVERSION (t) |= TYPE_HAS_REAL_CONVERSION (basetype); - } + 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; } @@ -1720,12 +1894,17 @@ finish_struct_bits (t, max_has_virtual) /* If this type has a copy constructor, force its mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to be passed by invisible reference and prevent it from being returned in - a register. */ - if (! TYPE_HAS_TRIVIAL_INIT_REF (t)) + a register. + + Also do this if the class has BLKmode but can still be returned in + registers, since function_cannot_inline_p won't let us inline + functions returning such a type. This affects the HP-PA. */ + if (! TYPE_HAS_TRIVIAL_INIT_REF (t) + || (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t) + && CLASSTYPE_NON_AGGREGATE (t))) { tree variants; - if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) - DECL_MODE (TYPE_NAME (t)) = BLKmode; + DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode; for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) { TYPE_MODE (variants) = BLKmode; @@ -1734,57 +1913,29 @@ finish_struct_bits (t, max_has_virtual) } } -/* Add FN to the method_vec growing on the class_obstack. Used by - finish_struct_methods. */ +/* 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. */ + static void -grow_method (fn, method_vec_ptr) - tree fn; +grow_method (fndecl, method_vec_ptr) + tree fndecl; tree *method_vec_ptr; { tree method_vec = (tree)obstack_base (&class_obstack); - tree *testp = &TREE_VEC_ELT (method_vec, 0); - if (*testp == NULL_TREE) - testp++; - while (((HOST_WIDE_INT) testp - < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) - && DECL_NAME (*testp) != DECL_NAME (fn)) + + /* Start off past the constructors and destructor. */ + tree *testp = &TREE_VEC_ELT (method_vec, 2); + + while (testp < (tree *) obstack_next_free (&class_obstack) + && (*testp == NULL_TREE || DECL_NAME (OVL_CURRENT (*testp)) != DECL_NAME (fndecl))) testp++; - if ((HOST_WIDE_INT) testp - < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) - { - tree x, prev_x; - for (x = *testp; x; x = DECL_CHAIN (x)) - { - if (DECL_NAME (fn) == ansi_opname[(int) DELETE_EXPR] - || DECL_NAME (fn) == ansi_opname[(int) VEC_DELETE_EXPR]) - { - /* ANSI C++ June 5 1992 WP 12.5.5.1 */ - cp_error_at ("`%D' overloaded", fn); - cp_error_at ("previous declaration as `%D' here", x); - } - if (DECL_ASSEMBLER_NAME (fn)==DECL_ASSEMBLER_NAME (x)) - { - /* We complain about multiple destructors on sight, - so we do not repeat the warning here. Friend-friend - ambiguities are warned about outside this loop. */ - if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn))) - cp_error_at ("ambiguous method `%#D' in structure", fn); - break; - } - prev_x = x; - } - if (x == 0) - { - if (*testp) - DECL_CHAIN (prev_x) = fn; - else - *testp = fn; - } - } + if (testp < (tree *) obstack_next_free (&class_obstack)) + *testp = build_overload (fndecl, *testp); else { - obstack_ptr_grow (&class_obstack, fn); + obstack_ptr_grow (&class_obstack, fndecl); *method_vec_ptr = (tree)obstack_base (&class_obstack); } } @@ -1812,36 +1963,35 @@ grow_method (fn, method_vec_ptr) us to reduce search time in places like `build_method_call' to consider only reasonably likely functions. */ -static tree +tree finish_struct_methods (t, fn_fields, nonprivate_method) tree t; tree fn_fields; int nonprivate_method; { tree method_vec; - tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields); - tree lastp; - tree name = constructor_name (t); + tree save_fn_fields = fn_fields; + 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_node (TREE_VEC); - /* Room has been saved for constructors and destructors. */ + method_vec = make_tree_vec (2); current_obstack = ambient_obstack; + /* Now make this a live vector. */ obstack_free (&class_obstack, method_vec); - obstack_blank (&class_obstack, sizeof (struct tree_vec)); - /* First fill in entry 0 with the constructors, and the next few with - type conversion operators (if any). */ + /* 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 (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp)) + for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) { tree fn_name = DECL_NAME (fn_fields); - if (fn_name == NULL_TREE) - fn_name = name; /* Clear out this flag. @@ -1852,7 +2002,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) /* Note here that a copy ctor is private, so we don't dare generate a default copy constructor for a class that has a member of this type without making sure they have access to it. */ - if (fn_name == name) + if (fn_name == ctor_name) { tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields); tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; @@ -1870,43 +2020,30 @@ finish_struct_methods (t, fn_fields, nonprivate_method) TYPE_HAS_NONPUBLIC_CTOR (t) = 2; } } - /* Constructors are handled easily in search routines. */ - DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = fn_fields; + 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)) - { - tree return_type = TREE_TYPE (TREE_TYPE (fn_fields)); - - if (typecode_p (return_type, INTEGER_TYPE) - || typecode_p (return_type, BOOLEAN_TYPE) - || typecode_p (return_type, ENUMERAL_TYPE)) - TYPE_HAS_INT_CONVERSION (t) = 1; - else if (typecode_p (return_type, REAL_TYPE)) - TYPE_HAS_REAL_CONVERSION (t) = 1; - - grow_method (fn_fields, &method_vec); - } - else - { - lastp = fn_fields; - continue; - } - - TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields); - TREE_CHAIN (fn_fields) = NULL_TREE; + grow_method (fn_fields, &method_vec); } - fn_fields = TREE_CHAIN (save_fn_fields); - while (fn_fields) + fn_fields = save_fn_fields; + for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) { - tree nextp; tree fn_name = DECL_NAME (fn_fields); - if (fn_name == NULL_TREE) - fn_name = name; - nextp = TREE_CHAIN (fn_fields); - TREE_CHAIN (fn_fields) = NULL_TREE; + if (fn_name == ctor_name || IDENTIFIER_TYPENAME_P (fn_name)) + continue; if (fn_name == ansi_opname[(int) MODIFY_EXPR]) { @@ -1922,7 +2059,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method) } grow_method (fn_fields, &method_vec); - fn_fields = nextp; } TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack) @@ -1932,7 +2068,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) if (nonprivate_method == 0 && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE - && DECL_FRIENDLIST (TYPE_NAME (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++) @@ -1942,60 +2078,44 @@ finish_struct_methods (t, fn_fields, nonprivate_method) nonprivate_method = 1; break; } - if (nonprivate_method == 0) + if (nonprivate_method == 0 + && warn_ctor_dtor_privacy) cp_warning ("all member functions in class `%T' are private", t); } - /* If there are constructors (and destructors), they are at the - front. Place destructors at very front. Also warn if all - constructors and/or destructors are private (in which case this - class is effectively unusable. */ + /* Warn if all destructors are private (in which case this class is + effectively unusable. */ if (TYPE_HAS_DESTRUCTOR (t)) { - tree dtor, prev; - - for (dtor = TREE_VEC_ELT (method_vec, 0); - dtor; - prev = dtor, dtor = DECL_CHAIN (dtor)) - { - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (dtor))) - { - if (TREE_PRIVATE (dtor) - && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE - && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE - && warn_ctor_dtor_privacy) - cp_warning ("`%#T' only defines a private destructor and has no friends", - t); - break; - } - } + 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 (dtor != TREE_VEC_ELT (method_vec, 0)) - { - DECL_CHAIN (prev) = DECL_CHAIN (dtor); - DECL_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = dtor; - } + 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) > 1) + && 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 = 1; i < len; i++) + for (i = 2; i < len; i++) { TREE_VEC_ELT (baselink_vec, i) - = get_baselinks (baselink_binfo, t, DECL_NAME (TREE_VEC_ELT (method_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; } @@ -2005,46 +2125,10 @@ finish_struct_methods (t, fn_fields, nonprivate_method) obstack_free (current_obstack, baselink_vec); } - /* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */ - { - tree x, last_x = NULL_TREE; - int limit = TREE_VEC_LENGTH (method_vec); - - for (i = 1; i < limit; i++) - { - for (x = TREE_VEC_ELT (method_vec, i); x; x = DECL_CHAIN (x)) - { - if (last_x != NULL_TREE) - TREE_CHAIN (last_x) = x; - last_x = x; - } - } - - /* Put ctors and dtors at the front of the list. */ - x = TREE_VEC_ELT (method_vec, 0); - if (x) - { - while (DECL_CHAIN (x)) - { - /* Let's avoid being circular about this. */ - if (x == DECL_CHAIN (x)) - break; - TREE_CHAIN (x) = DECL_CHAIN (x); - x = DECL_CHAIN (x); - } - if (TREE_VEC_LENGTH (method_vec) > 1) - TREE_CHAIN (x) = TREE_VEC_ELT (method_vec, 1); - else - TREE_CHAIN (x) = NULL_TREE; - } - } - - TYPE_METHODS (t) = method_vec; - return method_vec; } -/* Emit error when a duplicate definition of a type is seen. Patch up. */ +/* Emit error when a duplicate definition of a type is seen. Patch up. */ void duplicate_tag_error (t) @@ -2058,23 +2142,22 @@ duplicate_tag_error (t) /* All of the component_decl's were TREE_CHAINed together in the parser. finish_struct_methods walks these chains and assembles all methods with the same base name into DECL_CHAINs. Now we don't need the parser chains - anymore, so we unravel them. - */ - /* - * This used to be in finish_struct, but it turns out that the - * TREE_CHAIN is used by dbxout_type_methods and perhaps some other things... - */ - if (CLASSTYPE_METHOD_VEC(t)) - { - tree tv = CLASSTYPE_METHOD_VEC(t); - int i, len = TREE_VEC_LENGTH (tv); + anymore, so we unravel them. */ + + /* This used to be in finish_struct, but it turns out that the + TREE_CHAIN is used by dbxout_type_methods and perhaps some other + things... */ + if (CLASSTYPE_METHOD_VEC (t)) + { + tree method_vec = CLASSTYPE_METHOD_VEC (t); + int i, len = TREE_VEC_LENGTH (method_vec); for (i = 0; i < len; i++) { - tree unchain = TREE_VEC_ELT (tv, i); + tree unchain = TREE_VEC_ELT (method_vec, i); while (unchain != NULL_TREE) { - TREE_CHAIN (unchain) = NULL_TREE; - unchain = DECL_CHAIN(unchain); + TREE_CHAIN (OVL_CURRENT (unchain)) = NULL_TREE; + unchain = OVL_NEXT (unchain); } } } @@ -2095,7 +2178,6 @@ duplicate_tag_error (t) CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list; CLASSTYPE_INTERFACE_ONLY (t) = interface_only; SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); - CLASSTYPE_VBASE_SIZE (t) = integer_zero_node; TYPE_REDEFINED (t) = 1; } TYPE_SIZE (t) = NULL_TREE; @@ -2106,11 +2188,13 @@ duplicate_tag_error (t) TYPE_CONTEXT (t) = NULL_TREE; } -/* finish up all new vtables. */ +/* finish up all new vtables. */ + static void finish_vtbls (binfo, do_self, t) - tree binfo, t; + tree binfo; int do_self; + tree t; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2138,8 +2222,8 @@ finish_vtbls (binfo, do_self, t) for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); - int is_not_base_vtable = - i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); if (TREE_VIA_VIRTUAL (base_binfo)) { base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t)); @@ -2150,20 +2234,21 @@ finish_vtbls (binfo, do_self, t) /* True if we should override the given BASE_FNDECL with the given FNDECL. */ + static int overrides (fndecl, base_fndecl) tree fndecl, base_fndecl; { - /* Destructors have special names. */ - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) && - DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + /* Destructors have special names. */ + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) + && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) return 1; - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) || - DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) + || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) return 0; if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl)) { - tree rettype, base_rettype, types, base_types; + tree types, base_types; #if 0 retypes = TREE_TYPE (TREE_TYPE (fndecl)); base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl)); @@ -2226,6 +2311,7 @@ get_class_offset_1 (parent, binfo, context, t, fndecl) /* Get the offset to the CONTEXT subobject that is related to the given BINFO. */ + static tree get_class_offset (context, t, binfo, fndecl) tree context, t, binfo, fndecl; @@ -2251,7 +2337,7 @@ get_class_offset (context, t, binfo, fndecl) } /* Ok, not found in the less derived binfos, now check the more - derived binfos. */ + derived binfos. */ offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl); if (offset==0 || TREE_CODE (offset) != INTEGER_CST) my_friendly_abort (999); /* we have to find it. */ @@ -2259,6 +2345,7 @@ 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; @@ -2287,7 +2374,6 @@ modify_one_vtable (binfo, t, fndecl, pfn) tree binfo, t, fndecl, pfn; { tree virtuals = BINFO_VIRTUALS (binfo); - tree old_rtti; unsigned HOST_WIDE_INT n; /* update rtti entry */ @@ -2333,7 +2419,7 @@ modify_one_vtable (binfo, t, fndecl, pfn) base_offset = size_binop (PLUS_EXPR, get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)), BINFO_OFFSET (binfo)); - this_offset = size_binop (MINUS_EXPR, offset, base_offset); + this_offset = ssize_binop (MINUS_EXPR, offset, base_offset); /* Make sure we can modify the derived association with immunity. */ if (TREE_USED (binfo)) @@ -2369,11 +2455,13 @@ modify_one_vtable (binfo, t, fndecl, pfn) } } -/* These are the ones that are not through virtual base classes. */ +/* These are the ones that are not through virtual base classes. */ + static void modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn) - tree binfo, t, fndecl, pfn; + tree binfo; int do_self; + tree t, fndecl, pfn; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2387,14 +2475,15 @@ modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn) for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); - int is_not_base_vtable = - i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); if (! TREE_VIA_VIRTUAL (base_binfo)) modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn); } } /* Fixup all the delta entries in this one vtable that need updating. */ + static void fixup_vtable_deltas1 (binfo, t) tree binfo, t; @@ -2427,9 +2516,10 @@ fixup_vtable_deltas1 (binfo, t) Also, we want just the delta between the most base class that we derived this vfield from and us. */ base_offset = size_binop (PLUS_EXPR, - get_derived_offset (binfo, DECL_CONTEXT (fndecl)), + get_derived_offset (binfo, + DECL_CONTEXT (fndecl)), BINFO_OFFSET (binfo)); - this_offset = size_binop (MINUS_EXPR, offset, base_offset); + this_offset = ssize_binop (MINUS_EXPR, offset, base_offset); if (! tree_int_cst_equal (this_offset, delta)) { @@ -2469,10 +2559,12 @@ fixup_vtable_deltas1 (binfo, t) This happens when we have non-overridden virtual functions from a virtual base class, that are at a different offset, in the new hierarchy, because the layout of the virtual bases has changed. */ + static void fixup_vtable_deltas (binfo, init_self, t) - tree binfo, t; + tree binfo; int init_self; + tree t; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2480,8 +2572,8 @@ fixup_vtable_deltas (binfo, init_self, t) for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); - int is_not_base_vtable = - i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); if (! TREE_VIA_VIRTUAL (base_binfo)) fixup_vtable_deltas (base_binfo, is_not_base_vtable, t); } @@ -2492,11 +2584,13 @@ fixup_vtable_deltas (binfo, init_self, t) } } -/* These are the ones that are through virtual base classes. */ +/* These are the ones that are through virtual base classes. */ + static void modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn) - tree binfo, t, fndecl, pfn; + tree binfo; int do_self, via_virtual; + tree t, fndecl, pfn; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2510,8 +2604,8 @@ modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn) for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); - int is_not_base_vtable = - i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); if (TREE_VIA_VIRTUAL (base_binfo)) { via_virtual = 1; @@ -2526,7 +2620,7 @@ modify_all_vtables (t, fndecl, vfn) tree t, fndecl, vfn; { /* Do these first, so that we will make use of any non-virtual class's - vtable, over a virtual classes vtable. */ + vtable, over a virtual classes vtable. */ modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn); if (TYPE_USES_VIRTUAL_BASECLASSES (t)) modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn); @@ -2534,6 +2628,7 @@ modify_all_vtables (t, fndecl, vfn) /* Here, we already know that they match in every respect. All we have to check is where they had their declarations. */ + static int strictly_overrides (fndecl1, fndecl2) tree fndecl1, fndecl2; @@ -2558,6 +2653,7 @@ strictly_overrides (fndecl1, fndecl2) then it is ill-formed. (mrs) We take special care to reuse a vtable, if we can. */ + static void override_one_vtable (binfo, old, t) tree binfo, old, t; @@ -2567,7 +2663,7 @@ override_one_vtable (binfo, old, t) enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED; /* If we have already committed to modifying it, then don't try and - reuse another vtable. */ + reuse another vtable. */ if (BINFO_NEW_VTABLE_MARKED (binfo)) choose = NEITHER; @@ -2582,10 +2678,10 @@ override_one_vtable (binfo, old, t) old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl); fndecl = TREE_OPERAND (fndecl, 0); old_fndecl = TREE_OPERAND (old_fndecl, 0); - /* First check to see if they are the same. */ + /* First check to see if they are the same. */ if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl)) { - /* No need to do anything. */ + /* No need to do anything. */ } else if (strictly_overrides (fndecl, old_fndecl)) { @@ -2640,15 +2736,16 @@ override_one_vtable (binfo, old, t) fndecl = copy_node (fndecl); copy_lang_decl (fndecl); DECL_ABSTRACT_VIRTUAL_P (fndecl) = 1; - /* Make sure we search for it later. */ + DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1; + /* Make sure we search for it later. */ if (! CLASSTYPE_ABSTRACT_VIRTUALS (t)) CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node; vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl); TREE_CONSTANT (vfn) = 1; - /* We can use integer_zero_node, as we will will core dump - if this is used anyway. */ + /* We can use integer_zero_node, as we will core dump + if this is used anyway. */ TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn); } } @@ -2656,7 +2753,7 @@ override_one_vtable (binfo, old, t) old_virtuals = TREE_CHAIN (old_virtuals); } - /* Let's reuse the old vtable. */ + /* Let's reuse the old vtable. */ if (choose == REUSE_OLD) { BINFO_VTABLE (binfo) = BINFO_VTABLE (old); @@ -2667,10 +2764,12 @@ override_one_vtable (binfo, old, t) /* Merge in overrides for virtual bases. BINFO is the hierarchy we want to modify, and OLD has the potential overrides. */ + static void merge_overrides (binfo, old, do_self, t) - tree binfo, old, t; + tree binfo, old; int do_self; + tree t; { tree binfos = BINFO_BASETYPES (binfo); tree old_binfos = BINFO_BASETYPES (old); @@ -2686,13 +2785,252 @@ merge_overrides (binfo, old, do_self, t) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree old_base_binfo = TREE_VEC_ELT (old_binfos, i); - int is_not_base_vtable = - i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); if (! TREE_VIA_VIRTUAL (base_binfo)) merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t); } } +/* Get the base virtual function declarations in T that are either + overridden or hidden by FNDECL as a list. We set TREE_PURPOSE with + the overrider/hider. */ + +static tree +get_basefndecls (fndecl, t) + tree fndecl, t; +{ + tree methods = TYPE_METHODS (t); + tree base_fndecls = NULL_TREE; + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + while (methods) + { + if (TREE_CODE (methods) == FUNCTION_DECL + && DECL_VINDEX (methods) != NULL_TREE + && DECL_NAME (fndecl) == DECL_NAME (methods)) + base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls); + + methods = TREE_CHAIN (methods); + } + + if (base_fndecls) + return base_fndecls; + + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree basetype = BINFO_TYPE (base_binfo); + + base_fndecls = chainon (get_basefndecls (fndecl, basetype), + base_fndecls); + } + + return base_fndecls; +} + +/* 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. */ + +static void +mark_overriders (fndecl, base_fndecls) + tree fndecl, base_fndecls; +{ + while (base_fndecls) + { + if (overrides (TREE_VALUE (base_fndecls), fndecl)) + TREE_PURPOSE (base_fndecls) = fndecl; + + base_fndecls = TREE_CHAIN (base_fndecls); + } +} + +/* If this declaration supersedes the declaration of + a method declared virtual in the base class, then + mark this field as being virtual as well. */ + +static void +check_for_override (decl, ctype) + tree 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); + + 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) + { + tree tmp = get_matching_virtual + (base_binfo, decl, + DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))); + if (tmp) + { + /* If this function overrides some virtual in some base + class, then the function itself is also necessarily + virtual, even if the user didn't explicitly say so. */ + DECL_VIRTUAL_P (decl) = 1; + + /* The TMP we really want is the one from the deepest + baseclass on this path, taking care not to + duplicate if we have already found it (via another + path to its virtual baseclass. */ + if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) + { + cp_error_at ("method `%D' may not be declared static", + decl); + cp_error_at ("(since `%D' declared virtual in base class.)", + tmp); + break; + } + 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; + } + } + } + if (virtualp) + { + if (DECL_VINDEX (decl) == NULL_TREE) + DECL_VINDEX (decl) = error_mark_node; + IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; + } +} + +/* Warn about hidden virtual functions that are not overridden in t. + We know that constructors and destructors don't apply. */ + +void +warn_hidden (t) + tree t; +{ + tree method_vec = CLASSTYPE_METHOD_VEC (t); + int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; + int i; + + /* We go through each separately named virtual function. */ + for (i = 2; i < n_methods; ++i) + { + tree fns = TREE_VEC_ELT (method_vec, i); + tree fndecl; + + tree base_fndecls = NULL_TREE; + 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) + continue; + + /* First we get a list of all possible functions that might be + hidden from each base class. */ + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree basetype = BINFO_TYPE (base_binfo); + + base_fndecls = chainon (get_basefndecls (fndecl, basetype), + base_fndecls); + } + + 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) + { + mark_overriders (fndecl, base_fndecls); + + fns = OVL_NEXT (fns); + if (fns) + fndecl = OVL_CURRENT (fns); + else + fndecl = NULL_TREE; + } + + /* Now give a warning for all base functions without overriders, + as they are hidden. */ + while (base_fndecls) + { + if (! overrides (TREE_VALUE (base_fndecls), + TREE_PURPOSE (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); + } + } +} + +/* Check for things that are invalid. There are probably plenty of other + things we should check for also. */ + +static void +finish_struct_anon (t) + tree t; +{ + tree field; + for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + { + if (TREE_STATIC (field)) + continue; + if (TREE_CODE (field) != FIELD_DECL) + continue; + + if (DECL_NAME (field) == NULL_TREE + && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + { + tree* uelt = &TYPE_FIELDS (TREE_TYPE (field)); + for (; *uelt; uelt = &TREE_CHAIN (*uelt)) + { + if (TREE_CODE (*uelt) != FIELD_DECL) + continue; + + if (TREE_PRIVATE (*uelt)) + cp_pedwarn_at ("private member `%#D' in anonymous union", + *uelt); + else if (TREE_PROTECTED (*uelt)) + cp_pedwarn_at ("protected member `%#D' in anonymous union", + *uelt); + + TREE_PRIVATE (*uelt) = TREE_PRIVATE (field); + TREE_PROTECTED (*uelt) = TREE_PROTECTED (field); + } + } + } +} + extern int interface_only, interface_unknown; /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration @@ -2724,6 +3062,8 @@ extern int interface_only, interface_unknown; 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. @@ -2760,25 +3100,21 @@ finish_struct_1 (t, warn_anon) int warn_anon; { int old; - int round_up_size = 1; - tree name = TYPE_IDENTIFIER (t); enum tree_code code = TREE_CODE (t); tree fields = TYPE_FIELDS (t); - tree fn_fields = CLASSTYPE_METHODS (t); + tree fn_fields = TYPE_METHODS (t); tree x, last_x, method_vec; - int needs_virtual_dtor; int all_virtual; int has_virtual; int max_has_virtual; tree pending_virtuals = NULL_TREE; + tree pending_hard_virtuals = NULL_TREE; tree abstract_virtuals = NULL_TREE; tree vfield; tree vfields; int cant_have_default_ctor; int cant_have_const_ctor; - int cant_synth_copy_ctor; - int cant_synth_asn_ref; int no_const_asn_ref; /* The index of the first base class which has virtual @@ -2790,9 +3126,10 @@ finish_struct_1 (t, warn_anon) int const_sans_init = 0; int ref_sans_init = 0; int nonprivate_method = 0; - tree t_binfo = TYPE_BINFO (t); tree access_decls = NULL_TREE; int aggregate = 1; + int empty = 1; + int has_pointers = 0; if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) pedwarn ("anonymous class type not used to declare any objects"); @@ -2807,12 +3144,6 @@ finish_struct_1 (t, warn_anon) return t; } - if (dont_allow_type_definitions) - { - pedwarn ("types cannot be defined %s", - dont_allow_type_definitions); - } - GNU_xref_decl (current_function_decl, t); /* If this type was previously laid out as a forward reference, @@ -2831,13 +3162,6 @@ finish_struct_1 (t, warn_anon) } #endif -#if 0 - if (flag_rtti) - build_t_desc (t, 0); -#endif - - TYPE_BINFO (t) = NULL_TREE; - old = suspend_momentary (); /* Install struct as DECL_FIELD_CONTEXT of each field decl. @@ -2847,8 +3171,8 @@ finish_struct_1 (t, warn_anon) Store 0 there, except for ": 0" fields (so we can find them and delete them, below). */ - if (t_binfo && BINFO_BASETYPES (t_binfo)) - n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); + if (TYPE_BINFO_BASETYPES (t)) + n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); else n_baseclasses = 0; @@ -2856,27 +3180,18 @@ finish_struct_1 (t, warn_anon) { struct base_info base_info; - /* If using multiple inheritance, this may cause variants of our - basetypes to be used (instead of their canonical forms). */ - tree vf = layout_basetypes (t, BINFO_BASETYPES (t_binfo)); - last_x = tree_last (vf); - fields = chainon (vf, fields); - - first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo); - /* Remember where we got our vfield from */ + first_vfn_base_index = finish_base_struct (t, &base_info); + /* Remember where we got our vfield from. */ 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; cant_have_default_ctor = base_info.cant_have_default_ctor; cant_have_const_ctor = base_info.cant_have_const_ctor; - cant_synth_copy_ctor = base_info.cant_synth_copy_ctor; - cant_synth_asn_ref = base_info.cant_synth_asn_ref; no_const_asn_ref = base_info.no_const_asn_ref; - needs_virtual_dtor = base_info.needs_virtual_dtor; - n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); aggregate = 0; } else @@ -2886,13 +3201,10 @@ finish_struct_1 (t, warn_anon) max_has_virtual = has_virtual; vfield = NULL_TREE; vfields = NULL_TREE; - last_x = NULL_TREE; + CLASSTYPE_RTTI (t) = NULL_TREE; cant_have_default_ctor = 0; cant_have_const_ctor = 0; - cant_synth_copy_ctor = 0; - cant_synth_asn_ref = 0; no_const_asn_ref = 0; - needs_virtual_dtor = 0; } #if 0 @@ -2908,19 +3220,17 @@ finish_struct_1 (t, warn_anon) /* The three of these are approximations which may later be modified. Needed at this point to make add_virtual_function and modify_vtable_entries work. */ - TREE_CHAIN (t_binfo) = TYPE_BINFO (t); - TYPE_BINFO (t) = t_binfo; CLASSTYPE_VFIELDS (t) = vfields; CLASSTYPE_VFIELD (t) = vfield; if (IS_SIGNATURE (t)) all_virtual = 0; - else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t)) + else if (flag_all_virtual == 1) all_virtual = 1; else all_virtual = 0; - for (x = CLASSTYPE_METHODS (t); x; x = TREE_CHAIN (x)) + for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) { GNU_xref_member (current_class_name, x); @@ -2939,48 +3249,61 @@ finish_struct_1 (t, warn_anon) DECL_SAVED_INSNS (x) = NULL_RTX; DECL_FIELD_SIZE (x) = 0; + check_for_override (x, t); + if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x)) + cp_error_at ("initializer specified for non-virtual method `%D'", x); + /* 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))) { - pending_virtuals = add_virtual_function (pending_virtuals, - &has_virtual, x, t); + add_virtual_function (&pending_virtuals, &pending_hard_virtuals, + &has_virtual, x, t); if (DECL_ABSTRACT_VIRTUAL_P (x)) abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals); +#if 0 + /* XXX Why did I comment this out? (jason) */ else TREE_USED (x) = 1; +#endif } } - for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x)) + if (n_baseclasses) + fields = chainon (build_vbase_pointer_fields (t), fields); + + last_x = NULL_TREE; + for (x = fields; x; x = TREE_CHAIN (x)) { GNU_xref_member (current_class_name, x); - /* Handle access declarations. */ - if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) + if (TREE_CODE (x) == FIELD_DECL) { - tree fdecl = TREE_OPERAND (DECL_NAME (x), 1); - enum access_type access - = TREE_PRIVATE (x) ? access_private : - TREE_PROTECTED (x) ? access_protected : access_public; + DECL_PACKED (x) |= TYPE_PACKED (t); + empty = 0; + } + if (TREE_CODE (x) == USING_DECL) + { + /* Save access declarations for later. */ if (last_x) TREE_CHAIN (last_x) = TREE_CHAIN (x); else fields = TREE_CHAIN (x); - - access_decls = tree_cons ((tree) access, fdecl, access_decls); + + access_decls = scratch_tree_cons (NULL_TREE, x, access_decls); continue; } last_x = x; - if (TREE_CODE (x) == TYPE_DECL) + if (TREE_CODE (x) == TYPE_DECL + || TREE_CODE (x) == TEMPLATE_DECL) continue; /* If we've gotten this far, it's a data member, possibly static, - or an enumerator. */ + or an enumerator. */ DECL_FIELD_CONTEXT (x) = t; @@ -3009,7 +3332,7 @@ finish_struct_1 (t, warn_anon) #if 0 if (DECL_NAME (x) == constructor_name (t)) - cant_have_default_ctor = cant_synth_copy_ctor = 1; + cant_have_default_ctor = 1; #endif if (TREE_TYPE (x) == error_mark_node) @@ -3049,8 +3372,8 @@ finish_struct_1 (t, warn_anon) aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ - cant_synth_asn_ref = 1; cant_have_default_ctor = 1; + TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) { @@ -3061,6 +3384,9 @@ finish_struct_1 (t, warn_anon) } } + if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) + has_pointers = 1; + /* If any field is const, the structure type is pseudo-const. */ if (TREE_READONLY (x)) { @@ -3072,8 +3398,8 @@ finish_struct_1 (t, warn_anon) aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ - cant_synth_asn_ref = 1; cant_have_default_ctor = 1; + TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) && extra_warnings) @@ -3118,9 +3444,26 @@ finish_struct_1 (t, warn_anon) /* Detect and ignore out of range field width. */ if (DECL_INITIAL (x)) { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); + tree w = DECL_INITIAL (x); + register int width = 0; + + /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ + STRIP_NOPS (w); + + /* detect invalid field size. */ + if (TREE_CODE (w) == CONST_DECL) + w = DECL_INITIAL (w); + else if (TREE_READONLY_DECL_P (w)) + w = decl_constant_value (w); - if (width < 0) + if (TREE_CODE (w) != INTEGER_CST) + { + cp_error_at ("bit-field `%D' width not an integer constant", + x); + DECL_INITIAL (x) = NULL_TREE; + } + else if (width = TREE_INT_CST_LOW (w), + width < 0) { DECL_INITIAL (x) = NULL; cp_error_at ("negative width in bit-field `%D'", x); @@ -3141,7 +3484,8 @@ finish_struct_1 (t, warn_anon) cp_error_at (" in declaration of `%D'", x); } else if (width > TYPE_PRECISION (TREE_TYPE (x)) - && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE) + && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE + && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE) { cp_warning_at ("width of `%D' exceeds its type", x); } @@ -3154,23 +3498,13 @@ finish_struct_1 (t, warn_anon) cp_warning_at ("`%D' is too small to hold all values of `%#T'", x, TREE_TYPE (x)); } - } - /* Process valid field width. */ - if (DECL_INITIAL (x)) - { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - - if (width == 0) + if (DECL_INITIAL (x) == NULL_TREE) + ; + else if (width == 0) { #ifdef EMPTY_FIELD_BOUNDARY - /* field size 0 => mark following field as "aligned" */ - if (TREE_CHAIN (x)) - DECL_ALIGN (TREE_CHAIN (x)) - = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY); - /* field of size 0 at the end => round up the size. */ - else - round_up_size = 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), @@ -3182,11 +3516,6 @@ finish_struct_1 (t, warn_anon) DECL_INITIAL (x) = NULL_TREE; DECL_FIELD_SIZE (x) = width; DECL_BIT_FIELD (x) = 1; - /* Traditionally a bit field is unsigned - even if declared signed. */ - if (flag_traditional - && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE) - TREE_TYPE (x) = unsigned_type_node; } } else @@ -3197,7 +3526,7 @@ finish_struct_1 (t, warn_anon) { tree type = TREE_TYPE (x); - if (TREE_CODE (type) == ARRAY_TYPE) + while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x) @@ -3219,8 +3548,8 @@ finish_struct_1 (t, warn_anon) fie = "constructor"; else if (TYPE_NEEDS_DESTRUCTOR (type)) fie = "destructor"; - else if (TYPE_HAS_REAL_ASSIGNMENT (type)) - fie = "assignment operator"; + else if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) + fie = "copy assignment operator"; if (fie) cp_error_at ("member `%#D' with %s not allowed in union", x, fie); @@ -3233,18 +3562,10 @@ finish_struct_1 (t, warn_anon) TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); } - if (! TYPE_HAS_INIT_REF (type) - || (TYPE_HAS_NONPUBLIC_CTOR (type) - && ! is_friend (t, type))) - cant_synth_copy_ctor = 1; - else if (!TYPE_HAS_CONST_INIT_REF (type)) + if (!TYPE_HAS_CONST_INIT_REF (type)) cant_have_const_ctor = 1; - if (! TYPE_HAS_ASSIGN_REF (type) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type) - && ! is_friend (t, type))) - cant_synth_asn_ref = 1; - else if (!TYPE_HAS_CONST_ASSIGN_REF (type)) + if (!TYPE_HAS_CONST_ASSIGN_REF (type)) no_const_asn_ref = 1; if (TYPE_HAS_CONSTRUCTOR (type) @@ -3294,41 +3615,50 @@ finish_struct_1 (t, warn_anon) && !IS_SIGNATURE (t)) { /* Here we must cons up a destructor on the fly. */ - tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0); + 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. */ + /* Link dtor onto end of fn_fields. */ TREE_CHAIN (dtor) = fn_fields; fn_fields = dtor; - if (DECL_VINDEX (dtor) == NULL_TREE - && (needs_virtual_dtor - || pending_virtuals != NULL_TREE - || pending_hard_virtuals != NULL_TREE)) - DECL_VINDEX (dtor) = error_mark_node; if (DECL_VINDEX (dtor)) - pending_virtuals = add_virtual_function (pending_virtuals, - &has_virtual, dtor, t); + add_virtual_function (&pending_virtuals, &pending_hard_virtuals, + &has_virtual, dtor, t); nonprivate_method = 1; } } + /* Effective C++ rule 11. */ + if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t) + && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t))) + { + cp_warning ("`%#T' has pointer data members", t); + + if (! TYPE_HAS_INIT_REF (t)) + { + cp_warning (" but does not override `%T(const %T&)'", t, t); + if (! TYPE_HAS_ASSIGN_REF (t)) + cp_warning (" or `operator=(const %T&)'", t); + } + 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); - if (flag_rtti && (max_has_virtual > 0 || needs_virtual_dtor) && - has_virtual == 0) - has_virtual = 1; TYPE_HAS_COMPLEX_INIT_REF (t) |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || any_default_members); + || has_virtual || any_default_members); TYPE_NEEDS_CONSTRUCTING (t) |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || any_default_members || first_vfn_base_index >= 0); + || has_virtual || any_default_members); if (! IS_SIGNATURE (t)) CLASSTYPE_NON_AGGREGATE (t) = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t); @@ -3346,8 +3676,7 @@ finish_struct_1 (t, warn_anon) } /* Create default copy constructor, if needed. */ - if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor - && ! IS_SIGNATURE (t)) + 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 */ @@ -3362,8 +3691,7 @@ finish_struct_1 (t, warn_anon) TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); - if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref - && ! IS_SIGNATURE (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); @@ -3373,19 +3701,20 @@ finish_struct_1 (t, warn_anon) if (fn_fields) { + 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_NAME (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 = DECL_CHAIN (ctor)) - if (! TREE_PRIVATE (ctor)) + ctor = OVL_NEXT (ctor)) + if (! TREE_PRIVATE (OVL_CURRENT (ctor))) { nonprivate_ctor = 1; break; @@ -3406,68 +3735,9 @@ finish_struct_1 (t, warn_anon) TYPE_HAS_DESTRUCTOR (t) = 0; } - { - int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; - - for (access_decls = nreverse (access_decls); access_decls; - access_decls = TREE_CHAIN (access_decls)) - { - tree fdecl = TREE_VALUE (access_decls); - tree flist = NULL_TREE; - tree name; - enum access_type access = (enum access_type)TREE_PURPOSE(access_decls); - int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1; - tree tmp; - - if (TREE_CODE (fdecl) == TREE_LIST) - { - flist = fdecl; - fdecl = TREE_VALUE (flist); - } - - name = DECL_NAME (fdecl); - - for (; i < n_methods; i++) - if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name) - { - cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); - cp_error_at (" because of local method `%#D' with same name", - TREE_VEC_ELT (method_vec, i)); - fdecl = NULL_TREE; - break; - } - - if (! fdecl) - continue; - - for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp)) - if (DECL_NAME (tmp) == name) - { - cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); - cp_error_at (" because of local field `%#D' with same name", tmp); - fdecl = NULL_TREE; - break; - } - - if (!fdecl) - continue; - - /* Make type T see field decl FDECL with access ACCESS.*/ - if (flist) - { - fdecl = TREE_VALUE (flist); - while (fdecl) - { - if (alter_access (t, fdecl, access) == 0) - break; - fdecl = DECL_CHAIN (fdecl); - } - } - else - alter_access (t, fdecl, access); - } - - } + for (access_decls = nreverse (access_decls); access_decls; + access_decls = TREE_CHAIN (access_decls)) + handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields); if (vfield == NULL_TREE && has_virtual) { @@ -3477,23 +3747,26 @@ finish_struct_1 (t, warn_anon) 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. */ + them too. */ DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE); CLASSTYPE_VFIELD (t) = vfield; DECL_VIRTUAL_P (vfield) = 1; + DECL_ARTIFICIAL (vfield) = 1; DECL_FIELD_CONTEXT (vfield) = t; DECL_CLASS_CONTEXT (vfield) = t; DECL_FCONTEXT (vfield) = t; DECL_SAVED_INSNS (vfield) = NULL_RTX; DECL_FIELD_SIZE (vfield) = 0; DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); - if (CLASSTYPE_RTTI (t)) - { - /* vfield is always first entry in structure. */ - TREE_CHAIN (vfield) = fields; - fields = vfield; - } - else if (last_x) +#if 0 + /* This is more efficient, but breaks binary compatibility, turn + it on sometime when we don't care. If we turn it on, we also + have to enable the code in dfs_init_vbase_pointers. */ + /* vfield is always first entry in structure. */ + TREE_CHAIN (vfield) = fields; + fields = vfield; +#else + if (last_x) { my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175); TREE_CHAIN (last_x) = vfield; @@ -3501,6 +3774,8 @@ finish_struct_1 (t, warn_anon) } else fields = vfield; +#endif + empty = 0; vfields = chainon (vfields, CLASSTYPE_AS_LIST (t)); } @@ -3534,13 +3809,18 @@ finish_struct_1 (t, warn_anon) for (x = fields; x; x = TREE_CHAIN (x)) { tree name = DECL_NAME (x); - int i = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1; + int i = 2; + + if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)) + continue; + for (; i < n_methods; ++i) - if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name) + 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'", - TREE_VEC_ELT (method_vec, i)); + OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); break; } } @@ -3551,114 +3831,65 @@ finish_struct_1 (t, warn_anon) TYPE_FIELDS (t) = fields; - /* If there's a :0 field at the end, round the size to the - EMPTY_FIELD_BOUNDARY. */ - TYPE_ALIGN (t) = round_up_size; - - /* Pass layout information about base classes to layout_type, if any. */ if (n_baseclasses) { - tree pseudo_basetype = TREE_TYPE (base_layout_decl); + last_x = build_base_fields (t); - TREE_CHAIN (base_layout_decl) = TYPE_FIELDS (t); - TYPE_FIELDS (t) = base_layout_decl; - - TYPE_SIZE (pseudo_basetype) = CLASSTYPE_SIZE (t); - TYPE_MODE (pseudo_basetype) = TYPE_MODE (t); - TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t); - DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype); - /* Don't re-use old size. */ - DECL_SIZE (base_layout_decl) = NULL_TREE; + /* If all our bases are empty, we can be empty too. */ + for (x = last_x; empty && x; x = TREE_CHAIN (x)) + if (DECL_SIZE (x) != integer_zero_node) + empty = 0; + } + if (empty) + { + /* C++: do not let empty structures exist. */ + tree decl = build_lang_field_decl + (FIELD_DECL, NULL_TREE, char_type_node); + TREE_CHAIN (decl) = fields; + TYPE_FIELDS (t) = decl; } + if (n_baseclasses) + TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t)); layout_type (t); - { - tree field; - for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) - { - if (TREE_STATIC (field)) - continue; - if (TREE_CODE (field) != FIELD_DECL) - continue; - - /* If this field is an anonymous union, - give each union-member the same position as the union has. - - ??? This is a real kludge because it makes the structure - of the types look strange. This feature is only used by - C++, which should have build_component_ref build two - COMPONENT_REF operations, one for the union and one for - the inner field. We set the offset of this field to zero - so that either the old or the correct method will work. - Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are - moved into the type of this field, but nothing seems to break - by doing this. */ - - if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - tree uelt = TYPE_FIELDS (TREE_TYPE (field)); - for (; uelt; uelt = TREE_CHAIN (uelt)) - { - if (TREE_CODE (uelt) != FIELD_DECL) - continue; - - if (TREE_PRIVATE (uelt)) - cp_pedwarn_at ("private member `%#D' in anonymous union", - uelt); - else if (TREE_PROTECTED (uelt)) - cp_pedwarn_at ("protected member `%#D' in anonymous union", - uelt); - - DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); - DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); - } - - DECL_FIELD_BITPOS (field) = integer_zero_node; - } - } - } - - if (n_baseclasses) - TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t)); + /* Remember the size and alignment of the class before adding + the virtual bases. */ + if (empty && flag_new_abi) + CLASSTYPE_SIZE (t) = integer_zero_node; + else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t) + && TYPE_HAS_COMPLEX_ASSIGN_REF (t)) + CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t); + else + CLASSTYPE_SIZE (t) = TYPE_SIZE (t); + CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t); - /* C++: do not let empty structures exist. */ - if (integer_zerop (TYPE_SIZE (t))) - TYPE_SIZE (t) = TYPE_SIZE (char_type_node); + finish_struct_anon (t); /* Set the TYPE_DECL for this type to contain the right value for DECL_OFFSET, so that we can use it as part of a COMPONENT_REF for multiple inheritance. */ - if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) - layout_decl (TYPE_NAME (t), 0); + layout_decl (TYPE_MAIN_DECL (t), 0); /* Now fix up any virtual base class types that we left lying around. We must get these done before we try to lay out the virtual function table. */ - doing_hard_virtuals = 1; pending_hard_virtuals = nreverse (pending_hard_virtuals); + if (n_baseclasses) + /* layout_basetypes will remove the base subobject fields. */ + max_has_virtual = layout_basetypes (t, max_has_virtual); + else if (empty) + TYPE_FIELDS (t) = fields; + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) { tree vbases; - max_has_virtual = layout_vbasetypes (t, max_has_virtual); vbases = CLASSTYPE_VBASECLASSES (t); CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); - /* The rtti code should do this. (mrs) */ -#if 0 - while (vbases) - { - /* Update rtti info with offsets for virtual baseclasses. */ - if (flag_rtti && ! BINFO_NEW_VTABLE_MARKED (vbases)) - prepare_fresh_vtable (vbases, t); - vbases = TREE_CHAIN (vbases); - } -#endif - { /* Now fixup overrides of all functions in vtables from all direct or indirect virtual base classes. */ @@ -3681,19 +3912,6 @@ finish_struct_1 (t, warn_anon) } } } - - /* Now fixup any virtual function entries from virtual bases - that have different deltas. */ - vbases = CLASSTYPE_VBASECLASSES (t); - while (vbases) - { - /* We might be able to shorten the amount of work we do by - only doing this for vtables that come from virtual bases - that have differing offsets, but don't want to miss any - entries. */ - fixup_vtable_deltas (vbases, 1, t); - vbases = TREE_CHAIN (vbases); - } } /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we @@ -3736,38 +3954,53 @@ finish_struct_1 (t, warn_anon) TREE_VALUE (pending_hard_virtuals)); pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals); } - doing_hard_virtuals = 0; + + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) + { + tree vbases; + /* Now fixup any virtual function entries from virtual bases + that have different deltas. This has to come after we do the + pending hard virtuals, as we might have a function that comes + from multiple virtual base instances that is only overridden + by a hard virtual above. */ + vbases = CLASSTYPE_VBASECLASSES (t); + while (vbases) + { + /* We might be able to shorten the amount of work we do by + only doing this for vtables that come from virtual bases + that have differing offsets, but don't want to miss any + entries. */ + fixup_vtable_deltas (vbases, 1, t); + vbases = TREE_CHAIN (vbases); + } + } /* Under our model of GC, every C++ class gets its own virtual function table, at least virtually. */ - if (pending_virtuals || (flag_rtti && TYPE_VIRTUAL_P (t))) + if (pending_virtuals) { pending_virtuals = nreverse (pending_virtuals); /* We must enter these virtuals into the table. */ if (first_vfn_base_index < 0) { - /* The first slot is for the rtti offset. */ - pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); - /* 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); - set_rtti_entry (pending_virtuals, integer_zero_node, t); + /* 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); build_vtable (NULL_TREE, t); } else { - tree offset; /* Here we know enough to change the type of our virtual function table, but we will wait until later this function. */ if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t))) build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t); - - offset = get_derived_offset (TYPE_BINFO (t), NULL_TREE); - offset = size_binop (MINUS_EXPR, integer_zero_node, offset); - set_rtti_entry (TYPE_BINFO_VIRTUALS (t), offset, t); } /* If this type has basetypes with constructors, then those @@ -3877,42 +4110,6 @@ finish_struct_1 (t, warn_anon) } } - /* Now add the tags, if any, to the list of TYPE_DECLs - defined for this type. */ - if (CLASSTYPE_TAGS (t)) - { - x = CLASSTYPE_TAGS (t); - last_x = tree_last (TYPE_FIELDS (t)); - while (x) - { - tree tag = TYPE_NAME (TREE_VALUE (x)); - - /* Check to see if it is already there. This will be the case if - was do enum { red; } color; */ - if (chain_member (tag, TYPE_FIELDS (t))) - { - x = TREE_CHAIN (x); - continue; - } - -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) - { - /* Notify dwarfout.c that this TYPE_DECL node represent a - gratuitous typedef. */ - DECL_IGNORED_P (tag) = 1; - } -#endif /* DWARF_DEBUGGING_INFO */ - - TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0; - x = TREE_CHAIN (x); - last_x = chainon (last_x, tag); - } - if (TYPE_FIELDS (t) == NULL_TREE) - TYPE_FIELDS (t) = last_x; - CLASSTYPE_LOCAL_TYPEDECLS (t) = 1; - } - if (TYPE_HAS_CONSTRUCTOR (t)) { tree vfields = CLASSTYPE_VFIELDS (t); @@ -3932,9 +4129,6 @@ finish_struct_1 (t, warn_anon) else if (TYPE_NEEDS_CONSTRUCTING (t)) build_class_init_list (t); - if (! IS_SIGNATURE (t)) - embrace_waiting_friends (t); - /* Write out inline function definitions. */ do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t)); CLASSTYPE_INLINE_FRIENDS (t) = 0; @@ -3942,7 +4136,7 @@ finish_struct_1 (t, warn_anon) if (CLASSTYPE_VSIZE (t) != 0) { #if 0 - /* This is now done above. */ + /* This is now done above. */ if (DECL_FIELD_CONTEXT (vfield) != t) { tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0); @@ -3961,13 +4155,13 @@ finish_struct_1 (t, warn_anon) } #endif - /* In addition to this one, all the other vfields should be listed. */ + /* 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); if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t) - && DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE) + && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE) cp_warning ("`%#T' has virtual functions but non-virtual destructor", t); } @@ -3975,22 +4169,17 @@ finish_struct_1 (t, warn_anon) /* Make the rtl for any new vtables we have created, and unmark the base types we marked. */ finish_vtbls (TYPE_BINFO (t), 1, t); - TYPE_BEING_DEFINED (t) = 0; hack_incomplete_structures (t); #if 0 if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) undo_template_name_overload (TYPE_IDENTIFIER (t), 1); #endif - if (current_class_type) - popclass (0); - else - error ("trying to finish struct, but kicked out due to previous parse errors."); resume_momentary (old); - if (flag_cadillac) - cadillac_finish_struct (t); + if (warn_overloaded_virtual) + warn_hidden (t); #if 0 /* This has to be done after we have sorted out what to do with @@ -3999,13 +4188,12 @@ finish_struct_1 (t, warn_anon) { /* Be smarter about nested classes here. If a type is nested, only output it if we would output the enclosing type. */ - if (DECL_CONTEXT (TYPE_NAME (t)) - && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (TYPE_NAME (t)))) == 't') - DECL_IGNORED_P (TYPE_NAME (t)) = TREE_ASM_WRITTEN (TYPE_NAME (t)); + if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (t))) + DECL_IGNORED_P (TYPE_MAIN_DECL (t)) = TREE_ASM_WRITTEN (TYPE_MAIN_DECL (t)); } #endif - if (write_symbols != DWARF_DEBUG) + if (write_symbols != DWARF_DEBUG && write_symbols != DWARF2_DEBUG) { /* If the type has methods, we want to think about cutting down the amount of symbol table stuff we output. The value stored in @@ -4013,7 +4201,10 @@ finish_struct_1 (t, warn_anon) For example, if a member function is seen and we decide to write out that member function, then we can change the value of the DECL_IGNORED_P slot, and the type will be output when - that member function's debug info is written out. */ + that member function's debug info is written out. + + We can't do this with DWARF, which does not support name + references between translation units. */ if (CLASSTYPE_METHOD_VEC (t)) { extern tree pending_vtables; @@ -4021,16 +4212,19 @@ finish_struct_1 (t, warn_anon) /* 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_NAME (t)) + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0); else if (CLASSTYPE_INTERFACE_ONLY (t)) - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; +#if 0 + /* XXX do something about this. */ else if (CLASSTYPE_INTERFACE_UNKNOWN (t)) /* Only a first approximation! */ - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; +#endif } else if (CLASSTYPE_INTERFACE_ONLY (t)) - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; } /* Finish debugging output for this type. */ @@ -4040,16 +4234,19 @@ finish_struct_1 (t, warn_anon) } tree -finish_struct (t, list_of_fieldlists, warn_anon) - tree t; - tree list_of_fieldlists; +finish_struct (t, list_of_fieldlists, attributes, warn_anon) + tree t, list_of_fieldlists, attributes; int warn_anon; { - tree fields = NULL_TREE, fn_fields, *tail; - tree *tail_user_methods = &CLASSTYPE_METHODS (t); + 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; - enum access_type access; + tree access; + tree dummy = NULL_TREE; + tree next_x = NULL_TREE; if (TREE_CODE (name) == TYPE_DECL) { @@ -4071,34 +4268,53 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (IS_SIGNATURE (t)) append_signature_fields (list_of_fieldlists); - tail = &fn_fields; - if (last_x && list_of_fieldlists) - TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); - - /* For signatures, we made all methods `public' in the parser and - reported an error if a access specifier was used. */ - if (CLASSTYPE_DECLARED_CLASS (t) == 0) + /* 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))) { - if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_public; + dummy = TREE_VALUE (list_of_fieldlists); + list_of_fieldlists = TREE_CHAIN (list_of_fieldlists); } - else if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_private; + + if (last_x && list_of_fieldlists) + TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); while (list_of_fieldlists) { - access = (enum access_type)TREE_PURPOSE (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 = TREE_CHAIN (x)) + for (x = TREE_VALUE (list_of_fieldlists); x; x = next_x) { - TREE_PRIVATE (x) = access == access_private; - TREE_PROTECTED (x) = access == access_protected; + 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. - /* Check for inconsistent use of this name in the class body. Enums, types and static vars have already been checked. */ - if (TREE_CODE (x) != TYPE_DECL + 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); @@ -4111,6 +4327,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) icv = NULL_TREE; if (icv + && flag_optional_diags /* Don't complain about constructors. */ && name != constructor_name (current_class_type) /* Or inherited names. */ @@ -4119,35 +4336,42 @@ finish_struct (t, list_of_fieldlists, warn_anon) && !(TREE_CODE (icv) == TYPE_DECL && DECL_CONTEXT (icv) == t)) { - cp_error_at ("declaration of identifier `%D' as `%+#D'", - name, x); - cp_error_at ("conflicts with other use in class as `%#D'", - icv); + 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) + if (TREE_CODE (x) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (x)) { + DECL_CLASS_CONTEXT (x) = t; + if (last_x) - TREE_CHAIN (last_x) = TREE_CHAIN (x); - /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */ + 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); - *tail_user_methods = x; - tail_user_methods = &DECL_NEXT_METHOD (x); continue; } -#if 0 - /* Handle access declarations. */ - if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) - { - tree n = DECL_NAME (x); - x = build_decl - (USING_DECL, DECL_NAME (TREE_OPERAND (n, 1)), TREE_TYPE (x)); - DECL_RESULT (x) = n; - } -#endif + if (TREE_CODE (x) != TYPE_DECL) + DECL_FIELD_CONTEXT (x) = t; if (! fields) fields = x; @@ -4166,17 +4390,122 @@ finish_struct (t, list_of_fieldlists, warn_anon) } } + /* 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; - *tail_user_methods = NULL_TREE; TYPE_FIELDS (t) = fields; - if (0 && processing_template_defn) + cplus_decl_attributes (t, attributes, NULL_TREE); + + if (processing_template_decl) { - CLASSTYPE_METHOD_VEC (t) = finish_struct_methods (t, fn_fields, 1); - return t; + tree d = getdecls (); + for (; d; d = TREE_CHAIN (d)) + { + /* If this is the decl for the class or one of the template + parms, we've seen all the injected decls. */ + if ((TREE_CODE (d) == TYPE_DECL + && (TREE_TYPE (d) == t + || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM + || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TEMPLATE_PARM)) + || TREE_CODE (d) == CONST_DECL) + break; + /* Don't inject cache decls. */ + else if (IDENTIFIER_TEMPLATE (DECL_NAME (d))) + continue; + DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)) + = tree_cons (NULL_TREE, d, + DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))); + } + CLASSTYPE_METHOD_VEC (t) + = finish_struct_methods (t, TYPE_METHODS (t), 1); + TYPE_SIZE (t) = integer_zero_node; + } + else + t = 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); else - return finish_struct_1 (t, warn_anon); + 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. @@ -4185,6 +4514,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) *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; @@ -4219,13 +4549,6 @@ resolves_to_fixed_type_p (instance, nonnull) return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); case RTL_EXPR: - /* This is a call to `new', hence it's never zero. */ - if (TREE_CALLS_NEW (instance)) - { - if (nonnull) - *nonnull = 1; - return 1; - } return 0; case PLUS_EXPR: @@ -4249,10 +4572,6 @@ resolves_to_fixed_type_p (instance, nonnull) case COMPONENT_REF: return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull); - case WITH_CLEANUP_EXPR: - if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR) - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - /* fall through... */ case VAR_DECL: case FIELD_DECL: if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE @@ -4262,7 +4581,7 @@ resolves_to_fixed_type_p (instance, nonnull) *nonnull = 1; return 1; } - /* fall through... */ + /* fall through... */ case TARGET_EXPR: case PARM_DECL: if (IS_AGGR_TYPE (TREE_TYPE (instance))) @@ -4273,7 +4592,7 @@ resolves_to_fixed_type_p (instance, nonnull) } else if (nonnull) { - if (instance == current_class_decl + if (instance == current_class_ptr && flag_this_is_variable <= 0) { /* Some people still use `this = 0' inside destructors. */ @@ -4305,8 +4624,16 @@ init_class_processing () current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree)); current_lang_stack = current_lang_base; + access_default_node = build_int_2 (0, 0); + access_public_node = build_int_2 (1, 0); + access_protected_node = build_int_2 (2, 0); + access_private_node = build_int_2 (3, 0); + access_default_virtual_node = build_int_2 (4, 0); + access_public_virtual_node = build_int_2 (5, 0); + access_protected_virtual_node = build_int_2 (6, 0); + access_private_virtual_node = build_int_2 (7, 0); + /* Keep these values lying around. */ - the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node); base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node); TREE_TYPE (base_layout_decl) = make_node (RECORD_TYPE); @@ -4352,6 +4679,7 @@ pushclass (type, modify) tree type; int modify; { + type = TYPE_MAIN_VARIANT (type); push_memoized_context (type, modify); current_class_depth++; @@ -4359,9 +4687,9 @@ pushclass (type, modify) *current_class_stack++ = current_class_type; if (current_class_stack >= current_class_base + current_class_stacksize) { - current_class_base = - (tree *)xrealloc (current_class_base, - sizeof (tree) * (current_class_stacksize + 10)); + 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; } @@ -4382,6 +4710,11 @@ pushclass (type, modify) pushlevel_class (); +#if 0 + if (CLASSTYPE_TEMPLATE_INFO (type)) + overload_template_name (type); +#endif + if (modify) { tree tags; @@ -4394,15 +4727,15 @@ pushclass (type, modify) else current_function_decl = NULL_TREE; - if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) - declare_uninstantiated_type_level (); - else if (type != previous_class_type || current_class_depth > 1) + if (type != previous_class_type || current_class_depth > 1) { +#ifdef MI_MATRIX build_mi_matrix (type); push_class_decls (type); free_mi_matrix (); - if (current_class_depth == 1) - previous_class_type = type; +#else + push_class_decls (type); +#endif } else { @@ -4423,35 +4756,33 @@ pushclass (type, modify) unuse_fields (type); } - if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type))) - overload_template_name (current_class_name, 0); - for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags)) { - TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1; + tree tag_type = TREE_VALUE (tags); + + TREE_NONLOCAL_FLAG (tag_type) = 1; if (! TREE_PURPOSE (tags)) continue; - pushtag (TREE_PURPOSE (tags), TREE_VALUE (tags), 0); + 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)); } current_function_decl = this_fndecl; } - - if (flag_cadillac) - cadillac_push_class (type); } /* 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. */ + void popclass (modify) int modify; { - if (flag_cadillac) - cadillac_pop_class (); - if (modify < 0) { /* Back this old class out completely. */ @@ -4482,8 +4813,6 @@ popclass (modify) TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0; tags = TREE_CHAIN (tags); } - if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))) - undo_template_name_overload (current_class_name, 0); } /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition, @@ -4494,7 +4823,7 @@ popclass (modify) 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 (current_class_type); + pop_class_decls (); current_class_depth--; current_class_type = *--current_class_stack; @@ -4506,6 +4835,21 @@ popclass (modify) ; } +/* Returns 1 if current_class_type is either T or a nested type of T. */ + +int +currently_open_class (t) + tree t; +{ + int i; + if (t == current_class_type) + return 1; + for (i = 0; i < current_class_depth; ++i) + if (current_class_stack [-i*2 - 1] == t) + return 1; + return 0; +} + /* When entering a class scope, all enclosing class scopes' names with static meaning (static variables, static functions, types and enumerators) have to be visible. This recursive function calls pushclass for all @@ -4520,10 +4864,14 @@ push_nested_class (type, modify) { tree context; - if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)) + my_friendly_assert (!type || TREE_CODE (type) != NAMESPACE_DECL, 980711); + + if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type) + || TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM) return; - context = DECL_CONTEXT (TYPE_NAME (type)); + context = DECL_CONTEXT (TYPE_MAIN_DECL (type)); if (context && TREE_CODE (context) == RECORD_TYPE) push_nested_class (context, 2); @@ -4536,7 +4884,7 @@ void pop_nested_class (modify) int modify; { - tree context = DECL_CONTEXT (TYPE_NAME (current_class_type)); + tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type)); popclass (modify); if (context && TREE_CODE (context) == RECORD_TYPE) @@ -4553,14 +4901,14 @@ push_lang_context (name) *current_lang_stack++ = current_lang_name; if (current_lang_stack >= current_lang_base + current_lang_stacksize) { - current_lang_base = - (tree *)xrealloc (current_lang_base, - sizeof (tree) * (current_lang_stacksize + 10)); + current_lang_base + = (tree *)xrealloc (current_lang_base, + sizeof (tree) * (current_lang_stacksize + 10)); current_lang_stack = current_lang_base + current_lang_stacksize; current_lang_stacksize += 10; } - if (name == lang_name_cplusplus) + if (name == lang_name_cplusplus || name == lang_name_java) { strict_prototype = strict_prototypes_lang_cplusplus; current_lang_name = name; @@ -4572,44 +4920,64 @@ push_lang_context (name) } else error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name)); - - if (flag_cadillac) - cadillac_push_lang (name); } /* Get out of the current language scope. */ + void pop_lang_context () { - if (flag_cadillac) - cadillac_pop_lang (); - current_lang_name = *--current_lang_stack; - if (current_lang_name == lang_name_cplusplus) + if (current_lang_name == lang_name_cplusplus + || current_lang_name == lang_name_java) strict_prototype = strict_prototypes_lang_cplusplus; else if (current_lang_name == lang_name_c) strict_prototype = strict_prototypes_lang_c; } + +/* Type instantiation routines. */ -int -root_lang_context_p () +static tree +validate_lhs (lhstype, complain) + tree lhstype; + int complain; { - return current_lang_stack == current_lang_base; + if (TYPE_PTRMEMFUNC_P (lhstype)) + lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype); + + if (TREE_CODE (lhstype) == POINTER_TYPE) + { + if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE) + lhstype = TREE_TYPE (lhstype); + else + { + if (complain) + error ("invalid type combination for overload"); + return error_mark_node; + } + } + return lhstype; } - -/* Type instantiation routines. */ -/* This function will instantiate the type of the expression given - in RHS to match the type of LHSTYPE. If LHSTYPE is NULL_TREE, - or other errors exist, the TREE_TYPE of RHS will be ERROR_MARK_NODE. +/* 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 + 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. */ + tree instantiate_type (lhstype, rhs, complain) tree lhstype, rhs; int complain; { + tree explicit_targs = NULL_TREE; + int template_only = 0; + if (TREE_CODE (lhstype) == UNKNOWN_TYPE) { if (complain) @@ -4618,7 +4986,19 @@ instantiate_type (lhstype, rhs, complain) } if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs))) - return rhs; + { + if (comptypes (lhstype, TREE_TYPE (rhs), 1)) + return rhs; + if (complain) + cp_error ("argument of type `%T' does not match `%T'", + TREE_TYPE (rhs), lhstype); + return error_mark_node; + } + + /* We don't overwrite rhs if it is an overloaded function. + Copying it would destroy the tree link. */ + if (TREE_CODE (rhs) != OVERLOAD) + rhs = copy_node (rhs); /* This should really only be used when attempting to distinguish what sort of a pointer to function we have. For now, any @@ -4637,14 +5017,18 @@ instantiate_type (lhstype, rhs, complain) case INDIRECT_REF: case ARRAY_REF: - TREE_TYPE (rhs) = lhstype; - lhstype = build_pointer_type (lhstype); - TREE_OPERAND (rhs, 0) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - if (TREE_OPERAND (rhs, 0) == error_mark_node) - return error_mark_node; + { + tree new_rhs; - return rhs; + new_rhs = instantiate_type (build_pointer_type (lhstype), + TREE_OPERAND (rhs, 0), complain); + if (new_rhs == error_mark_node) + return error_mark_node; + + TREE_TYPE (rhs) = lhstype; + TREE_OPERAND (rhs, 0) = new_rhs; + return rhs; + } case NOP_EXPR: rhs = copy_node (TREE_OPERAND (rhs, 0)); @@ -4671,9 +5055,13 @@ instantiate_type (lhstype, rhs, complain) return error_mark_node; return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function)); } + mark_used (function); return function; } + /* 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), @@ -4687,6 +5075,7 @@ instantiate_type (lhstype, rhs, complain) if (field) { TREE_OPERAND (rhs, 1) = field; + mark_used (field); return rhs; } @@ -4713,144 +5102,194 @@ instantiate_type (lhstype, rhs, complain) error ("no appropriate overload exists for COMPONENT_REF"); return error_mark_node; } +#endif return rhs; } - case TREE_LIST: - { - tree elem, baselink, name; - int globals = overloaded_globals_p (rhs); - -#if 0 /* obsolete */ - /* If there's only one function we know about, return that. */ - if (globals > 0 && TREE_CHAIN (rhs) == NULL_TREE) - return TREE_VALUE (rhs); -#endif + case OFFSET_REF: + /* 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. */ - /* First look for an exact match. Search either overloaded - functions or member functions. May have to undo what - `default_conversion' might do to lhstype. */ + 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); - if (TYPE_PTRMEMFUNC_P (lhstype)) - lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype); + case OVERLOAD: + { + tree elem, elems; - if (TREE_CODE (lhstype) == POINTER_TYPE) - if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE) - lhstype = TREE_TYPE (lhstype); - else - { - if (complain) - error ("invalid type combination for overload"); - return error_mark_node; - } + /* 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 && globals > 0) + 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", - TREE_PURPOSE (rhs)); + cp_error("cannot resolve overloaded function `%D' " + "based on non-function type", + DECL_NAME (OVL_FUNCTION (rhs))); return error_mark_node; } - - if (globals > 0) + + /* 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 = get_first_fn (rhs); - while (elem) - if (! comptypes (lhstype, TREE_TYPE (elem), 1)) - elem = DECL_CHAIN (elem); - else + elem = OVL_FUNCTION (elems); + if (comptypes (lhstype, TREE_TYPE (elem), 1)) + { + mark_used (elem); return elem; + } + } - /* No exact match found, look for a compatible template. */ - { - tree save_elem = 0; - for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem)) - if (TREE_CODE (elem) == TEMPLATE_DECL) + /* 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) { - int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem)); - tree *t = (tree *) alloca (sizeof (tree) * n); - int i, d = 0; - i = type_unification (DECL_TEMPLATE_PARMS (elem), t, - TYPE_ARG_TYPES (TREE_TYPE (elem)), - TYPE_ARG_TYPES (lhstype), &d, 0); - if (i == 0) + if (save_elem) { - 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; + cp_error ("ambiguous template instantiation converting to `%#T'", lhstype); + return error_mark_node; } + save_elem = instantiate_template (elem, t); + /* Check the return type. */ + if (! comptypes (TREE_TYPE (lhstype), + TREE_TYPE (TREE_TYPE (save_elem)), 1)) + save_elem = 0; } - if (save_elem) - return save_elem; + } + if (save_elem) + { + mark_used (save_elem); + return save_elem; } + } - /* No match found, look for a compatible function. */ - elem = get_first_fn (rhs); - while (elem && comp_target_types (lhstype, - TREE_TYPE (elem), 1) <= 0) - elem = DECL_CHAIN (elem); - if (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; - elem = DECL_CHAIN (elem); - while (elem && comp_target_types (lhstype, - TREE_TYPE (elem), 0) <= 0) - elem = DECL_CHAIN (elem); - if (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 + ("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; } - if (complain) - { - cp_error ("cannot resolve overload to target type `%#T'", - lhstype); - cp_error (" because no suitable overload of function `%D' exists", - TREE_PURPOSE (rhs)); - } - return error_mark_node; } - if (TREE_NONLOCAL_FLAG (rhs)) + /* We failed to find a match. */ + if (complain) { - /* Got to get it as a baselink. */ - rhs = lookup_fnfields (TYPE_BINFO (current_class_type), - TREE_PURPOSE (rhs), 0); + 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))); } - else + return error_mark_node; + } + + case TREE_LIST: + { + tree elem, baselink, name = NULL_TREE; + + if (TREE_PURPOSE (rhs) == error_mark_node) { - my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181); - if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST) - rhs = TREE_VALUE (rhs); - my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL, - 182); + /* 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. */ + + 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 (elem), 1)) - return elem; + if (comptypes (lhstype, TREE_TYPE (OVL_CURRENT (elem)), 1)) + { + mark_used (OVL_CURRENT (elem)); + return OVL_CURRENT (elem); + } else - elem = DECL_CHAIN (elem); + elem = OVL_NEXT (elem); } /* No exact match found, look for a compatible method. */ @@ -4858,25 +5297,30 @@ instantiate_type (lhstype, rhs, complain) baselink = next_baselink (baselink)) { elem = TREE_VALUE (baselink); - while (elem && comp_target_types (lhstype, - TREE_TYPE (elem), 1) <= 0) - elem = DECL_CHAIN (elem); + for (; elem; elem = OVL_NEXT (elem)) + if (comp_target_types (lhstype, + TREE_TYPE (OVL_CURRENT (elem)), 1) > 0) + break; if (elem) { - tree save_elem = elem; - elem = DECL_CHAIN (elem); - while (elem && comp_target_types (lhstype, - TREE_TYPE (elem), 0) <= 0) - elem = DECL_CHAIN (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 = DECL_NAME (TREE_VALUE (rhs)); + 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) { @@ -5006,15 +5450,20 @@ instantiate_type (lhstype, rhs, complain) error ("type for resolving address of overloaded function must be pointer type"); return error_mark_node; } - TREE_TYPE (rhs) = lhstype; - lhstype = TREE_TYPE (lhstype); { - tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); + 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; @@ -5036,6 +5485,7 @@ instantiate_type (lhstype, rhs, complain) this may have to look back through base types to find the ultimate field name. (For single inheritance, these could all be the same name. Who knows for multiple inheritance). */ + static tree get_vfield_name (type) tree type; @@ -5049,8 +5499,8 @@ get_vfield_name (type) binfo = BINFO_BASETYPE (binfo, 0); type = BINFO_TYPE (binfo); - buf = (char *)alloca (sizeof (VFIELD_NAME_FORMAT) - + TYPE_NAME_LENGTH (type) + 2); + buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT) + + TYPE_NAME_LENGTH (type) + 2); sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type)); return get_identifier (buf); } @@ -5077,6 +5527,7 @@ print_class_statistics () 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. */ + void maybe_push_cache_obstack () { @@ -5084,3 +5535,49 @@ maybe_push_cache_obstack () if (current_class_depth == 1) current_obstack = &permanent_obstack; } + +/* Build a dummy reference to ourselves so Derived::Base (and A::A) works, + according to [class]: + The class-name is also inserted + 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 +build_self_reference () +{ + tree name = constructor_name (current_class_type); + tree value = build_lang_decl (TYPE_DECL, name, current_class_type); + 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; +} + +/* Returns 1 if TYPE contains only padding bytes. */ + +int +is_empty_class (type) + tree type; +{ + tree t; + + if (type == error_mark_node) + return 0; + + if (! IS_AGGR_TYPE (type)) + return 0; + + if (flag_new_abi) + return CLASSTYPE_SIZE (type) == integer_zero_node; + + if (TYPE_BINFO_BASETYPES (type)) + return 0; + t = TYPE_FIELDS (type); + while (t && TREE_CODE (t) != FIELD_DECL) + t = TREE_CHAIN (t); + return (t == NULL_TREE); +} diff --git a/contrib/gcc/cp/config-lang.in b/contrib/gcc/cp/config-lang.in index 7a9a5c5..9b39d51 100644 --- a/contrib/gcc/cp/config-lang.in +++ b/contrib/gcc/cp/config-lang.in @@ -32,4 +32,10 @@ compilers="cc1plus\$(exeext)" stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)" -diff_excludes="-x cp/parse.c -x cp/parse.h" +diff_excludes="-x parse.c -x parse.h" + +headers='$(CXX_EXTRA_HEADERS)' + +lib2funcs=cplib2.txt + +outputs=cp/Makefile diff --git a/contrib/gcc/cp/cp-tree.def b/contrib/gcc/cp/cp-tree.def new file mode 100644 index 0000000..dbbdb66 --- /dev/null +++ b/contrib/gcc/cp/cp-tree.def @@ -0,0 +1,240 @@ +/* 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. + Hacked by Michael Tiemann (tiemann@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. */ + + +/* Reference to the contents of an offset + (a value whose type is an OFFSET_TYPE). + Operand 0 is the object within which the offset is taken. + Operand 1 is the offset. The language independent OFFSET_REF + just won't work for us. */ +DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2) + +/* For NEW_EXPR, operand 0 is the placement list. + Operand 1 is the new-declarator. + Operand 2 is the initializer. */ +DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 3) +DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", 'e', 3) + +/* For DELETE_EXPR, operand 0 is the store to be destroyed. + Operand 1 is the value to pass to the destroying function + saying whether the store should be deallocated as well. */ +DEFTREECODE (DELETE_EXPR, "dl_expr", 'e', 2) +DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", 'e', 2) + +/* Value is reference to particular overloaded class method. + Operand 0 is the class name (an IDENTIFIER_NODE); + operand 1 is the field (also an IDENTIFIER_NODE). + The COMPLEXITY field holds the class level (usually 0). */ +DEFTREECODE (SCOPE_REF, "scope_ref", 'r', 2) + +/* When composing an object with a member, this is the result. + Operand 0 is the object. Operand 1 is the member (usually + a dereferenced pointer to member). */ +DEFTREECODE (MEMBER_REF, "member_ref", 'r', 2) + +/* Type conversion operator in C++. TREE_TYPE is type that this + operator converts to. Operand is expression to be converted. */ +DEFTREECODE (TYPE_EXPR, "type_expr", 'e', 1) + +/* For AGGR_INIT_EXPR, operand 0 is function which performs initialization, + operand 1 is argument list to initialization function, + and operand 2 is the slot which was allocated for this expression. */ +DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", 'e', 3) + +/* A throw expression. operand 0 is the expression, if there was one, + else it is NULL_TREE. */ +DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1) + +/* Initialization of a vector, used in build_new. Operand 0 is the target + of the initialization, operand 1 is the initializer, and operand 2 is + the number of elements. */ +DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", 'e', 3) + +/* Template definition. The following fields have the specified uses, + although there are other macros in cp-tree.h that should be used for + accessing this data. + DECL_ARGUMENTS template parm vector + DECL_TEMPLATE_INFO template text &c + DECL_VINDEX list of instantiations already produced; + only done for functions so far + For class template: + DECL_INITIAL associated templates (methods &c) + DECL_RESULT null + For non-class templates: + TREE_TYPE type of object to be constructed + DECL_RESULT decl for object to be created + (e.g., FUNCTION_DECL with tmpl parms used) + */ +DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0) + +/* Index into a template parameter list. The TEMPLATE_PARM_IDX gives + the index (from 0) of the parameter, while the TEMPLATE_PARM_LEVEL + gives the level (from 1) of the parameter. + + Here's an example: + + template // Index 0, Level 1. + struct S + { + template // Index 1, Level 2. + void f(); + }; + + The DESCENDANTS will be a chain of TEMPLATE_PARM_INDEXs descended + from this one. The first descendant will have the same IDX, but + its LEVEL will be one less. The TREE_CHAIN field is used to chain + together the descendants. The TEMPLATE_PARM_DECL is the + declaration of this parameter, either a TYPE_DECL or CONST_DECL. + The TEMPLATE_PARM_ORIG_LEVEL is the LEVEL of the most distant + parent, i.e., the LEVEL that the parameter originally had when it + was declared. For example, if we instantiate S, we will have: + + struct S + { + template // Index 1, Level 1, Orig Level 2 + void f(); + }; + + The LEVEL is the level of the parameter when we are worrying about + the types of things; the ORIG_LEVEL is the level when we are + worrying about instantiating things. */ +DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", 'x', + /* The addition of (sizeof(char*) - 1) in the next + expression is to ensure against the case where + sizeof(char*) does not evenly divide + sizeof(HOST_WIDE_INT). */ + 2 + ((3 * sizeof (HOST_WIDE_INT) + sizeof(char*) - 1) + / sizeof (char*))) + +/* Index into a template parameter list. This parameter must be a type. + The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */ +DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0) + +/* Index into a template parameter list. This parameter must be a type. + If it is used in signature of a template, TEMPLATE_INFO is NULL_TREE. + Otherwise it is used to declare a type like TT. + 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'. */ +DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0) + +/* A thunk is a stub function. + + Thunks are used to implement multiple inheritance: + At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree) + from the this pointer, and then jumps to DECL_INITIAL + (which is an ADDR_EXPR whose operand is a FUNCTION_DECL). + + Other kinds of thunks may be defined later. */ +DEFTREECODE (THUNK_DECL, "thunk_decl", 'd', 0) + +/* A using declaration. DECL_INITIAL contains the specified scope. + This is not an alias, but is later expanded into multiple aliases. */ +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. 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. */ +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. */ +DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2) + +/* A list-like node for chaining overloading candidates. TREE_TYPE is + the original name, and the parameter is the FUNCTION_DECL. */ +DEFTREECODE (OVERLOAD, "overload", 'x', 1) + +/* A generic wrapper for something not tree that we want to include in + tree structure. */ +DEFTREECODE (WRAPPER, "wrapper", 'x', 1) + +/* A node to remember a source position. */ +DEFTREECODE (SRCLOC, "srcloc", 'x', 2) + +/* 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) +DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", '1', 1) +DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", '1', 1) +DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", '1', 1) +DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", '1', 1) +DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1) +DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1) +DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2) +DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1) + +DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1) +DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1) +DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 3) +DEFTREECODE (IF_STMT, "if_stmt", 'e', 3) +DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4) +DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2) +DEFTREECODE (DO_STMT, "do_stmt", 'e', 2) +DEFTREECODE (RETURN_STMT, "return_stmt", 'e', 1) +DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0) +DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0) +DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2) +DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1) +DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5) + +DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2) +DEFTREECODE (CASE_LABEL, "case_label", 'e', 2) +DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) +DEFTREECODE (TRY_BLOCK, "try_stmt", 'e', 2) +DEFTREECODE (HANDLER, "catch_stmt", 'e', 2) + +DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0) + +/* And some codes for expressing conversions for overload resolution. */ + +DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1) +DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1) +DEFTREECODE (QUAL_CONV, "qual_conv", 'e', 1) +DEFTREECODE (STD_CONV, "std_conv", 'e', 1) +DEFTREECODE (PTR_CONV, "ptr_conv", 'e', 1) +DEFTREECODE (PMEM_CONV, "pmem_conv", 'e', 1) +DEFTREECODE (BASE_CONV, "base_conv", 'e', 1) +DEFTREECODE (REF_BIND, "ref_bind", 'e', 1) +DEFTREECODE (USER_CONV, "user_conv", 'e', 2) +DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1) +DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1) + +/* +Local variables: +mode:c +End: +*/ diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h index fe9855d..7572921 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, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 93, 94, 95, 1996 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -22,24 +22,66 @@ Boston, MA 02111-1307, USA. */ #ifndef _CP_TREE_H #define _CP_TREE_H -/* Borrow everything that is C from c-tree.h, - but do so by copy, not by inclusion, since c-tree.h defines - lang_identifier. */ - -#ifndef STDIO_PROTO -#ifdef BUFSIZ -#define STDIO_PROTO(ARGS) PROTO(ARGS) -#else -#define STDIO_PROTO(ARGS) () -#endif -#endif +#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. + 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. + 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. + 2: IDENTIFIER_OPNAME_P. + 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. + (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. + 6: Not used. + + Usage of TYPE_LANG_FLAG_?: + 0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE). + 1: TYPE_HAS_CONSTRUCTOR. + 2: TYPE_HAS_DESTRUCTOR. + 3: TYPE_FOR_JAVA. + 4: TYPE_NEEDS_DESTRUCTOR. + 5: IS_AGGR_TYPE. + 6: TYPE_BUILT_IN. + + Usage of DECL_LANG_FLAG_?: + 0: DECL_ERROR_REPORTED (in VAR_DECL). + 1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_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). +*/ /* Language-dependent contents of an identifier. */ struct lang_identifier { struct tree_identifier ignore; - tree global_value, local_value; + tree namespace_bindings, local_value; tree class_value; tree class_template_info; struct lang_id2 *x; @@ -51,14 +93,96 @@ struct lang_id2 tree type_desc, as_list, error_locus; }; +typedef struct +{ + tree t; + int new_type_flag; +} flagged_type_tree; + +typedef struct +{ + char common[sizeof (struct tree_common)]; + struct rtx_def *rtl; /* Unused, but required to match up with what + the middle-end expects. */ + HOST_WIDE_INT index; + HOST_WIDE_INT level; + HOST_WIDE_INT orig_level; + 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) +/* 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) \ + set_namespace_binding (NODE, global_namespace, VAL) +#define IDENTIFIER_NAMESPACE_VALUE(NODE) \ + namespace_binding (NODE, current_namespace) +#define SET_IDENTIFIER_NAMESPACE_VALUE(NODE, VAL) \ + set_namespace_binding (NODE, current_namespace, VAL) + +struct tree_binding +{ + char common[sizeof (struct tree_common)]; + tree scope; + tree value; +}; + +/* The overloaded FUNCTION_DECL. */ +#define OVL_FUNCTION(NODE) (((struct tree_overload*)NODE)->function) +#define OVL_CHAIN(NODE) TREE_CHAIN(NODE) +/* Polymorphic access to FUNCTION and CHAIN. */ +#define OVL_CURRENT(NODE) \ + ((TREE_CODE(NODE)==OVERLOAD) ? OVL_FUNCTION(NODE) : NODE) +#define OVL_NEXT(NODE) \ + ((TREE_CODE(NODE)==OVERLOAD) ? TREE_CHAIN(NODE) : NULL_TREE) +/* If set, this was imported in a using declaration. + This is not to confuse with being used somewhere, which + is not important for this node. */ +#define OVL_USED(NODE) TREE_USED(NODE) + +struct tree_overload +{ + char common[sizeof (struct tree_common)]; + tree function; +}; + +#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr) +#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i) + +struct tree_wrapper +{ + char common[sizeof (struct tree_common)]; + union { + void *ptr; + int i; + } u; +}; + +#define SRCLOC_FILE(NODE) (((struct tree_srcloc*)NODE)->filename) +#define SRCLOC_LINE(NODE) (((struct tree_srcloc*)NODE)->linenum) +struct tree_srcloc +{ + char common[sizeof (struct tree_common)]; + char *filename; + int linenum; +}; + /* To identify to the debug emitters if it should pay attention to the flag `-Wtemplate-debugging'. */ #define HAVE_TEMPLATES 1 /* Macros for access to language-specific slots in an identifier. */ -#define IDENTIFIER_GLOBAL_VALUE(NODE) \ - (((struct lang_identifier *)(NODE))->global_value) +#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) \ @@ -66,9 +190,14 @@ struct lang_id2 #define IDENTIFIER_TEMPLATE(NODE) \ (((struct lang_identifier *)(NODE))->class_template_info) -#define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (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 + be found through lookup. */ +#define IDENTIFIER_TYPE_VALUE(NODE) (identifier_type_value(NODE)) +#define REAL_IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE)) #define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE) -#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (TREE_TYPE (NODE) ? 1 : 0) +#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (IDENTIFIER_TYPE_VALUE (NODE) ? 1 : 0) #define LANG_ID_FIELD(NAME,NODE) \ (((struct lang_identifier *)(NODE))->x \ @@ -139,15 +268,34 @@ extern tree unsigned_type_node; extern tree string_type_node, char_array_type_node, int_array_type_node; extern tree wchar_array_type_node; extern tree wchar_type_node, signed_wchar_type_node, unsigned_wchar_type_node; + +extern tree complex_integer_type_node; +extern tree complex_float_type_node; +extern tree complex_double_type_node; +extern tree complex_long_double_type_node; + 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; +extern tree intTI_type_node, unsigned_intTI_type_node; + +extern tree java_byte_type_node; +extern tree java_short_type_node; +extern tree java_int_type_node; +extern tree java_long_type_node; +extern tree java_float_type_node; +extern tree java_double_type_node; +extern tree java_char_type_node; +extern tree java_boolean_type_node; extern int current_function_returns_value; extern int current_function_returns_null; extern tree current_function_return_value; +extern tree current_namespace; +extern tree global_namespace; + extern tree ridpointers[]; extern tree ansi_opname[]; extern tree ansi_assopname[]; @@ -181,6 +329,10 @@ extern int flag_no_ident; extern int warn_implicit; +/* Nonzero means warn about usage of long long when `-pedantic'. */ + +extern int warn_long_long; + /* Nonzero means warn when all ctors or dtors are private, and the class has no friends. */ @@ -202,10 +354,6 @@ extern int warn_write_strings; extern int warn_pointer_arith; -/* Nonzero means warn for all old-style non-prototype function decls. */ - -extern int warn_strict_prototypes; - /* Nonzero means warn about suggesting putting in ()'s. */ extern int warn_parentheses; @@ -219,6 +367,10 @@ extern int warn_redundant_decls; extern int warn_missing_braces; +/* Warn about comparison of signed and unsigned values. */ + +extern int warn_sign_compare; + /* Warn about a subscript that has type char. */ extern int warn_char_subscripts; @@ -228,25 +380,36 @@ extern int warn_char_subscripts; extern int warn_cast_qual; -/* Warn about traditional constructs whose meanings changed in ANSI C. */ - -extern int warn_traditional; - -/* Warn about *printf or *scanf format/argument anomalies. */ +/* Warn about *printf or *scanf format/argument anomalies. */ extern int warn_format; /* Nonzero means warn about non virtual destructors in classes that have - virtual functions. */ + virtual functions. */ extern int warn_nonvdtor; +/* Non-zero means warn when we convert a pointer to member function + into a pointer to (void or function). */ + +extern int warn_pmf2ptr; + +/* Nonzero means warn about violation of some Effective C++ style rules. */ + +extern int warn_ecpp; + +/* Nonzero means warn where overload resolution chooses a promotion from + unsigned to signed over a conversion to an unsigned of the same size. */ + +extern int warn_sign_promo; + /* Non-zero means warn when a function is declared extern and later inline. */ + extern int warn_extern_inline; -/* Nonzero means do some things the same way PCC does. */ +/* Non-zero means warn when an old-style cast is used. */ -extern int flag_traditional; +extern int warn_old_style_cast; /* Nonzero means to treat bitfields as unsigned unless they say `signed'. */ @@ -264,9 +427,9 @@ extern int flag_signed_bitfields; extern int write_virtuals; -/* True for more efficient but incompatible (not not fully tested) +/* True for more efficient but incompatible (not fully tested) vtable implementation (using thunks). - 0 is old behavior; 1 is new behavior. */ + 0 is old behavior; 1 is new behavior. */ extern int flag_vtable_thunks; /* INTERFACE_ONLY nonzero means that we are in an "interface" @@ -285,11 +448,6 @@ extern int flag_elide_constructors; extern int flag_ansi; -/* Nonzero means recognize and handle ansi-style exception handling - constructs. */ - -extern int flag_handle_exceptions; - /* Nonzero means recognize and handle signature language constructs. */ extern int flag_handle_signatures; @@ -299,24 +457,32 @@ extern int flag_handle_signatures; extern int flag_default_inline; -/* Nonzero means emit cadillac protocol. */ +/* The name-mangling scheme to use. Versions of gcc before 2.8 use + version 0. */ +extern int name_mangling_version; + +/* Nonzero means that guiding declarations are allowed. */ +extern int flag_guiding_decls; + +/* Nonzero if squashed mangling is to be performed. + This uses the B and K codes to reference previously seen class types + and class qualifiers. */ +extern int flag_do_squangling; -extern int flag_cadillac; +/* Nonzero if we want to issue diagnostics that the standard says are not + required. */ +extern int flag_optional_diags; /* C++ language-specific tree codes. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, enum cplus_tree_code { __DUMMY = LAST_AND_UNUSED_TREE_CODE, -#include "tree.def" +#include "cp-tree.def" LAST_CPLUS_TREE_CODE }; #undef DEFTREECODE -/* Override OFFSET_REFs from the back-end, as we want our very own. */ -/* Allow complex pointer to members to work correctly. */ -#define OFFSET_REF CP_OFFSET_REF - -enum languages { lang_c, lang_cplusplus }; +enum languages { lang_c, lang_cplusplus, lang_java }; /* Macros to make error reporting functions' lives easier. */ #define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE))) @@ -327,27 +493,28 @@ enum languages { lang_c, lang_cplusplus }; #define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) /* The _DECL for this _TYPE. */ -#define TYPE_MAIN_DECL(NODE) (TYPE_NAME (NODE)) +#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE))) #define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t)) -#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE || t == UNINSTANTIATED_P_TYPE) +#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) \ && IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2)) -#define IS_OVERLOAD_TYPE_CODE(t) (IS_AGGR_TYPE_CODE (t) || t == ENUMERAL_TYPE) -#define IS_OVERLOAD_TYPE(t) (IS_OVERLOAD_TYPE_CODE (TREE_CODE (t))) +#define IS_OVERLOAD_TYPE(t) \ + (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE) /* In a *_TYPE, nonzero means a built-in type. */ #define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6(NODE) -/* Macros which might want to be replaced by function calls. */ +/* True if this a "Java" type, defined in 'extern "Java"'. */ +#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3(NODE) #define DELTA_FROM_VTABLE_ENTRY(ENTRY) \ (!flag_vtable_thunks ? \ TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \ : TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? integer_zero_node \ : build_int_2 (THUNK_DELTA (TREE_OPERAND ((ENTRY), 0)), 0)) -#if 1 + /* Virtual function addresses can be gotten from a virtual function table entry using this macro. */ #define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \ @@ -363,15 +530,6 @@ enum languages { lang_c, lang_cplusplus }; && IS_AGGR_TYPE (TREE_TYPE (NODE))) \ || IS_AGGR_TYPE (NODE)) -#else -#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) (fnaddr_from_vtable_entry (ENTRY)) -#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \ - (set_fnaddr_from_vtable_entry (ENTRY, VALUE)) -/* #define TYPE_NAME_STRING(NODE) (type_name_string (NODE)) */ -#define FUNCTION_ARG_CHAIN(NODE) (function_arg_chain (NODE)) -#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) (promotes_to_aggr_type (NODE, CODE)) -/* #define IS_AGGR_TYPE_2(TYPE1, TYPE2) (is_aggr_type_2 (TYPE1, TYPE2)) */ -#endif /* Nonzero iff TYPE is uniquely derived from PARENT. Under MI, PARENT can be an ambiguous base class of TYPE, and this macro will be false. */ #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0) @@ -389,57 +547,48 @@ struct lang_type struct { unsigned has_type_conversion : 1; - unsigned has_int_conversion : 1; - unsigned has_float_conversion : 1; unsigned has_init_ref : 1; - unsigned gets_init_aggr : 1; unsigned has_assignment : 1; unsigned has_default_ctor : 1; unsigned uses_multiple_inheritance : 1; - - unsigned has_nonpublic_ctor : 2; - unsigned has_nonpublic_assign_ref : 2; unsigned const_needs_init : 1; unsigned ref_needs_init : 1; unsigned has_const_assign_ref : 1; - unsigned vtable_needs_writing : 1; + unsigned has_nonpublic_ctor : 2; + unsigned has_nonpublic_assign_ref : 2; + unsigned vtable_needs_writing : 1; unsigned has_assign_ref : 1; unsigned gets_new : 2; + unsigned gets_delete : 2; 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 vec_delete_takes_size : 1; unsigned declared_class : 1; unsigned being_defined : 1; unsigned redefined : 1; - - unsigned no_globalize : 1; unsigned marked : 1; unsigned marked2 : 1; unsigned marked3 : 1; + unsigned marked4 : 1; unsigned marked5 : 1; unsigned marked6 : 1; - - unsigned use_template : 2; unsigned debug_requested : 1; - unsigned has_method_call_overloaded : 1; - unsigned private_attr : 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_default_implementation : 1; - unsigned grokking_typedef : 1; unsigned has_opaque_typedecls : 1; unsigned sigtable_has_been_generated : 1; unsigned was_anonymous : 1; @@ -455,39 +604,30 @@ struct lang_type /* 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 : 19; - - unsigned n_vancestors : 16; + unsigned dummy : 11; } 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 *vbinfo[2]; union tree_node *baselink_vec; union tree_node *vfields; union tree_node *vbases; - union tree_node *vbase_size; union tree_node *tags; char *memoized_table_entry; - char *search_slot; - -#ifdef ONLY_INT_FIELDS - unsigned int mode : 8; -#else - enum machine_mode mode : 8; -#endif + union tree_node *search_slot; - unsigned char size_unit; unsigned char align; - unsigned char sep_unit; + /* Room for another three unsigned chars. */ - union tree_node *sep; union tree_node *size; union tree_node *base_init_list; @@ -497,7 +637,9 @@ struct lang_type union tree_node *binfo_as_list; union tree_node *friend_classes; +#ifdef MI_MATRIX char *mi_matrix; +#endif union tree_node *rtti; @@ -507,6 +649,8 @@ struct lang_type union tree_node *signature_pointer_to; union tree_node *signature_reference_to; + union tree_node *template_info; + int linenum; }; @@ -549,21 +693,10 @@ struct lang_type /* 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 for a _CLASSTYPE node which we know to be private. */ -#define TYPE_PRIVATE_P(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.private_attr) - /* 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) -/* Nonzero means that this _CLASSTYPE node can convert itself to an - INTEGER_TYPE. */ -#define TYPE_HAS_INT_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_int_conversion) - -/* Nonzero means that this _CLASSTYPE node can convert itself to an - REAL_TYPE. */ -#define TYPE_HAS_REAL_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_float_conversion) - /* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */ #define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assign_ref) #define TYPE_HAS_CONST_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_assign_ref) @@ -572,11 +705,6 @@ struct lang_type #define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_init_ref) #define TYPE_HAS_CONST_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_init_ref) -/* Nonzero means that this _CLASSTYPE node has an X(X ...) constructor. - Note that there must be other arguments, or this constructor is flagged - as being erroneous. */ -#define TYPE_GETS_INIT_AGGR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_init_aggr) - /* Nonzero means that this type is being defined. I.e., the left brace starting the definition of this type has been seen. */ #define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.being_defined) @@ -584,10 +712,6 @@ struct lang_type convenient, don't reprocess any methods that appear in its redefinition. */ #define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.redefined) -/* Nonzero means that this _CLASSTYPE node overloads the method call - operator. In this case, all method calls go through `operator->()(...). */ -#define TYPE_OVERLOADS_METHOD_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_method_call_overloaded) - /* Nonzero means that this type is a signature. */ # define IS_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)?TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature:0) # define SET_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature=1) @@ -599,12 +723,6 @@ struct lang_type /* Nonzero means that this type is a signature reference type. */ # define IS_SIGNATURE_REFERENCE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature_reference) -/* Nonzero means that this signature type has a default implementation. */ -# define HAS_DEFAULT_IMPLEMENTATION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_implementation) - -/* Nonzero means that grokdeclarator works on a signature-local typedef. */ -#define SIGNATURE_GROKKING_TYPEDEF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.grokking_typedef) - /* Nonzero means that this signature contains opaque type declarations. */ #define SIGNATURE_HAS_OPAQUE_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_opaque_typedecls) @@ -636,10 +754,6 @@ struct lang_type /* The is the VAR_DECL that contains NODE's rtti. */ #define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti) -/* List of all explicit methods (chained using DECL_NEXT_METHOD), - in order they were parsed. */ -#define CLASSTYPE_METHODS(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods) - /* Nonzero means that this _CLASSTYPE node overloads operator(). */ #define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded) @@ -660,14 +774,14 @@ struct lang_type #define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE)) /* List of lists of member functions defined in this class. */ -#define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE) +#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods) /* The first type conversion operator in the class (the others can be searched with TREE_CHAIN), or the first non-constructor function if there are no type conversion operators. */ #define CLASSTYPE_FIRST_CONVERSION(NODE) \ - TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 1 \ - ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) \ + TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 2 \ + ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \ : NULL_TREE; /* Pointer from any member function to the head of the list of @@ -695,13 +809,17 @@ struct lang_type #define SET_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 1) #define CLEAR_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 0) +/* 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 + of the type; the TREE_VALUE is the type itself. This list includes + nested member class templates. */ #define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags) /* If this class has any bases, this is the number of the base class from which our VFIELD is based, -1 otherwise. If this class has no base classes, this is not used. In D : B1, B2, PARENT would be 0, if D's vtable came from B1, - 1, if D's vtable came from B2. */ + 1, if D's vtable came from B2. */ #define CLASSTYPE_VFIELD_PARENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfield_parent) /* Remove when done merging. */ @@ -725,7 +843,7 @@ struct lang_type 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)->type_flags.n_vancestors) +#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. */ @@ -740,20 +858,11 @@ struct lang_type it can mean almost anything. */ #define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry) -/* This is the total size of the baseclasses defined for this type. - Needed because it is desirable to layout such information - before beginning to process the class itself, and we - don't want to compute it second time when actually laying - out the type for real. */ +/* 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_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit) -#define CLASSTYPE_MODE(NODE) (TYPE_LANG_SPECIFIC(NODE)->mode) #define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align) -/* This is the space needed for virtual base classes. NULL if - there are no virtual basetypes. */ -#define CLASSTYPE_VBASE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbase_size) - /* 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, @@ -807,17 +916,19 @@ struct lang_type /* 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. */ +/* A list of class types with 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 /* 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) -/* whether this can be globalized. */ -#define CLASSTYPE_NO_GLOBALIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.no_globalize) /* Nonzero if this class has const members which have no specified initialization. */ #define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.const_needs_init) @@ -838,24 +949,20 @@ struct lang_type /* Nonzero if a _DECL node requires us to output debug info for this class. */ #define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested) - -#define TYPE_INCOMPLETE(NODE) \ - (TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM) /* Additional macros for inheritance information. */ -#define CLASSTYPE_VBINFO(NODE,VIA_PUBLIC) \ - (TYPE_LANG_SPECIFIC (NODE)->vbinfo[VIA_PUBLIC]) - /* When following an binfo-specific chain, this is the cumulative via-public flag. */ #define BINFO_VIA_PUBLIC(NODE) TREE_LANG_FLAG_5 (NODE) +#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 /* Nonzero means marked by DFS or BFS search, including searches by `get_binfo' and `get_base_distance'. */ @@ -923,8 +1030,8 @@ struct lang_type this type can raise. */ #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE) -/* The binding level associated with the namespace. */ -#define NAMESPACE_LEVEL(NODE) ((NODE)->decl.arguments) +/* The binding level associated with the namespace. */ +#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level) struct lang_decl_flags { @@ -951,38 +1058,48 @@ struct lang_decl_flags unsigned saved_inline : 1; unsigned use_template : 2; - unsigned c_static : 1; unsigned nonconverting : 1; unsigned declared_inline : 1; unsigned not_really_extern : 1; - unsigned dummy : 4; + unsigned comdat : 1; + unsigned needs_final_overrider : 1; + unsigned dummy : 3; tree access; tree context; tree memfunc_pointer_to; + tree template_info; + struct binding_level *level; }; struct lang_decl { struct lang_decl_flags decl_flags; - struct template_info *template_info; tree main_decl_variant; struct pending_inline *pending_inline_info; - tree next_method; - tree chain; }; /* Non-zero if NODE is a _DECL with TREE_READONLY set. */ #define TREE_READONLY_DECL_P(NODE) \ (TREE_READONLY (NODE) && TREE_CODE_CLASS (TREE_CODE (NODE)) == 'd') +/* Non-zero iff DECL is memory-based. The DECL_RTL of + certain const variables might be a CONST_INT, or a REG + in some cases. We cannot use `memory_operand' as a test + here because on most RISC machines, a variable's address + is not, by itself, a legitimate address. */ +#define DECL_IN_MEMORY_P(NODE) \ + (DECL_RTL (NODE) != NULL_RTX && GET_CODE (DECL_RTL (NODE)) == MEM) + /* For FUNCTION_DECLs: return the language in which this decl was declared. */ #define DECL_LANGUAGE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.language) /* 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))) + /* 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) @@ -997,7 +1114,7 @@ struct lang_decl /* 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_decl' + 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) @@ -1023,10 +1140,15 @@ struct lang_decl (TREE_CODE (NODE) == VAR_DECL || TREE_CODE (NODE) == TYPE_DECL \ || TREE_CODE (NODE) == CONST_DECL) +/* Nonzero for FUNCTION_DECL means that this decl is a non-static + member function. */ +#define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) \ + (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE) + /* Nonzero for FUNCTION_DECL means that this decl is a member function (static or non-static). */ #define DECL_FUNCTION_MEMBER_P(NODE) \ - (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE || DECL_STATIC_FUNCTION_P (NODE)) + (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE)) /* Nonzero for FUNCTION_DECL means that this member function has `this' as const X *const. */ @@ -1048,31 +1170,57 @@ struct lang_decl exists as part of an abstract class's interface. */ #define DECL_ABSTRACT_VIRTUAL_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.abstract_virtual) +/* Nonzero for FUNCTION_DECL means that this member function + must be overridden by derived classes. */ +#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.needs_final_overrider) + /* Nonzero if allocated on permanent_obstack. */ #define LANG_DECL_PERMANENT(LANGDECL) ((LANGDECL)->decl_flags.permanent_attr) /* The _TYPE context in which this _DECL appears. This field holds the class where a virtual function instance is actually defined, and the - lexical scope of a friend function defined in a class body. */ + lexical scope of a friend function defined in a class body. */ #define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context) #define DECL_REAL_CONTEXT(NODE) \ ((TREE_CODE (NODE) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (NODE)) \ - ? DECL_CLASS_CONTEXT (NODE) : DECL_CONTEXT (NODE)) - -/* For a FUNCTION_DECL: the chain through which the next method - in the method chain is found. We now use TREE_CHAIN to - link into the FIELD_DECL chain. */ -#if 1 -#define DECL_CHAIN(NODE) (DECL_LANG_SPECIFIC(NODE)->chain) -#else -#define DECL_CHAIN(NODE) (TREE_CHAIN (NODE)) -#endif - -/* Next method in CLASSTYPE_METHODS list. */ -#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method) + ? DECL_CLASS_CONTEXT (NODE) : CP_DECL_CONTEXT (NODE)) + +/* NULL_TREE in DECL_CONTEXT represents the global namespace. */ +#define CP_DECL_CONTEXT(NODE) \ + (DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace) +#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE)) + +/* 1 iff NODE has namespace scope, including the global namespace. */ +#define DECL_NAMESPACE_SCOPE_P(NODE) \ + (DECL_CONTEXT (NODE) == NULL_TREE \ + || TREE_CODE (DECL_CONTEXT (NODE)) == NAMESPACE_DECL) + +/* 1 iff NODE is a class member. */ +#define DECL_CLASS_SCOPE_P(NODE) \ + (DECL_CONTEXT (NODE) \ + && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (NODE))) == 't') + +/* 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. */ +#define DECL_NAMESPACE_USING(NODE) DECL_VINDEX(NODE) + +/* In a NAMESPACE_DECL, the DECL_INITIAL is used to record all users + of a namespace, to record the transitive closure of using namespace. */ +#define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NODE) + +/* In a NAMESPACE_DECL, points to the original namespace if this is + a namespace alias. */ +#define DECL_NAMESPACE_ALIAS(NODE) DECL_ABSTRACT_ORIGIN (NODE) +#define ORIGINAL_NAMESPACE(NODE) \ + (DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE)) + +/* In a TREE_LIST concatenating using directives, indicate indirekt + directives */ +#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0) /* In a VAR_DECL for a variable declared in a for statement, - this is the shadowed variable. */ + this is the shadowed (local) variable. */ #define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE) /* Points back to the decl which caused this lang_decl to be allocated. */ @@ -1083,7 +1231,7 @@ struct lang_decl squirreled away. */ #define DECL_PENDING_INLINE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->pending_inline_info) -/* True if on the saved_inlines (see decl2.c) list. */ +/* True if on the saved_inlines (see decl2.c) list. */ #define DECL_SAVED_INLINE(DECL) \ (DECL_LANG_SPECIFIC(DECL)->decl_flags.saved_inline) @@ -1096,31 +1244,71 @@ struct lang_decl which this signature member function pointer was created. */ #define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to) -/* For a TEMPLATE_DECL: template-specific information. */ -#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info) - -/* Nonzero in INT_CST means that this int is negative by dint of +/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */ +#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info) +#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info) +#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) +#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE)) +#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 INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE) + +#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE) + +#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE) +#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE) +#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE) +#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE) +#define DELETE_EXPR_USE_VEC(NODE) TREE_LANG_FLAG_1 (NODE) +#define LOOKUP_EXPR_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE) + +/* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a + TEMPLATE_DECL. This macro determines whether or not a given class + type is really a template type, as opposed to an instantiation or + specialization of one. */ +#define CLASSTYPE_IS_TEMPLATE(NODE) \ + (CLASSTYPE_TEMPLATE_INFO (NODE) \ + && !CLASSTYPE_USE_TEMPLATE (NODE) \ + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))) + +#define TYPENAME_TYPE_FULLNAME(NODE) CLASSTYPE_SIZE (NODE) + +/* Nonzero in INTEGER_CST means that this int is negative by dint of using a twos-complement negated operand. */ #define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE)) +#if 0 /* UNUSED */ /* Nonzero in any kind of _EXPR or _REF node means that it is a call to a storage allocation routine. If, later, alternate storage is found to hold the object, this call can be ignored. */ #define TREE_CALLS_NEW(NODE) (TREE_LANG_FLAG_1 (NODE)) +#endif /* Nonzero in any kind of _TYPE that uses multiple inheritance or virtual baseclasses. */ #define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE)) +#if 0 /* UNUSED */ /* 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)) +#endif #if 0 /* UNUSED */ /* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and should be looked up in a non-standard way. */ -#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE)) +#define DECL_OVERLOADED(NODE) (FOO) #endif /* Nonzero if this (non-TYPE)_DECL has its virtual attribute set. @@ -1134,20 +1322,10 @@ struct lang_decl one that does). */ #define TYPE_VIRTUAL_P(NODE) (TREE_LANG_FLAG_2 (NODE)) -#if 0 -/* Same, but tells if this field is private in current context. */ -#define DECL_PRIVATE(NODE) (FOO) - -/* Same, but tells if this field is private in current context. */ -#define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6 (NODE)) - -#define DECL_PUBLIC(NODE) (DECL_LANG_FLAG_7 (NODE)) -#endif - extern int flag_new_for_scope; /* This flag is true of a local VAR_DECL if it was declared in a for - statement, but we are no longer in the scope of the for. */ + statement, but we are no longer in the scope of the for. */ #define DECL_DEAD_FOR_LOCAL(NODE) DECL_LANG_FLAG_7 (NODE) /* This flag is set on a VAR_DECL that is a DECL_DEAD_FOR_LOCAL @@ -1179,11 +1357,6 @@ extern int flag_new_for_scope; These may be shadowed, and may be referenced from nested functions. */ #define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label) -/* Record whether a type or decl was written with nonconstant size. - Note that TYPE_SIZE may have simplified to a constant. */ -#define C_TYPE_VARIABLE_SIZE(type) TREE_LANG_FLAG_4 (type) -#define C_DECL_VARIABLE_SIZE(type) DECL_LANG_FLAG_8 (type) - /* Nonzero for _TYPE means that the _TYPE defines at least one constructor. */ #define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1(NODE)) @@ -1207,10 +1380,12 @@ extern int flag_new_for_scope; #define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ && CONSTRUCTOR_ELTS (NODE) == NULL_TREE) +#if 0 /* Indicates that a NON_LVALUE_EXPR came from a C++ reference. Used to generate more helpful error message in case somebody tries to take its address. */ #define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE)) +#endif /* Nonzero for _TYPE means that the _TYPE defines a destructor. */ #define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE)) @@ -1219,7 +1394,7 @@ extern int flag_new_for_scope; /* Nonzero for _TYPE node means that creating an object of this type will involve a call to a constructor. This can apply to objects of ARRAY_TYPE if the type of the elements needs a constructor. */ -#define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE)) +#define TYPE_NEEDS_CONSTRUCTING(NODE) ... defined in ../tree.h ... #endif /* Nonzero means that an object of this type can not be initialized using @@ -1250,21 +1425,41 @@ extern int flag_new_for_scope; #define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \ (TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE)) +#define TYPE_PTRMEM_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE) +#define TYPE_PTR_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE) +#define TYPE_PTROB_P(NODE) \ + (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) +#define TYPE_PTROBV_P(NODE) \ + (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE) +#define TYPE_PTRFN_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) + /* Nonzero for _TYPE node means that this type is a pointer to member - function type. */ + 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) /* 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. */ + before using this macro. */ #define TYPE_PTRMEMFUNC_FN_TYPE(NODE) (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE))))))) -/* These are use to manipulate the the canonical RECORD_TYPE from the - hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */ + +/* Returns `A' for a type like `int (A::*)(double)' */ +#define TYPE_PTRMEMFUNC_OBJECT_TYPE(NODE) \ + TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE))) + +/* These are use to manipulate the canonical RECORD_TYPE from the + hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */ #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, 0, 0), delta2_identifier, 0, 0)) -#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0)) +/* 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)) /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was specified in its declaration. */ @@ -1283,6 +1478,11 @@ extern int flag_new_for_scope; #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))) + #define UNKNOWN_TYPE LANG_TYPE /* Define fields and accessors for nodes representing declared names. */ @@ -1299,22 +1499,22 @@ extern int flag_new_for_scope; #define DECL_VPARENT(NODE) ((NODE)->decl.arguments) #endif -/* Make a slot so we can implement nested types. This slot holds - the IDENTIFIER_NODE that uniquely names the nested type. This - is for TYPE_DECLs only. */ -#define DECL_NESTED_TYPENAME(NODE) ((NODE)->decl.arguments) -#define TYPE_NESTED_NAME(NODE) (DECL_NESTED_TYPENAME (TYPE_NAME (NODE))) - #define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous) /* C++: all of these are overloaded! These apply only to TYPE_DECLs. */ + +/* The format of each node in the DECL_FRIENDLIST is as follows: + + The TREE_PURPOSE will be the name of a function, i.e., an + IDENTIFIER_NODE. The TREE_VALUE will be itself a TREE_LIST, the + list of functions with that name which are friends. The + TREE_PURPOSE of each node in this sublist will be error_mark_node, + if the function was declared a friend individually, in which case + the TREE_VALUE will be the function_decl. If, however, all + functions with a given name in a class were declared to be friends, + the TREE_PUROSE will be the class type, and the TREE_VALUE will be + NULL_TREE. */ #define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE)) -#if 0 -#define DECL_UNDEFINED_FRIENDS(NODE) ((NODE)->decl.result) -#endif -#define DECL_WAITING_FRIENDS(NODE) ((tree)(NODE)->decl.rtl) -#define SET_DECL_WAITING_FRIENDS(NODE,VALUE) \ - ((NODE)->decl.rtl=(struct rtx_def*)VALUE) /* The DECL_ACCESS is used to record under which context special access rules apply. */ @@ -1325,25 +1525,70 @@ extern int flag_new_for_scope; #define DECL_REFERENCE_SLOT(NODE) ((tree)(NODE)->decl.arguments) #define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL) -/* For local VAR_DECLs, holds index into gc-protected obstack. */ -#define DECL_GC_OFFSET(NODE) ((NODE)->decl.result) - /* Accessor macros for C++ template decl nodes. */ -#define DECL_TEMPLATE_IS_CLASS(NODE) (DECL_RESULT(NODE) == NULL_TREE) + +/* 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). */ #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_MEMBERS(NODE) DECL_SIZE(NODE) +#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE) /* For function, method, class-data templates. */ #define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE) +#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE) + +/* Nonzero for TEMPLATE_DECL nodes that represents template template + parameters */ +#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL && TREE_TYPE (NODE) \ + && TREE_CODE (TREE_TYPE (NODE)) == TEMPLATE_TEMPLATE_PARM) + +#define DECL_FUNCTION_TEMPLATE_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL \ + && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL) + +/* Nonzero for a DECL that represents a template class. */ +#define DECL_CLASS_TEMPLATE_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL \ + && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \ + && !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE)) + +/* Nonzero if NODE which declares a type. */ +#define DECL_DECLARES_TYPE_P(NODE) \ + (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE)) + +/* A `primary' template is one that has its own template header. A + member function of a class template is a template, but not primary. + A member template is primary. Friend templates are primary, too. */ + +/* Returns the primary template corresponding to these parameters. */ +#define DECL_PRIMARY_TEMPLATE(NODE) \ + (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE))) + +/* Returns non-zero if NODE is a primary template. */ +#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == NODE) + +#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \ + (TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE)))) /* Indicates whether or not (and how) a template was expanded for this FUNCTION_DECL or VAR_DECL. 0=normal declaration, e.g. int min (int, int); 1=implicit template instantiation 2=explicit template specialization, e.g. int min (int, int); - 3=explicit template instantiation, e.g. template int min (int, int); - */ + 3=explicit template instantiation, e.g. template int min (int, int); */ #define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.use_template) #define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1) @@ -1371,14 +1616,11 @@ extern int flag_new_for_scope; #define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \ (CLASSTYPE_USE_TEMPLATE(NODE) = 3) +/* This function may be a guiding decl for a template. */ +#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE) /* We know what we're doing with this decl now. */ #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) -/* This decl was declared or deduced to have internal linkage. This is - only meaningful if TREE_PUBLIC is set. */ -#define DECL_C_STATIC(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.c_static) - /* This function was declared inline. This flag controls the linkage semantics of 'inline'; whether or not the function is inlined is controlled by DECL_INLINE. */ @@ -1391,9 +1633,12 @@ extern int flag_new_for_scope; #define DECL_NOT_REALLY_EXTERN(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern) -#define DECL_PUBLIC(NODE) \ - (TREE_CODE (NODE) == FUNCTION_DECL \ - ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE)) +#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) @@ -1401,6 +1646,45 @@ extern int flag_new_for_scope; #define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE)) #define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE)) +/* An un-parsed default argument looks like an identifier. */ +#define DEFARG_NODE_CHECK(t) TREE_CHECK(t, DEFAULT_ARG) +#define DEFARG_LENGTH(NODE) (DEFARG_NODE_CHECK(NODE)->identifier.length) +#define DEFARG_POINTER(NODE) (DEFARG_NODE_CHECK(NODE)->identifier.pointer) + +#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ + define_function (NAME, TYPE, CODE, (void (*) PROTO((tree)))pushdecl, LIBNAME) + +/* These macros provide convenient access to the various _STMT nodes + created when parsing template declarations. */ +#define IF_COND(NODE) TREE_OPERAND (NODE, 0) +#define THEN_CLAUSE(NODE) TREE_OPERAND (NODE, 1) +#define ELSE_CLAUSE(NODE) TREE_OPERAND (NODE, 2) +#define WHILE_COND(NODE) TREE_OPERAND (NODE, 0) +#define WHILE_BODY(NODE) TREE_OPERAND (NODE, 1) +#define DO_COND(NODE) TREE_OPERAND (NODE, 0) +#define DO_BODY(NODE) TREE_OPERAND (NODE, 1) +#define RETURN_EXPR(NODE) TREE_OPERAND (NODE, 0) +#define EXPR_STMT_EXPR(NODE) TREE_OPERAND (NODE, 0) +#define FOR_INIT_STMT(NODE) TREE_OPERAND (NODE, 0) +#define FOR_COND(NODE) TREE_OPERAND (NODE, 1) +#define FOR_EXPR(NODE) TREE_OPERAND (NODE, 2) +#define FOR_BODY(NODE) TREE_OPERAND (NODE, 3) +#define SWITCH_COND(NODE) TREE_OPERAND (NODE, 0) +#define SWITCH_BODY(NODE) TREE_OPERAND (NODE, 1) +#define CASE_LOW(NODE) TREE_OPERAND (NODE, 0) +#define CASE_HIGH(NODE) TREE_OPERAND (NODE, 1) +#define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0) +#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0) +#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1) +#define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0) +#define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1) +#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0) +#define ASM_CV_QUAL(NODE) TREE_OPERAND (NODE, 0) +#define ASM_STRING(NODE) TREE_OPERAND (NODE, 1) +#define ASM_OUTPUTS(NODE) TREE_OPERAND (NODE, 2) +#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3) +#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4) + /* An enumeration of the kind of tags that C++ accepts. */ enum tag_types { record_type, class_type, union_type, enum_type, signature_type }; @@ -1423,6 +1707,9 @@ extern int flag_detailed_statistics; type signature of any virtual function in the base class. */ extern int warn_overloaded_virtual; +/* Nonzero means warn about use of multicharacter literals. */ +extern int warn_multichar; + /* in c-common.c */ extern void declare_function_name PROTO((void)); extern void decl_attributes PROTO((tree, tree, tree)); @@ -1433,6 +1720,7 @@ extern void check_function_format PROTO((tree, tree, tree)); 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 canonical_type_variant PROTO((tree)); extern void c_expand_expr_stmt PROTO((tree)); /* Validate the expression after `case' and apply default promotions. */ extern tree check_case_value PROTO((tree)); @@ -1443,16 +1731,23 @@ extern tree convert_and_check PROTO((tree, tree)); extern void overflow_warning PROTO((tree)); extern void unsigned_conversion_warning PROTO((tree, tree)); /* Read the rest of the current #-directive line. */ -extern char *get_directive_line STDIO_PROTO((FILE *)); +#if USE_CPPLIB +extern char *get_directive_line PROTO((void)); +#define GET_DIRECTIVE_LINE() get_directive_line () +#else +extern char *get_directive_line PROTO((FILE *)); +#define GET_DIRECTIVE_LINE() get_directive_line (finput) +#endif /* Subroutine of build_binary_op, used for comparison operations. See if the operands have both been converted from subword integer types and, if so, perhaps change them both back to their original type. */ extern tree shorten_compare PROTO((tree *, tree *, tree *, enum tree_code *)); /* Prepare expr to be an argument of a TRUTH_NOT_EXPR, - or validate its data type for an `if' or `while' statement or ?..: exp. */ + or validate its data type for an `if' or `while' statement or ?..: exp. */ extern tree truthvalue_conversion PROTO((tree)); extern tree type_for_mode PROTO((enum machine_mode, int)); extern tree type_for_size PROTO((unsigned, int)); +extern int c_get_alias_set PROTO((tree)); /* in decl{2}.c */ extern tree void_list_node; @@ -1461,7 +1756,9 @@ extern tree default_function_type; extern tree vtable_entry_type; extern tree sigtable_entry_type; extern tree __t_desc_type_node; +#if 0 extern tree __tp_desc_type_node; +#endif extern tree __access_mode_type_node; extern tree __bltn_desc_type_node, __user_desc_type_node; extern tree __class_desc_type_node, __attr_desc_type_node; @@ -1470,87 +1767,89 @@ extern tree __ptmf_desc_type_node, __ptmd_desc_type_node; extern tree type_info_type_node; extern tree class_star_type_node; extern tree this_identifier; +extern tree ctor_identifier, dtor_identifier; extern tree pfn_identifier; extern tree index_identifier; extern tree delta_identifier; extern tree delta2_identifier; extern tree pfn_or_delta2_identifier; extern tree tag_identifier; -extern tree vb_off_identifier; extern tree vt_off_identifier; /* A node that is a list (length 1) of error_mark_nodes. */ extern tree error_mark_list; -extern tree ptr_type_node, const_ptr_type_node; +extern tree ptr_type_node; extern tree class_type_node, record_type_node, union_type_node, enum_type_node; extern tree unknown_type_node; extern tree opaque_type_node, signature_type_node; /* Node for "pointer to (virtual) function". - This may be distinct from ptr_type_node so gdb can distinguish them. */ + This may be distinct from ptr_type_node so gdb can distinguish them. */ #define vfunc_ptr_type_node \ (flag_vtable_thunks ? vtable_entry_type : ptr_type_node) /* Array type `(void *)[]' */ extern tree vtbl_type_node; extern tree delta_type_node; +extern tree std_node; extern tree long_long_integer_type_node, long_long_unsigned_type_node; /* For building calls to `delete'. */ extern tree integer_two_node, integer_three_node; extern tree boolean_type_node, boolean_true_node, boolean_false_node; +extern tree null_node; + /* in pt.c */ -/* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or - PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those - parameters. */ -struct template_info { - /* Vector of template parameters, either PARM_DECLs or IDENTIFIER_NODEs. */ - tree parm_vec; - /* If non-null, a vector of bindings for the template parms. */ - tree bindings; - - /* Text of template, and length. */ - char *text; - int length; - /* Where it came from. */ - char *filename; - int lineno; - /* What kind of aggregate -- struct, class, or null. */ - tree aggr; -}; -extern int processing_template_decl, processing_template_defn; +/* These values are used for the `STRICT' parameter to type_unfication and + fn_type_unification. Their meanings are described with the + documentation for fn_type_unification. */ + +typedef enum unification_kind_t { + DEDUCE_CALL, + DEDUCE_CONV, + DEDUCE_EXACT +} unification_kind_t; + +extern tree current_template_parms; +extern HOST_WIDE_INT processing_template_decl; +extern tree last_tree; /* The template currently being instantiated, and where the instantiation was triggered. */ struct tinst_level { - tree classname; + tree decl; int line; char *file; struct tinst_level *next; }; +extern int minimal_parse_mode; + +extern void maybe_print_template_context PROTO ((void)); + /* in class.c */ extern tree current_class_name; extern tree current_class_type; +extern tree current_class_ptr; extern tree previous_class_type; +extern tree current_class_ref; +extern int current_class_depth; -extern tree current_lang_name, lang_name_cplusplus, lang_name_c; +extern tree current_lang_name; +extern tree lang_name_cplusplus, lang_name_c, lang_name_java; /* 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; -extern tree current_class_name, current_class_type, current_class_decl, C_C_D; - /* in init.c */ extern tree global_base_init_list; extern tree current_base_init_list, current_member_init_list; -extern int current_function_assigns_this; extern int current_function_just_assigned_this; extern int current_function_parms_stored; @@ -1671,6 +1970,8 @@ extern int current_function_parms_stored; #define THIS_NAME "this" #define DESTRUCTOR_NAME_FORMAT "~%s" #define FILE_FUNCTION_PREFIX_LEN 9 +#define CTOR_NAME "__ct" +#define DTOR_NAME "__dt" #define IN_CHARGE_NAME "__in_chrg" @@ -1726,23 +2027,34 @@ extern int current_function_parms_stored; #define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \ && IDENTIFIER_POINTER (ID_NODE)[1] <= '9') #endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */ + +/* Returns non-zero iff ID_NODE is an IDENTIFIER_NODE whose name is + `main'. */ +#define MAIN_NAME_P(ID_NODE) \ + (strcmp (IDENTIFIER_POINTER (ID_NODE), "main") == 0) + +/* Returns non-zero iff NODE is a declaration for the global function + `main'. */ +#define DECL_MAIN_P(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL \ + && DECL_CONTEXT (NODE) == NULL_TREE \ + && DECL_NAME (NODE) != NULL_TREE \ + && MAIN_NAME_P (DECL_NAME (NODE))) + /* Define the sets of attributes that member functions and baseclasses can have. These are sensible combinations of {public,private,protected} cross {virtual,non-virtual}. */ -enum access_type { - access_default, - access_public, - access_protected, - access_private, - access_default_virtual, - access_public_virtual, - access_private_virtual -}; - -/* in lex.c */ -extern tree current_unit_name, current_unit_language; +/* in class.c. */ +extern tree access_default_node; /* 0 */ +extern tree access_public_node; /* 1 */ +extern tree access_protected_node; /* 2 */ +extern tree access_private_node; /* 3 */ +extern tree access_default_virtual_node; /* 4 */ +extern tree access_public_virtual_node; /* 5 */ +extern tree access_protected_virtual_node; /* 6 */ +extern tree access_private_virtual_node; /* 7 */ /* Things for handling inline functions. */ @@ -1757,7 +2069,6 @@ struct pending_inline char *buf; /* pointer to character stream */ int len; /* length of stream */ - tree parm_vec, bindings; /* in case this is derived from a template */ unsigned int can_free : 1; /* free this after we're done with it? */ unsigned int deja_vu : 1; /* set iff we don't want to see it again. */ unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */ @@ -1784,10 +2095,6 @@ extern int flag_this_is_variable; extern int flag_int_enum_equivalence; -/* Nonzero means layout structures so that we can do garbage collection. */ - -extern int flag_gc; - /* Nonzero means generate 'rtti' that give run-time type information. */ extern int flag_rtti; @@ -1809,17 +2116,25 @@ extern int flag_alt_external_templates; extern int flag_implicit_templates; -/* Current end of entries in the gc obstack for stack pointer variables. */ +/* Nonzero if we want to emit defined symbols with common-like linkage as + weak symbols where possible, in order to conform to C++ semantics. + Otherwise, emit them as local symbols. */ -extern int current_function_obstack_index; +extern int flag_weak; -/* Flag saying whether we have used the obstack in this function or not. */ +/* Nonzero to enable experimental ABI changes. */ -extern int current_function_obstack_usage; +extern int flag_new_abi; -enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG }; +/* Nonzero to not ignore namespace std. */ -extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */ +extern int flag_honor_std; + +/* Nonzero if we're done parsing and into end-of-file activities. */ + +extern int at_eof; + +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 */ @@ -1837,32 +2152,56 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ LOOKUP_COMPLAIN mean complain if no suitable member function matching the arguments is found. LOOKUP_NORMAL is just a combination of these two. - LOOKUP_AGGR requires the instance to be of aggregate type. LOOKUP_NONVIRTUAL means make a direct call to the member function found LOOKUP_GLOBAL means search through the space of overloaded functions, as well as the space of member functions. LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already in the parameter list. LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried. + DIRECT_BIND means that if a temporary is created, it should be created so + that it lives as long as the current variable bindings; otherwise it + only lives until the end of the complete-expression. LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are after. Note, LOOKUP_COMPLAIN is checked and error messages printed before LOOKUP_SPECULATIVELY is checked. LOOKUP_NO_CONVERSION means that user-defined conversions are not permitted. Built-in conversions are permitted. - LOOKUP_DESTRUCTOR means explicit call to destructor. */ + LOOKUP_DESTRUCTOR means explicit call to destructor. + LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references. + + These are used in global lookup to support elaborated types and + qualifiers. + + LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces. + LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types. + LOOKUP_PREFER_BOTH means class-or-namespace-name. + LOOKUP_TEMPLATES_EXPECTED means that class templates also count + as types. */ #define LOOKUP_PROTECT (1) #define LOOKUP_COMPLAIN (2) #define LOOKUP_NORMAL (3) -#define LOOKUP_AGGR (4) +/* #define LOOKUP_UNUSED (4) */ #define LOOKUP_NONVIRTUAL (8) #define LOOKUP_GLOBAL (16) #define LOOKUP_HAS_IN_CHARGE (32) #define LOOKUP_SPECULATIVELY (64) #define LOOKUP_ONLYCONVERTING (128) -/* 256 is free */ +#define DIRECT_BIND (256) #define LOOKUP_NO_CONVERSION (512) #define LOOKUP_DESTRUCTOR (512) +#define LOOKUP_NO_TEMP_BIND (1024) +#define LOOKUP_PREFER_TYPES (2048) +#define LOOKUP_PREFER_NAMESPACES (4096) +#define LOOKUP_PREFER_BOTH (6144) +#define LOOKUP_TEMPLATES_EXPECTED (8192) + +#define LOOKUP_NAMESPACES_ONLY(f) \ + (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES)) +#define LOOKUP_TYPES_ONLY(f) \ + (!((f) & LOOKUP_PREFER_NAMESPACES) && ((f) & LOOKUP_PREFER_TYPES)) +#define LOOKUP_QUALIFIERS_ONLY(f) ((f) & LOOKUP_PREFER_BOTH) + /* These flags are used by the conversion code. CONV_IMPLICIT : Perform implicit conversions (standard and user-defined). @@ -1870,7 +2209,6 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ CONV_CONST : Perform the explicit conversions for const_cast. CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast. CONV_PRIVATE : Perform upcasts to private bases. - CONV_NONCONVERTING : Allow non-converting constructors to be used. CONV_FORCE_TEMP : Require a new temporary when converting to the same aggregate type. */ @@ -1879,7 +2217,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define CONV_CONST 4 #define CONV_REINTERPRET 8 #define CONV_PRIVATE 16 -#define CONV_NONCONVERTING 32 +/* #define CONV_NONCONVERTING 32 */ #define CONV_FORCE_TEMP 64 #define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP) #define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ @@ -1898,23 +2236,27 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define WANT_ARITH (WANT_INT | WANT_FLOAT) -/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST): - purpose = friend name (IDENTIFIER_NODE); - value = TREE_LIST of FUNCTION_DECLS; - chain, type = EMPTY; */ #define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST)) #define FRIEND_DECLS(LIST) (TREE_VALUE (LIST)) -/* These macros are for accessing the fields of TEMPLATE...PARM nodes. */ -#define TEMPLATE_TYPE_TPARMLIST(NODE) TREE_PURPOSE (TYPE_FIELDS (NODE)) -#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TREE_VALUE (TYPE_FIELDS (NODE))) -#define TEMPLATE_TYPE_SET_INFO(NODE,P,I) \ - (TYPE_FIELDS (NODE) = build_tree_list (P, build_int_2 (I, 0))) -#define TEMPLATE_CONST_TPARMLIST(NODE) (*(tree*)&TREE_INT_CST_LOW(NODE)) -#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_HIGH(NODE)) -#define TEMPLATE_CONST_SET_INFO(NODE,P,I) \ - (TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \ - TEMPLATE_CONST_IDX (NODE) = I) +/* These macros are used to access a TEMPLATE_PARM_INDEX. */ +#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index) +#define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level) +#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE)) +#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (((template_parm_index*) NODE)->orig_level) +#define TEMPLATE_PARM_DECL(NODE) (((template_parm_index*) NODE)->decl) + +/* These macros are for accessing the fields of TEMPLATE_TYPE_PARM + and TEMPLATE_TEMPLATE_PARM nodes. */ +#define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE)) +#define TEMPLATE_TYPE_IDX(NODE) \ + (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE))) +#define TEMPLATE_TYPE_LEVEL(NODE) \ + (TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE))) +#define TEMPLATE_TYPE_ORIG_LEVEL(NODE) \ + (TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE))) +#define TEMPLATE_TYPE_DECL(NODE) \ + (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE))) /* in lex.c */ /* Indexed by TREE_CODE, these tables give C-looking names to @@ -1922,163 +2264,214 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ opname_tab[(int) MINUS_EXPR] == "-". */ extern char **opname_tab, **assignop_tab; -/* in c-common.c */ -extern tree convert_and_check PROTO((tree, tree)); -extern void overflow_warning PROTO((tree)); -extern void unsigned_conversion_warning PROTO((tree, tree)); - /* in call.c */ -extern struct candidate *ansi_c_bullshit; - -extern int rank_for_overload PROTO((struct candidate *, struct candidate *)); -extern void compute_conversion_costs PROTO((tree, tree, struct candidate *, int)); +extern int check_dtor_name PROTO((tree, tree)); extern int get_arglist_len_in_bytes PROTO((tree)); + extern tree build_vfield_ref PROTO((tree, tree)); -extern tree find_scoped_type PROTO((tree, tree, tree)); extern tree resolve_scope_to_name PROTO((tree, tree)); extern tree build_scoped_method_call PROTO((tree, tree, tree, tree)); +extern tree build_addr_func PROTO((tree)); +extern tree build_call PROTO((tree, tree, tree)); extern tree build_method_call PROTO((tree, tree, tree, tree, int)); -extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int)); -extern tree build_overload_call PROTO((tree, tree, int, struct candidate *)); -extern tree build_overload_call_maybe PROTO((tree, tree, int, struct candidate *)); +extern int null_ptr_cst_p PROTO((tree)); +extern tree type_decays_to PROTO((tree)); +extern tree build_user_type_conversion PROTO((tree, tree, int)); +extern tree build_new_function_call PROTO((tree, tree)); +extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree)); +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 tree convert_arg_to_ellipsis PROTO((tree)); /* in class.c */ -extern char *dont_allow_type_definitions; -extern tree build_vbase_pointer PROTO((tree, tree)); extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); -extern tree build_vtable_entry PROTO((tree, tree)); +extern tree build_vtbl_ref PROTO((tree, tree)); extern tree build_vfn_ref PROTO((tree *, tree, tree)); 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, int)); +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 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 push_nested_class PROTO((tree, int)); extern void pop_nested_class PROTO((int)); extern void push_lang_context PROTO((tree)); extern void pop_lang_context PROTO((void)); -extern int root_lang_context_p 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 warn_hidden PROTO((tree)); /* in cvt.c */ extern tree convert_to_reference PROTO((tree, tree, int, int, tree)); extern tree convert_from_reference PROTO((tree)); -extern tree convert_to_aggr PROTO((tree, tree, char **, int)); -extern tree convert_pointer_to PROTO((tree, tree)); extern tree convert_pointer_to_real PROTO((tree, tree)); -extern tree convert_pointer_to_vbase PROTO((tree, tree)); +extern tree convert_pointer_to PROTO((tree, tree)); +extern tree ocp_convert PROTO((tree, tree, int, int)); +extern tree cp_convert PROTO((tree, tree)); extern tree convert PROTO((tree, tree)); -extern tree cp_convert PROTO((tree, tree, int, int)); extern tree convert_force PROTO((tree, tree, int)); extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int)); extern tree build_expr_type_conversion PROTO((int, tree, int)); -extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *)); extern tree type_promotes_to PROTO((tree)); +extern tree perform_qualification_conversions PROTO((tree, tree)); /* decl.c */ +/* resume_binding_level */ extern int global_bindings_p PROTO((void)); extern int toplevel_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)); -extern void declare_implicit_exception PROTO((void)); -extern int have_exceptions_p PROTO((void)); -extern void declare_uninstantiated_type_level PROTO((void)); -extern int uninstantiated_type_level_p PROTO((void)); extern void declare_pseudo_global_level PROTO((void)); extern int pseudo_global_level_p PROTO((void)); +extern void set_class_shadows PROTO((tree)); extern void pushlevel PROTO((int)); +extern void note_level_for_for PROTO((void)); extern void pushlevel_temporary PROTO((int)); extern tree poplevel PROTO((int, int, int)); +extern void resume_level PROTO((struct binding_level *)); extern void delete_block PROTO((tree)); 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)); -/* skip print_other_binding_stack and print_binding_level */ extern void print_binding_stack PROTO((void)); +extern void print_binding_level PROTO((struct binding_level *)); +extern void push_namespace PROTO((tree)); +extern void pop_namespace PROTO((void)); +extern void maybe_push_to_top_level PROTO((int)); 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 tree make_type_decl PROTO((tree, tree)); extern void pushtag PROTO((tree, tree, int)); extern tree make_anon_name PROTO((void)); extern void clear_anon_tags PROTO((void)); +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 void push_class_level_binding PROTO((tree, tree)); -extern void push_overloaded_decl_top_level PROTO((tree, int)); extern tree pushdecl_class_level PROTO((tree)); -extern tree pushdecl_nonclass_level PROTO((tree)); -extern int overloaded_globals_p PROTO((tree)); -extern tree push_overloaded_decl PROTO((tree, int)); +#if 0 +extern void pushdecl_nonclass_level PROTO((tree)); +#endif +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 tree getdecls PROTO((void)); extern tree gettags PROTO((void)); +#if 0 extern void set_current_level_tags_transparency PROTO((int)); -extern tree typedecl_for_tag PROTO((tree)); -extern tree lookup_name PROTO((tree, int)); +#endif +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 make_typename_type PROTO((tree, tree)); +extern tree lookup_name_nonclass PROTO((tree)); +extern tree lookup_function_nonclass PROTO((tree, tree)); +extern tree lookup_name PROTO((tree, int)); extern tree lookup_name_current_level PROTO((tree)); +extern tree lookup_type_current_level PROTO((tree)); +extern tree lookup_name_namespace_only PROTO((tree)); +extern void begin_only_namespace_names PROTO((void)); +extern void end_only_namespace_names PROTO((void)); +extern tree namespace_ancestor PROTO((tree, tree)); +extern int lookup_using_namespace PROTO((tree,tree,tree,tree,int)); +extern int qualified_lookup_using_namespace PROTO((tree,tree,tree,int)); +extern tree auto_function PROTO((tree, tree, enum built_in_function)); extern void init_decl_processing PROTO((void)); -/* skipped define_function */ +extern int init_type_desc PROTO((void)); +extern tree define_function + PROTO((char *, tree, enum built_in_function, + void (*) (tree), char *)); extern void shadow_tag PROTO((tree)); -extern int grok_ctor_properties PROTO((tree, tree)); extern tree groktypename PROTO((tree)); -extern tree start_decl PROTO((tree, tree, int, tree)); +extern tree start_decl PROTO((tree, tree, int, tree, tree)); +extern void start_decl_1 PROTO((tree)); extern void cp_finish_decl PROTO((tree, tree, tree, int, int)); +extern void finish_decl PROTO((tree, tree, tree)); extern void expand_static_init PROTO((tree, tree)); extern int complete_array_type PROTO((tree, tree, int)); extern tree build_ptrmemfunc_type PROTO((tree)); /* the grokdeclarator prototype is in decl.h */ 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_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, tree)); -extern int start_function PROTO((tree, tree, tree, tree, int)); -extern void store_parm_decls PROTO((void)); +extern tree grok_enum_decls PROTO((tree)); +extern int start_function PROTO((tree, tree, tree, int)); extern void expand_start_early_try_stmts PROTO((void)); -extern void store_in_parms PROTO((struct rtx_def *)); +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, tree)); +extern tree start_method PROTO((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 void pop_implicit_try_blocks PROTO((tree)); -extern void push_exception_cleanup PROTO((tree)); -extern void revert_static_member_fn PROTO((tree *, tree *, tree *)); +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)); /* in decl2.c */ -extern int lang_decode_option PROTO((char *)); +extern int check_java_method PROTO((tree, tree)); +extern int flag_assume_nonnull_objects; +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 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 tree grok_alignof PROTO((tree)); extern tree grok_array_decl PROTO((tree, tree)); extern tree delete_sanity PROTO((tree, tree, int, int)); -extern tree check_classfn PROTO((tree, tree, tree)); -extern tree grokfield PROTO((tree, tree, tree, tree, tree, tree)); +extern tree check_classfn PROTO((tree, tree)); +extern void check_member_template PROTO((tree)); +extern tree grokfield PROTO((tree, tree, tree, tree, tree)); extern tree grokbitfield PROTO((tree, tree, tree)); extern tree groktypefield PROTO((tree, tree)); extern tree grokoptypename PROTO((tree, tree)); -extern tree build_push_scope PROTO((tree, tree)); +extern int copy_assignment_arg_p PROTO((tree, int)); extern void cplus_decl_attributes PROTO((tree, tree, tree)); extern tree constructor_name_full PROTO((tree)); extern tree constructor_name PROTO((tree)); @@ -2092,232 +2485,278 @@ extern tree finish_table PROTO((tree, tree, tree, int)); extern void finish_builtin_type PROTO((tree, char *, tree *, int, tree)); extern tree coerce_new_type PROTO((tree)); extern tree coerce_delete_type PROTO((tree)); -extern void walk_vtables PROTO((void (*)(), void (*)())); -extern void walk_sigtables PROTO((void (*)(), void (*)())); +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)); -extern void warn_if_unknown_interface PROTO((tree)); -extern tree grok_x_components PROTO((tree, tree)); extern tree reparse_absdcl_as_expr PROTO((tree, tree)); extern tree reparse_absdcl_as_casts PROTO((tree, tree)); +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 lookup_name_nonclass PROTO((tree)); extern tree check_cp_case_value PROTO((tree)); -extern tree do_toplevel_using_decl PROTO((tree)); +extern void set_decl_namespace PROTO((tree, tree)); +extern tree current_decl_namespace PROTO((void)); +extern void push_decl_namespace PROTO((tree)); +extern void pop_decl_namespace PROTO((void)); +extern void do_namespace_alias PROTO((tree, tree)); +extern void do_toplevel_using_decl PROTO((tree)); +extern void do_local_using_decl PROTO((tree)); extern tree do_class_using_decl PROTO((tree)); -extern tree current_namespace_id PROTO((tree)); -extern tree get_namespace_id PROTO((void)); +extern void do_using_directive PROTO((tree)); 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)); -/* in edsel.c */ +/* 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 (); + +/* in error.c */ +extern void init_error PROTO((void)); +extern char *fndecl_as_string PROTO((tree, int)); +extern char *type_as_string PROTO((tree, int)); +extern char *type_as_string_real PROTO((tree, int, int)); +extern char *args_as_string PROTO((tree, int)); +extern char *decl_as_string PROTO((tree, int)); +extern char *expr_as_string PROTO((tree, int)); +extern char *code_as_string PROTO((enum tree_code, int)); +extern char *language_as_string PROTO((enum languages, int)); +extern char *parm_as_string PROTO((int, int)); +extern char *op_as_string PROTO((enum tree_code, int)); +extern char *assop_as_string PROTO((enum tree_code, int)); +extern char *cv_as_string PROTO((tree, int)); +extern char *lang_decl_name PROTO((tree, int)); +extern char *cp_file_of PROTO((tree)); +extern int cp_line_of PROTO((tree)); /* in except.c */ -extern tree protect_list; -extern void start_protect PROTO((void)); -extern void end_protect PROTO((tree)); -extern void end_protect_partials (); -extern void expand_exception_blocks PROTO((void)); -extern void expand_start_try_stmts PROTO((void)); -extern void expand_end_try_stmts PROTO((void)); -extern void expand_start_all_catch PROTO((void)); -extern void expand_end_all_catch PROTO((void)); -extern void start_catch_block PROTO((tree, tree)); -extern void end_catch_block PROTO((void)); -extern void expand_throw PROTO((tree)); -extern int might_have_exceptions_p PROTO((void)); -extern void emit_exception_table PROTO((void)); -extern tree build_throw PROTO((tree)); extern void init_exception_processing PROTO((void)); +extern void expand_start_catch_block PROTO((tree, tree)); +extern void expand_end_catch_block PROTO((void)); extern void expand_builtin_throw PROTO((void)); extern void expand_start_eh_spec PROTO((void)); -extern void expand_end_eh_spec PROTO((tree)); +extern void expand_exception_blocks PROTO((void)); +extern tree start_anon_func PROTO((void)); +extern void end_anon_func PROTO((void)); +extern void expand_throw PROTO((tree)); +extern tree build_throw PROTO((tree)); +extern void mark_all_runtime_matches PROTO((void)); /* in expr.c */ -/* skip cplus_expand_expr */ extern void init_cplus_expand PROTO((void)); extern void fixup_result_decl PROTO((tree, struct rtx_def *)); -extern int decl_in_memory_p PROTO((tree)); -extern tree unsave_expr_now PROTO((tree)); - -/* in gc.c */ -extern int type_needs_gc_entry PROTO((tree)); -extern int value_safe_from_gc PROTO((tree, tree)); -extern void build_static_gc_entry PROTO((tree, tree)); -extern tree protect_value_from_gc PROTO((tree, tree)); -extern tree build_headof PROTO((tree)); -extern tree build_classof PROTO((tree)); -extern tree build_t_desc PROTO((tree, int)); -extern tree build_i_desc PROTO((tree)); -extern tree build_m_desc PROTO((tree)); -extern void expand_gc_prologue_and_epilogue PROTO((void)); -extern void lang_expand_end_bindings PROTO((struct rtx_def *, struct rtx_def *)); -extern void init_gc_processing PROTO((void)); -extern tree build_typeid PROTO((tree)); -extern tree get_typeid PROTO((tree)); -extern tree build_dynamic_cast PROTO((tree, tree)); +extern int extract_init PROTO((tree, tree)); +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)); /* in init.c */ +extern void init_init_processing PROTO((void)); +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_direct_vtbls_init PROTO((tree, tree, int, int, tree)); -extern void do_member_init PROTO((tree, tree, tree)); extern void expand_member_init PROTO((tree, tree, tree)); extern void expand_aggr_init PROTO((tree, tree, int, 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)); extern tree get_type_value PROTO((tree)); extern tree build_member_call PROTO((tree, tree, tree)); extern tree build_offset_ref PROTO((tree, tree)); -extern tree get_member_function PROTO((tree *, tree, tree)); -extern tree get_member_function_from_ptrfunc PROTO((tree *, tree)); extern tree resolve_offset_ref PROTO((tree)); extern tree decl_constant_value PROTO((tree)); -extern int is_friend_type PROTO((tree, tree)); -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)); -extern void embrace_waiting_friends PROTO((tree)); -extern tree build_builtin_call PROTO((tree, tree, 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_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, tree, int)); +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 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)); +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)); -extern void init_lex PROTO((void)); +#endif extern void reinit_parse_for_function PROTO((void)); -extern int *init_parse PROTO((void)); extern void print_parse_statistics PROTO((void)); extern void extract_interface_info PROTO((void)); -extern void set_vardecl_interface_info PROTO((tree, tree)); extern void do_pending_inlines PROTO((void)); extern void process_next_inline PROTO((tree)); -/* skip restore_pending_input */ +extern struct pending_input *save_pending_input PROTO((void)); +extern void restore_pending_input PROTO((struct pending_input *)); extern void yyungetc PROTO((int, int)); extern void reinit_parse_for_method PROTO((int, tree)); -#if 0 -extern void reinit_parse_for_block PROTO((int, struct obstack *, int)); -#endif +extern void reinit_parse_for_block PROTO((int, struct obstack *)); extern tree cons_up_default_function PROTO((tree, tree, int)); extern void check_for_missing_semicolon PROTO((tree)); extern void note_got_semicolon PROTO((tree)); extern void note_list_got_semicolon PROTO((tree)); -extern int check_newline PROTO((void)); -extern void dont_see_typename PROTO((void)); +extern void do_pending_lang_change PROTO((void)); extern int identifier_type PROTO((tree)); extern void see_typename PROTO((void)); -extern tree do_identifier PROTO((tree)); +extern tree do_identifier PROTO((tree, int, tree)); +extern tree do_scoped_id PROTO((tree, int)); 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 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 copy_decl_lang_specific PROTO((tree)); extern void dump_time_statistics PROTO((void)); /* extern void compiler_error PROTO((char *, HOST_WIDE_INT, HOST_WIDE_INT)); */ -extern void compiler_error_with_decl PROTO((tree, char *)); extern void yyerror PROTO((char *)); - -/* 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 (); - -/* in error.c */ -extern void init_error PROTO((void)); -extern char *fndecl_as_string PROTO((tree, tree, int)); -extern char *type_as_string PROTO((tree, int)); -extern char *args_as_string PROTO((tree, int)); -extern char *decl_as_string PROTO((tree, int)); -extern char *expr_as_string PROTO((tree, int)); -extern char *code_as_string PROTO((enum tree_code, int)); -extern char *language_as_string PROTO((enum languages, int)); -extern char *parm_as_string PROTO((int, int)); -extern char *op_as_string PROTO((enum tree_code, int)); -extern char *cv_as_string PROTO((tree, int)); +extern void clear_inline_text_obstack PROTO((void)); +extern void maybe_snarf_defarg PROTO((void)); +extern tree snarf_defarg PROTO((void)); +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)); /* in method.c */ extern void init_method PROTO((void)); -extern tree make_anon_parm_name PROTO((void)); -extern void clear_anon_parm_name PROTO((void)); extern void do_inline_function_hair PROTO((tree, tree)); -/* skip report_type_mismatch */ extern char *build_overload_name PROTO((tree, int, int)); extern tree build_static_name PROTO((tree, tree)); -extern tree cplus_exception_name PROTO((tree)); extern tree build_decl_overload PROTO((tree, tree, int)); +extern tree build_template_decl_overload PROTO((tree, tree, tree, tree, tree, int)); extern tree build_typename_overload PROTO((tree)); -extern tree build_t_desc_overload PROTO((tree)); -extern void declare_overloaded PROTO((tree)); -#ifdef NO_AUTO_OVERLOAD -extern int is_overloaded PROTO((tree)); -#endif +extern tree build_overload_with_type PROTO((tree, tree)); +extern tree build_destructor_name PROTO((tree)); extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree)); -extern tree hack_identifier PROTO((tree, tree, int)); -extern tree build_component_type_expr PROTO((tree, tree, tree, int)); +extern tree hack_identifier PROTO((tree, tree)); +extern tree make_thunk PROTO((tree, int)); +extern void emit_thunk PROTO((tree)); +extern void synthesize_method PROTO((tree)); +extern tree get_id_2 PROTO((char *, tree)); /* in pt.c */ -extern tree tsubst PROTO ((tree, tree*, int, tree)); +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 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 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 process_template_parm PROTO((tree, tree)); extern tree end_template_parm_list PROTO((tree)); -extern void end_template_decl PROTO((tree, tree, tree, int)); -extern tree lookup_template_class PROTO((tree, tree, tree)); -extern void push_template_decls PROTO((tree, tree, int)); -extern void pop_template_decls PROTO((tree, tree, int)); +extern void end_template_decl PROTO((void)); +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_function PROTO((tree, tree)); extern int uses_template_parms PROTO((tree)); -extern void instantiate_member_templates PROTO((tree)); -extern tree instantiate_class_template PROTO((tree, int)); -extern tree instantiate_template PROTO((tree, tree *)); -extern void undo_template_name_overload PROTO((tree, int)); -extern void overload_template_name PROTO((tree, int)); -extern void end_template_instantiation PROTO((tree)); -extern void reinit_parse_for_template PROTO((int, tree, tree)); -extern int type_unification PROTO((tree, tree *, tree, tree, int *, int)); -extern int do_pending_expansions PROTO((void)); -extern void do_pending_templates PROTO((void)); +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)); struct tinst_level *tinst_for_decl PROTO((void)); -extern void do_function_instantiation PROTO((tree, tree, tree)); +extern void mark_decl_instantiated PROTO((tree, int)); +extern int more_specialized PROTO((tree, tree, tree)); +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 create_nested_upt 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 ... */ +extern void add_tree PROTO((tree)); +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 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 int processing_specialization; +extern int processing_explicit_instantiation; +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 finish_repo PROTO((void)); + +/* in rtti.c */ +extern void init_rtti_processing PROTO((void)); +extern tree get_tinfo_fn_dynamic PROTO((tree)); +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 build_dynamic_cast PROTO((tree, tree)); +extern void synthesize_tinfo_fn PROTO((tree)); /* in search.c */ -extern tree make_memoized_table_entry PROTO((tree, tree, int)); +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 enum access_type compute_access PROTO((tree, tree)); +extern tree compute_access PROTO((tree, tree)); extern tree lookup_field PROTO((tree, tree, int, int)); extern tree lookup_nested_field PROTO((tree, int)); 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 HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)())); -extern int tree_needs_constructor_p PROTO((tree, int)); -extern int tree_has_any_destructor_p PROTO((tree, int)); 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, int)); +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)); @@ -2327,7 +2766,7 @@ 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((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)); @@ -2335,100 +2774,196 @@ 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)); + +/* in semantics.c */ +extern void finish_expr_stmt PROTO((tree)); +extern tree begin_if_stmt PROTO((void)); +extern void finish_if_stmt_cond PROTO((tree, tree)); +extern tree finish_then_clause PROTO((tree)); +extern void begin_else_clause PROTO((void)); +extern void finish_else_clause PROTO((tree)); +extern void finish_if_stmt PROTO((void)); +extern tree begin_while_stmt PROTO((void)); +extern void finish_while_stmt_cond PROTO((tree, tree)); +extern void finish_while_stmt PROTO((tree)); +extern tree begin_do_stmt PROTO((void)); +extern void finish_do_body PROTO((tree)); +extern void finish_do_stmt PROTO((tree, tree)); +extern void finish_return_stmt PROTO((tree)); +extern tree begin_for_stmt PROTO((void)); +extern void finish_for_init_stmt PROTO((tree)); +extern void finish_for_cond PROTO((tree, tree)); +extern void finish_for_expr PROTO((tree, tree)); +extern void finish_for_stmt PROTO((tree, tree)); +extern void finish_break_stmt PROTO((void)); +extern void finish_continue_stmt PROTO((void)); +extern void begin_switch_stmt PROTO((void)); +extern tree finish_switch_cond PROTO((tree)); +extern void finish_switch_stmt PROTO((tree, tree)); +extern void finish_case_label PROTO((tree, tree)); +extern void finish_goto_stmt PROTO((tree)); +extern tree begin_try_block PROTO((void)); +extern void finish_try_block PROTO((tree)); +extern void finish_handler_sequence PROTO((tree)); +extern tree begin_handler PROTO((void)); +extern void finish_handler_parms PROTO((tree)); +extern void finish_handler PROTO((tree)); +extern tree begin_compound_stmt PROTO((int)); +extern tree finish_compound_stmt PROTO((int, tree)); +extern void finish_asm_stmt PROTO((tree, tree, tree, tree, tree)); +extern tree finish_parenthesized_expr PROTO((tree)); +extern tree begin_stmt_expr PROTO((void)); +extern tree finish_stmt_expr PROTO((tree, tree)); +extern tree finish_call_expr PROTO((tree, tree, int)); +extern tree finish_increment_expr PROTO((tree, enum tree_code)); +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_label_address_expr PROTO((tree)); +extern tree finish_unary_op_expr PROTO((enum tree_code, tree)); +extern tree finish_id_expr PROTO((tree)); +extern int begin_new_placement PROTO((void)); +extern tree finish_new_placement PROTO((tree, int)); +extern int begin_function_definition PROTO((tree, tree)); +extern tree begin_constructor_declarator PROTO((tree, tree)); +extern tree finish_declarator PROTO((tree, tree, tree, tree, int)); +extern void finish_translation_unit PROTO((void)); +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 void finish_default_args PROTO((void)); +extern void begin_inline_definitions PROTO((void)); +extern tree finish_member_class_template PROTO((tree, 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_constructor PROTO((tree, tree)); -extern tree build_signature_method_call PROTO((tree, tree, tree, tree)); +extern tree build_signature_method_call PROTO((tree, tree)); extern tree build_optr_ref PROTO((tree)); -extern tree build_sptr_ref PROTO((tree)); +extern void append_signature_fields PROTO((tree)); /* in spew.c */ extern void init_spew PROTO((void)); +extern int peekyylex PROTO((void)); extern int yylex PROTO((void)); extern tree arbitrate_lookup PROTO((tree, tree, tree)); /* in tree.c */ +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 tree build_cplus_new PROTO((tree, tree, int)); +extern tree build_cplus_new PROTO((tree, tree)); +extern tree get_target_expr PROTO((tree)); extern tree break_out_cleanups PROTO((tree)); extern tree break_out_calls PROTO((tree)); extern tree build_cplus_method_type PROTO((tree, tree, tree)); extern tree build_cplus_staticfn_type PROTO((tree, tree, tree)); extern tree build_cplus_array_type PROTO((tree, tree)); -extern void propagate_binfo_offsets PROTO((tree, tree)); -extern int layout_vbasetypes PROTO((tree, int)); -extern tree layout_basetypes PROTO((tree, tree)); -extern int list_hash PROTO((tree)); -extern tree list_hash_lookup PROTO((int, tree)); -extern void list_hash_add PROTO((int, tree)); -extern tree list_hash_canon PROTO((int, 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_chain PROTO((tree, tree)); extern tree hash_chainon PROTO((tree, tree)); extern tree get_decl_list PROTO((tree)); -extern tree list_hash_lookup_or_cons PROTO((tree)); extern tree make_binfo PROTO((tree, tree, tree, tree, tree)); extern tree binfo_value PROTO((tree, tree)); extern tree reverse_path PROTO((tree)); -extern tree virtual_member PROTO((tree, tree)); -extern void debug_binfo PROTO((tree)); -extern int decl_list_length PROTO((tree)); extern int count_functions PROTO((tree)); -extern tree decl_value_member PROTO((tree, tree)); extern int is_overloaded_fn PROTO((tree)); extern tree get_first_fn PROTO((tree)); +extern tree binding_init PROTO((struct tree_binding*)); +extern tree ovl_cons PROTO((tree, tree)); +extern tree scratch_ovl_cons PROTO((tree, tree)); +extern int ovl_member PROTO((tree, tree)); +extern tree build_overload PROTO((tree, tree)); extern tree fnaddr_from_vtable_entry PROTO((tree)); -extern void set_fnaddr_from_vtable_entry PROTO((tree, tree)); extern tree function_arg_chain PROTO((tree)); extern int promotes_to_aggr_type PROTO((tree, enum tree_code)); extern int is_aggr_type_2 PROTO((tree, tree)); -extern void message_2_types PROTO((void (*)(), char *, tree, tree)); -extern char *lang_printable_name PROTO((tree)); +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 void print_lang_statistics PROTO((void)); -/* skip __eprintf */ +extern void __eprintf + PROTO((const char *, const char *, unsigned, const char *)); extern tree array_type_nelts_total PROTO((tree)); extern tree array_type_nelts_top PROTO((tree)); extern tree break_out_target_exprs PROTO((tree)); -extern tree build_unsave_expr PROTO((tree)); -extern int cp_expand_decl_cleanup PROTO((tree, 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 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 void debug_binfo PROTO((tree)); +extern void push_expression_obstack PROTO((void)); +#define scratchalloc expralloc +#define scratch_tree_cons expr_tree_cons +#define build_scratch_list build_expr_list +#define make_scratch_vec make_temp_vec +#define push_scratch_obstack push_expression_obstack /* in typeck.c */ extern tree condition_conversion PROTO((tree)); extern tree target_type PROTO((tree)); extern tree require_complete_type PROTO((tree)); +extern tree complete_type PROTO((tree)); +extern tree complete_type_or_else PROTO((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, int)); +extern int compexcepttypes PROTO((tree, tree)); extern int comptypes PROTO((tree, tree, int)); extern int comp_target_types PROTO((tree, tree, int)); -extern tree common_base_types PROTO((tree, tree)); extern int compparms PROTO((tree, tree, int)); 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)); extern int self_promoting_args_p PROTO((tree)); extern tree unsigned_type PROTO((tree)); extern tree signed_type PROTO((tree)); extern tree signed_or_unsigned_type PROTO((int, tree)); +extern tree expr_sizeof PROTO((tree)); extern tree c_sizeof PROTO((tree)); extern tree c_sizeof_nowarn PROTO((tree)); extern tree c_alignof PROTO((tree)); +extern tree inline_conversion PROTO((tree)); extern tree decay_conversion PROTO((tree)); extern tree default_conversion PROTO((tree)); 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_array_ref PROTO((tree, tree)); 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)); @@ -2448,7 +2983,8 @@ extern tree build_compound_expr PROTO((tree)); extern tree build_static_cast PROTO((tree, tree)); extern tree build_reinterpret_cast PROTO((tree, tree)); extern tree build_const_cast PROTO((tree, tree)); -extern tree build_c_cast PROTO((tree, tree, int)); +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)); @@ -2456,15 +2992,16 @@ extern tree convert_for_initialization PROTO((tree, tree, tree, int, char *, tr 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 tree build_component_ref PROTO((tree, tree, tree, int)); +extern int comp_ptr_ttypes PROTO((tree, tree)); +extern int ptr_reasonably_similar PROTO((tree, tree)); extern tree build_ptrmemfunc PROTO((tree, tree, int)); /* in typeck2.c */ extern tree error_not_base_type PROTO((tree, tree)); extern tree binfo_or_else PROTO((tree, tree)); -extern void error_with_aggr_type (); /* PROTO((tree, char *, HOST_WIDE_INT)); */ extern void readonly_error PROTO((tree, 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_assert PROTO((int, int)); @@ -2476,19 +3013,21 @@ 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 tree initializer_constant_valid_p PROTO((tree, tree)); /* in xref.c */ extern void GNU_xref_begin PROTO((char *)); extern void GNU_xref_end PROTO((int)); extern void GNU_xref_file PROTO((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, 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_decl PROTO((tree, tree)); extern void GNU_xref_call PROTO((tree, char *)); extern void GNU_xref_function PROTO((tree, tree)); extern void GNU_xref_assign PROTO((tree)); -extern void GNU_xref_hier PROTO((char *, char *, int, int, int)); +extern void GNU_xref_hier PROTO((tree, tree, int, int, int)); extern void GNU_xref_member PROTO((tree, tree)); /* -- end of C++ */ diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c index 56508c1..18b7d8b 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, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92-96, 1998 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -26,14 +26,17 @@ Boston, MA 02111-1307, USA. */ but what kind of conversions it does will depend on the language. */ #include "config.h" +#include "system.h" #include "tree.h" #include "flags.h" #include "cp-tree.h" -#include "class.h" #include "convert.h" -#undef NULL -#define NULL (char *)0 +extern tree static_aggregates; + +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)); /* Change of width--truncation and extension of integers or reals-- is represented with NOP_EXPR. Proper functioning of many things @@ -57,71 +60,87 @@ Boston, MA 02111-1307, USA. */ /* Subroutines of `convert'. */ -/* Build a thunk. What it is, is an entry point that when called will - adjust the this pointer (the first argument) by offset, and then - goto the real address of the function given by REAL_ADDR that we - would like called. What we return is the address of the thunk. */ -static tree -build_thunk (offset, real_addr) - tree offset, real_addr; -{ - if (TREE_CODE (real_addr) != ADDR_EXPR - || TREE_CODE (TREE_OPERAND (real_addr, 0)) != FUNCTION_DECL) - { - sorry ("MI pointer to member conversion too complex"); - return error_mark_node; - } - sorry ("MI pointer to member conversion too complex"); - return error_mark_node; -} - -/* Convert a `pointer to member' (POINTER_TYPE to METHOD_TYPE) into - another `pointer to method'. This may involved the creation of - a thunk to handle the this offset calculation. */ -static tree -convert_fn_ptr (type, expr) - tree type, expr; -{ - if (flag_vtable_thunks) - { - tree intype = TREE_TYPE (expr); - tree binfo = get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (intype)), - TYPE_METHOD_BASETYPE (TREE_TYPE (type)), 1); - if (binfo == error_mark_node) - { - error (" in pointer to member conversion"); - return error_mark_node; - } - if (binfo == NULL_TREE) - { - /* ARM 4.8 restriction. */ - error ("invalid pointer to member conversion"); - return error_mark_node; - } - - if (BINFO_OFFSET_ZEROP (binfo)) - return build1 (NOP_EXPR, type, expr); - return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr)); - } - else - return build_ptrmemfunc (type, expr, 1); -} - /* if converting pointer to pointer if dealing with classes, check for derived->base or vice versa else if dealing with method pointers, delegate else convert blindly else if converting class, pass off to build_type_conversion else try C-style pointer conversion */ + static tree cp_convert_to_pointer (type, expr) tree type, expr; { register tree intype = TREE_TYPE (expr); register enum tree_code form; + tree rval; + + if (IS_AGGR_TYPE (intype)) + { + intype = complete_type (intype); + if (TYPE_SIZE (intype) == NULL_TREE) + { + cp_error ("can't convert from incomplete type `%T' to `%T'", + intype, type); + return error_mark_node; + } + + rval = build_type_conversion (CONVERT_EXPR, type, expr, 1); + if (rval) + { + if (rval == error_mark_node) + cp_error ("conversion of `%E' from `%T' to `%T' is ambiguous", + expr, intype, type); + return rval; + } + } 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 + || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)) + { + /* Allow an implicit this pointer for pointer to member + 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; + + expr = build (OFFSET_REF, fntype, decl, expr); + } + + if (TREE_CODE (expr) == OFFSET_REF + && TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) + expr = resolve_offset_ref (expr); + if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) + expr = build_addr_func (expr); + if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) + { + if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE) + if (pedantic || warn_pmf2ptr) + cp_pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr), + type); + return build1 (NOP_EXPR, type, expr); + } + intype = TREE_TYPE (expr); + } + if (TYPE_PTRMEMFUNC_P (intype)) intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); @@ -133,6 +152,8 @@ cp_convert_to_pointer (type, expr) if (TYPE_MAIN_VARIANT (type) != intype && 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) { enum tree_code code = PLUS_EXPR; @@ -156,9 +177,11 @@ cp_convert_to_pointer (type, expr) tree path; if (code == PLUS_EXPR) - get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), 0, &path); + get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), + 0, &path); else - get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), 0, &path); + get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), + 0, &path); return build_vbase_path (code, type, expr, path, 0); } } @@ -166,18 +189,26 @@ 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 convert_fn_ptr (type, expr); + return build_ptrmemfunc (type, expr, 1); if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE && TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE) { tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); - tree binfo = get_binfo (b1, b2, 1); + tree binfo = get_binfo (b2, b1, 1); + enum tree_code code = PLUS_EXPR; + if (binfo == NULL_TREE) - binfo = get_binfo (b2, b1, 1); + { + binfo = get_binfo (b1, b2, 1); + code = MINUS_EXPR; + } + if (binfo == error_mark_node) return error_mark_node; + if (binfo && ! TREE_VIA_VIRTUAL (binfo)) + expr = size_binop (code, expr, BINFO_OFFSET (binfo)); } if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE @@ -189,7 +220,9 @@ cp_convert_to_pointer (type, expr) return error_mark_node; } - return build1 (NOP_EXPR, type, expr); + rval = build1 (NOP_EXPR, type, expr); + TREE_CONSTANT (rval) = TREE_CONSTANT (expr); + return rval; } my_friendly_assert (form != OFFSET_TYPE, 186); @@ -198,23 +231,10 @@ cp_convert_to_pointer (type, expr) && (IS_SIGNATURE_POINTER (intype) || IS_SIGNATURE_REFERENCE (intype))) return convert_to_pointer (type, build_optr_ref (expr)); - if (IS_AGGR_TYPE (intype)) - { - tree rval; - rval = build_type_conversion (CONVERT_EXPR, type, expr, 1); - if (rval) - { - if (rval == error_mark_node) - cp_error ("conversion of `%E' from `%T' to `%T' is ambiguous", - expr, intype, type); - return rval; - } - } - if (integer_zerop (expr)) { - if (type == TREE_TYPE (null_pointer_node)) - return null_pointer_node; + if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE) + return build_ptrmemfunc (type, expr, 0); expr = build_int_2 (0, 0); TREE_TYPE (expr) = type; return expr; @@ -222,9 +242,9 @@ cp_convert_to_pointer (type, expr) if (INTEGRAL_CODE_P (form)) { - if (type_precision (intype) == POINTER_SIZE) + if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = convert (type_for_size (POINTER_SIZE, 0), expr); + expr = cp_convert (type_for_size (POINTER_SIZE, 0), expr); /* Modes may be different but sizes should be the same. */ if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))) != GET_MODE_SIZE (TYPE_MODE (type))) @@ -242,6 +262,7 @@ cp_convert_to_pointer (type, expr) /* Like convert, except permit conversions to take place which are not normally allowed due to access restrictions (such as conversion from sub-type to private super-type). */ + static tree convert_to_pointer_force (type, expr) tree type, expr; @@ -251,8 +272,6 @@ convert_to_pointer_force (type, expr) if (integer_zerop (expr)) { - if (type == TREE_TYPE (null_pointer_node)) - return null_pointer_node; expr = build_int_2 (0, 0); TREE_TYPE (expr) = type; return expr; @@ -273,6 +292,8 @@ convert_to_pointer_force (type, expr) if (TYPE_MAIN_VARIANT (type) != intype && 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) { enum tree_code code = PLUS_EXPR; @@ -282,8 +303,9 @@ convert_to_pointer_force (type, expr) if (distance == -2) { ambig: - cp_error ("type `%T' is ambiguous baseclass of `%s'", TREE_TYPE (type), - TYPE_NAME_STRING (TREE_TYPE (intype))); + cp_error ("type `%T' is ambiguous baseclass of `%s'", + TREE_TYPE (type), + TYPE_NAME_STRING (TREE_TYPE (intype))); return error_mark_node; } if (distance == -1) @@ -300,7 +322,6 @@ convert_to_pointer_force (type, expr) } return build_vbase_path (code, type, expr, path, 0); } - return build1 (NOP_EXPR, type, expr); } return cp_convert_to_pointer (type, expr); @@ -311,343 +332,61 @@ convert_to_pointer_force (type, expr) value we have to begin with is in ARG. FLAGS controls how we manage access checking. - CHECKCONST controls if we report error messages on const subversion. */ + DIRECT_BIND in FLAGS controls how any temporaries are generated. */ + static tree build_up_reference (type, arg, flags, checkconst) tree type, arg; int flags, checkconst; { - tree rval, targ; - int literal_flag = 0; + tree rval; tree argtype = TREE_TYPE (arg); tree target_type = TREE_TYPE (type); - tree binfo = NULL_TREE; my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187); + + if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg)) + { + tree targ = arg; + if (toplevel_bindings_p ()) + arg = get_temp_name (argtype, 1); + else + { + arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype)); + DECL_ARTIFICIAL (arg) = 1; + } + DECL_INITIAL (arg) = targ; + cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); + } + else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg)) + { + tree slot = build_decl (VAR_DECL, NULL_TREE, argtype); + arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE); + TREE_SIDE_EFFECTS (arg) = 1; + } + + /* If we had a way to wrap this up, and say, if we ever needed it's + address, transform all occurrences of the register, into a memory + reference we could win better. */ + rval = build_unary_op (ADDR_EXPR, arg, 1); if ((flags & LOOKUP_PROTECT) && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type) && IS_AGGR_TYPE (argtype) && IS_AGGR_TYPE (target_type)) { - binfo = get_binfo (target_type, argtype, 1); + /* We go through get_binfo for the access control. */ + tree binfo = get_binfo (target_type, argtype, 1); if (binfo == error_mark_node) return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); - } - - /* Pass along const and volatile down into the type. */ - if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) - target_type = cp_build_type_variant (target_type, TYPE_READONLY (type), - TYPE_VOLATILE (type)); - targ = arg; - if (TREE_CODE (targ) == SAVE_EXPR) - targ = TREE_OPERAND (targ, 0); - while (TREE_CODE (targ) == NOP_EXPR - && (TYPE_MAIN_VARIANT (argtype) - == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (targ, 0))))) - targ = TREE_OPERAND (targ, 0); - - switch (TREE_CODE (targ)) - { - case INDIRECT_REF: - /* This is a call to a constructor which did not know what it was - initializing until now: it needs to initialize a temporary. */ - if (TREE_HAS_CONSTRUCTOR (targ)) - { - tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1); - TREE_HAS_CONSTRUCTOR (targ) = 0; - return build_up_reference (type, temp, flags, 1); - } - /* Let &* cancel out to simplify resulting code. - Also, throw away intervening NOP_EXPRs. */ - arg = TREE_OPERAND (targ, 0); - if (TREE_CODE (arg) == NOP_EXPR || TREE_CODE (arg) == NON_LVALUE_EXPR - || (TREE_CODE (arg) == CONVERT_EXPR && TREE_REFERENCE_EXPR (arg))) - arg = TREE_OPERAND (arg, 0); - - /* in doing a &*, we have to get rid of the const'ness on the pointer - value. Haven't thought about volatile here. Pointers come to mind - here. */ - if (TREE_READONLY (arg)) - { - arg = copy_node (arg); - TREE_READONLY (arg) = 0; - } - - rval = build1 (CONVERT_EXPR, type, arg); - TREE_REFERENCE_EXPR (rval) = 1; - - /* propagate the const flag on something like: - - class Base { - public: - int foo; - }; - - class Derived : public Base { - public: - int bar; - }; - - void func(Base&); - - void func2(const Derived& d) { - func(d); - } - - on the d parameter. The below could have been avoided, if the flags - were down in the tree, not sure why they are not. (mrs) */ - /* The below code may have to be propagated to other parts of this - switch. */ - if (TREE_READONLY (targ) && !TREE_READONLY (arg) - && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL) - && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE - && (TYPE_READONLY (target_type) && checkconst)) - { - arg = copy_node (arg); - TREE_READONLY (arg) = TREE_READONLY (targ); - } - literal_flag = TREE_CONSTANT (arg); - - goto done; - - /* Get this out of a register if we happened to be in one by accident. - Also, build up references to non-lvalues it we must. */ - /* For &x[y], return (&) x+y */ - case ARRAY_REF: - if (mark_addressable (TREE_OPERAND (targ, 0)) == 0) - return error_mark_node; - rval = build_binary_op (PLUS_EXPR, TREE_OPERAND (targ, 0), - TREE_OPERAND (targ, 1), 1); - TREE_TYPE (rval) = type; - if (TREE_CONSTANT (TREE_OPERAND (targ, 1)) - && staticp (TREE_OPERAND (targ, 0))) - TREE_CONSTANT (rval) = 1; - goto done; - - case SCOPE_REF: - /* Could be a reference to a static member. */ - { - tree field = TREE_OPERAND (targ, 1); - if (TREE_STATIC (field)) - { - rval = build1 (ADDR_EXPR, type, field); - literal_flag = 1; - goto done; - } - } - - /* We should have farmed out member pointers above. */ - my_friendly_abort (188); - - case COMPONENT_REF: - rval = build_component_addr (targ, build_pointer_type (argtype), - "attempt to make a reference to bit-field structure member `%s'"); - TREE_TYPE (rval) = type; - literal_flag = staticp (TREE_OPERAND (targ, 0)); - - goto done; - - /* Anything not already handled and not a true memory reference - needs to have a reference built up. Do so silently for - things like integers and return values from function, - but complain if we need a reference to something declared - as `register'. */ - - case RESULT_DECL: - if (staticp (targ)) - literal_flag = 1; - TREE_ADDRESSABLE (targ) = 1; - put_var_into_stack (targ); - break; - - case PARM_DECL: -#if 0 - if (targ == current_class_decl) - { - error ("address of `this' not available"); -/* #if 0 */ - /* This code makes the following core dump the compiler on a sun4, - if the code below is used. - - class e_decl; - class a_decl; - typedef a_decl* a_ref; - - class a_s { - public: - a_s(); - void* append(a_ref& item); - }; - class a_decl { - public: - a_decl (e_decl *parent); - a_s generic_s; - a_s decls; - e_decl* parent; - }; - - class e_decl { - public: - e_decl(); - a_s implementations; - }; - - void foobar(void *); - - a_decl::a_decl(e_decl *parent) { - parent->implementations.append(this); - } - */ - - TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */ - put_var_into_stack (targ); - break; -/* #else */ - return error_mark_node; -/* #endif */ - } -#endif - /* Fall through. */ - case VAR_DECL: - case CONST_DECL: - if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ) - && !DECL_ARTIFICIAL (targ)) - cp_warning ("address needed to build reference for `%D', which is declared `register'", - targ); - else if (staticp (targ)) - literal_flag = 1; - - TREE_ADDRESSABLE (targ) = 1; - put_var_into_stack (targ); - break; - - case COMPOUND_EXPR: - { - tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1), - LOOKUP_PROTECT, checkconst); - rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference); - TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1)); - return rval; - } - - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case MODIFY_EXPR: - case INIT_EXPR: - { - tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0), - LOOKUP_PROTECT, checkconst); - rval = build (COMPOUND_EXPR, type, arg, real_reference); - TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0)); - return rval; - } - - case COND_EXPR: - return build (COND_EXPR, type, - TREE_OPERAND (targ, 0), - build_up_reference (type, TREE_OPERAND (targ, 1), - LOOKUP_PROTECT, checkconst), - build_up_reference (type, TREE_OPERAND (targ, 2), - LOOKUP_PROTECT, checkconst)); - - /* Undo the folding... */ - case MIN_EXPR: - case MAX_EXPR: - return build (COND_EXPR, type, - build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR, - boolean_type_node, TREE_OPERAND (targ, 0), - TREE_OPERAND (targ, 1)), - build_up_reference (type, TREE_OPERAND (targ, 0), - LOOKUP_PROTECT, checkconst), - build_up_reference (type, TREE_OPERAND (targ, 1), - LOOKUP_PROTECT, checkconst)); - - case WITH_CLEANUP_EXPR: - return build (WITH_CLEANUP_EXPR, type, - build_up_reference (type, TREE_OPERAND (targ, 0), - LOOKUP_PROTECT, checkconst), - 0, TREE_OPERAND (targ, 2)); - - case BIND_EXPR: - arg = TREE_OPERAND (targ, 1); - if (arg == NULL_TREE) - { - compiler_error ("({ ... }) expression not expanded when needed for reference"); - return error_mark_node; - } - rval = build1 (ADDR_EXPR, type, arg); - TREE_REFERENCE_EXPR (rval) = 1; - return rval; - - default: - break; - } - - if (TREE_ADDRESSABLE (targ) == 0) - { - tree temp; - - if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) - { - temp = build_cplus_new (argtype, targ, 1); - if (TREE_CODE (temp) == WITH_CLEANUP_EXPR) - rval = build (WITH_CLEANUP_EXPR, type, - build1 (ADDR_EXPR, type, TREE_OPERAND (temp, 0)), - 0, TREE_OPERAND (temp, 2)); - else - rval = build1 (ADDR_EXPR, type, temp); - goto done; - } - else - { - temp = get_temp_name (argtype, 0); - if (toplevel_bindings_p ()) - { - /* Give this new temp some rtl and initialize it. */ - DECL_INITIAL (temp) = targ; - TREE_STATIC (temp) = 1; - cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); - /* Do this after declaring it static. */ - rval = build_unary_op (ADDR_EXPR, temp, 0); - TREE_TYPE (rval) = type; - literal_flag = TREE_CONSTANT (rval); - goto done; - } - else - { - rval = build_unary_op (ADDR_EXPR, temp, 0); - if (binfo && !BINFO_OFFSET_ZEROP (binfo)) - rval = convert_pointer_to (target_type, rval); - else - TREE_TYPE (rval) = type; - - temp = build (MODIFY_EXPR, argtype, temp, arg); - TREE_SIDE_EFFECTS (temp) = 1; - return build (COMPOUND_EXPR, type, temp, rval); - } - } + rval = convert_pointer_to_real (binfo, rval); } else - rval = build1 (ADDR_EXPR, type, arg); - - done: - if (TYPE_USES_COMPLEX_INHERITANCE (argtype) - || TYPE_USES_COMPLEX_INHERITANCE (target_type)) - { - TREE_TYPE (rval) = build_pointer_type (argtype); - if (flags & LOOKUP_PROTECT) - rval = convert_pointer_to (target_type, rval); - else - rval - = convert_to_pointer_force (build_pointer_type (target_type), rval); - TREE_TYPE (rval) = type; - if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR) - TREE_TYPE (TREE_OPERAND (rval, 0)) - = TREE_TYPE (TREE_OPERAND (rval, 1)) = type; - } - TREE_CONSTANT (rval) = literal_flag; + rval + = convert_to_pointer_force (build_pointer_type (target_type), rval); + rval = build1 (NOP_EXPR, type, rval); + TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0)); return rval; } @@ -682,7 +421,8 @@ 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, type, expr, 1); + rval_as_conversion + = build_type_conversion (CONVERT_EXPR, reftype, expr, 1); if (rval_as_conversion && rval_as_conversion != error_mark_node && real_lvalue_p (rval_as_conversion)) @@ -708,15 +448,14 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ttr = cp_build_type_variant (TREE_TYPE (expr), r, v); } - if (! real_lvalue_p (expr) && - (decl == NULL_TREE || ! TYPE_READONLY (ttl))) + if (! real_lvalue_p (expr) && ! TYPE_READONLY (ttl)) { if (decl) /* Ensure semantics of [dcl.init.ref] */ - cp_pedwarn ("initialization of non-const `%T' from rvalue `%T'", + cp_pedwarn ("initialization of non-const reference `%#T' from rvalue `%T'", reftype, intype); else - cp_pedwarn ("conversion to `%T' from rvalue `%T'", + cp_pedwarn ("conversion to non-const `%T' from rvalue `%T'", reftype, intype); } else if (! (convtype & CONV_CONST)) @@ -749,89 +488,18 @@ convert_to_reference (reftype, expr, convtype, flags, decl) rval = build_unary_op (ADDR_EXPR, expr, 0); if (rval != error_mark_node) - rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0); + rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), + rval, 0); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } - else if (decl) + else { - tree rval_as_ctor = NULL_TREE; - - if (rval_as_conversion) - { - if (rval_as_conversion == error_mark_node) - { - cp_error ("conversion from `%T' to `%T' is ambiguous", - intype, reftype); - return error_mark_node; - } - rval_as_conversion = build_up_reference (reftype, rval_as_conversion, - flags, 1); - } - - /* Definitely need to go through a constructor here. */ - if (TYPE_HAS_CONSTRUCTOR (type) - && ! CLASSTYPE_ABSTRACT_VIRTUALS (type) - && (rval = build_method_call - (NULL_TREE, constructor_name_full (type), - build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), - LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY - | LOOKUP_ONLYCONVERTING))) - { - tree init; - - if (toplevel_bindings_p ()) - { - extern tree static_aggregates; - tree t = get_temp_name (type, toplevel_bindings_p ()); - init = build_method_call (t, constructor_name_full (type), - build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION - | LOOKUP_ONLYCONVERTING); - - if (init == error_mark_node) - return error_mark_node; - - make_decl_rtl (t, NULL_PTR, 1); - static_aggregates = perm_tree_cons (expr, t, static_aggregates); - rval = build_unary_op (ADDR_EXPR, t, 0); - } - else - { - init = build_method_call (NULL_TREE, constructor_name_full (type), - build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION - |LOOKUP_ONLYCONVERTING); - - if (init == error_mark_node) - return error_mark_node; - - rval = build_cplus_new (type, init, 1); - rval = build_up_reference (reftype, rval, flags, 1); - } - rval_as_ctor = rval; - } - - if (rval_as_ctor && rval_as_conversion) - { - cp_error ("ambiguous conversion from `%T' to `%T'; both user-defined conversion and constructor apply", - intype, reftype); - return error_mark_node; - } - else if (rval_as_ctor) - rval = rval_as_ctor; - else if (rval_as_conversion) - rval = rval_as_conversion; - else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype)) - { - rval = convert (type, expr); - if (rval == error_mark_node) - return error_mark_node; - - rval = build_up_reference (reftype, rval, flags, 1); - } + 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 && ! TYPE_READONLY (TREE_TYPE (reftype))) cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary", @@ -840,7 +508,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl) if (rval) { - /* If we found a way to convert earlier, then use it. */ + /* If we found a way to convert earlier, then use it. */ return rval; } @@ -856,7 +524,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl) } /* We are using a reference VAL for its value. Bash that reference all the - way down to its lowest form. */ + way down to its lowest form. */ + tree convert_from_reference (val) tree val; @@ -870,231 +539,13 @@ convert_from_reference (val) return val; } -/* See if there is a constructor of type TYPE which will convert - EXPR. The reference manual seems to suggest (8.5.6) that we need - not worry about finding constructors for base classes, then converting - to the derived class. - - MSGP is a pointer to a message that would be an appropriate error - string. If MSGP is NULL, then we are not interested in reporting - errors. */ -tree -convert_to_aggr (type, expr, msgp, protect) - tree type, expr; - char **msgp; - int protect; -{ - tree basetype = type; - tree name = TYPE_IDENTIFIER (basetype); - tree function, fndecl, fntype, parmtypes, parmlist, result; - tree method_name; - enum access_type access; - int can_be_private, can_be_protected; - - if (! TYPE_HAS_CONSTRUCTOR (basetype)) - { - if (msgp) - *msgp = "type `%s' does not have a constructor"; - return error_mark_node; - } - - access = access_public; - can_be_private = 0; - can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name; - - parmlist = build_tree_list (NULL_TREE, expr); - parmtypes = tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node); - - if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)) - { - parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes); - parmlist = tree_cons (NULL_TREE, integer_one_node, parmlist); - } - - /* The type of the first argument will be filled in inside the loop. */ - parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist); - parmtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes); - -#if 0 - method_name = build_decl_overload (name, parmtypes, 1); - - /* constructors are up front. */ - fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); - if (TYPE_HAS_DESTRUCTOR (basetype)) - fndecl = DECL_CHAIN (fndecl); - - while (fndecl) - { - if (DECL_ASSEMBLER_NAME (fndecl) == method_name) - { - function = fndecl; - if (protect) - { - if (TREE_PRIVATE (fndecl)) - { - can_be_private = - (basetype == current_class_type - || is_friend (basetype, current_function_decl) - || purpose_member (basetype, DECL_ACCESS (fndecl))); - if (! can_be_private) - goto found; - } - else if (TREE_PROTECTED (fndecl)) - { - if (! can_be_protected) - goto found; - } - } - goto found_and_ok; - } - fndecl = DECL_CHAIN (fndecl); - } -#endif - - /* No exact conversion was found. See if an approximate - one will do. */ - fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); - if (TYPE_HAS_DESTRUCTOR (basetype)) - fndecl = DECL_CHAIN (fndecl); - - { - int saw_private = 0; - int saw_protected = 0; - struct candidate *candidates = - (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate)); - struct candidate *cp = candidates; - - while (fndecl) - { - function = fndecl; - cp->h_len = 2; - cp->harshness = (struct harshness_code *) - alloca (3 * sizeof (struct harshness_code)); - - compute_conversion_costs (fndecl, parmlist, cp, 2); - if ((cp->h.code & EVIL_CODE) == 0) - { - cp->u.field = fndecl; - if (protect) - { - if (TREE_PRIVATE (fndecl)) - access = access_private; - else if (TREE_PROTECTED (fndecl)) - access = access_protected; - else - access = access_public; - } - else - access = access_public; - - if (access == access_private - ? (basetype == current_class_type - || is_friend (basetype, cp->function) - || purpose_member (basetype, DECL_ACCESS (fndecl))) - : access == access_protected - ? (can_be_protected - || purpose_member (basetype, DECL_ACCESS (fndecl))) - : 1) - { - if (cp->h.code <= TRIVIAL_CODE) - goto found_and_ok; - cp++; - } - else - { - if (access == access_private) - saw_private = 1; - else - saw_protected = 1; - } - } - fndecl = DECL_CHAIN (fndecl); - } - if (cp - candidates) - { - /* Rank from worst to best. Then cp will point to best one. - Private fields have their bits flipped. For unsigned - numbers, this should make them look very large. - If the best alternate has a (signed) negative value, - then all we ever saw were private members. */ - if (cp - candidates > 1) - qsort (candidates, /* char *base */ - cp - candidates, /* int nel */ - sizeof (struct candidate), /* int width */ - rank_for_overload); /* int (*compar)() */ - - --cp; - if (cp->h.code & EVIL_CODE) - { - if (msgp) - *msgp = "ambiguous type conversion possible for `%s'"; - return error_mark_node; - } - - function = cp->function; - fndecl = cp->u.field; - goto found_and_ok; - } - else if (msgp) - { - if (saw_private) - if (saw_protected) - *msgp = "only private and protected conversions apply"; - else - *msgp = "only private conversions apply"; - else if (saw_protected) - *msgp = "only protected conversions apply"; - else - *msgp = "no appropriate conversion to type `%s'"; - } - return error_mark_node; - } - /* NOTREACHED */ - - found: - if (access == access_private) - if (! can_be_private) - { - if (msgp) - *msgp = TREE_PRIVATE (fndecl) - ? "conversion to type `%s' is private" - : "conversion to type `%s' is from private base class"; - return error_mark_node; - } - if (access == access_protected) - if (! can_be_protected) - { - if (msgp) - *msgp = TREE_PRIVATE (fndecl) - ? "conversion to type `%s' is protected" - : "conversion to type `%s' is from protected base class"; - return error_mark_node; - } - function = fndecl; - found_and_ok: - - /* It will convert, but we don't do anything about it yet. */ - if (msgp == 0) - return NULL_TREE; - - fntype = TREE_TYPE (function); - function = default_conversion (function); - - result = build_nt (CALL_EXPR, function, - convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), - parmlist, NULL_TREE, LOOKUP_NORMAL), - NULL_TREE); - TREE_TYPE (result) = TREE_TYPE (fntype); - TREE_SIDE_EFFECTS (result) = 1; - return result; -} - /* Call this when we know (for any reason) that expr is not, in fact, zero. This routine is like convert_pointer_to, but it pays attention to which specific instance of what type we want to convert to. This routine should eventually become convert_to_pointer after all references to convert_to_pointer are removed. */ + tree convert_pointer_to_real (binfo, expr) tree binfo, expr; @@ -1103,6 +554,9 @@ convert_pointer_to_real (binfo, expr) tree ptr_type; tree type, rval; + if (intype == error_mark_node) + return error_mark_node; + if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (IS_AGGR_TYPE (binfo)) @@ -1115,13 +569,12 @@ convert_pointer_to_real (binfo, expr) binfo = NULL_TREE; } - ptr_type = build_pointer_type (type); + ptr_type = cp_build_type_variant (type, TYPE_READONLY (TREE_TYPE (intype)), + TYPE_VOLATILE (TREE_TYPE (intype))); + ptr_type = build_pointer_type (ptr_type); if (ptr_type == TYPE_MAIN_VARIANT (intype)) return expr; - if (intype == error_mark_node) - return error_mark_node; - my_friendly_assert (!integer_zerop (expr), 191); if (TREE_CODE (type) == RECORD_TYPE @@ -1159,6 +612,7 @@ convert_pointer_to_real (binfo, expr) is more than one instance of that type in the expr, the conversion is ambiguous. This routine should eventually go away, and all callers should use convert_to_pointer_real. */ + tree convert_pointer_to (binfo, expr) tree binfo, expr; @@ -1174,23 +628,39 @@ convert_pointer_to (binfo, expr) return convert_pointer_to_real (type, expr); } +/* C++ conversions, preference to static cast conversions. */ + +tree +cp_convert (type, expr) + tree type, expr; +{ + return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); +} + /* Conversion... FLAGS indicates how we should behave. */ tree -cp_convert (type, expr, convtype, flags) +ocp_convert (type, expr, convtype, flags) tree type, expr; int convtype, flags; { register tree e = expr; register enum tree_code code = TREE_CODE (type); - if (TREE_CODE (e) == ERROR_MARK - || TREE_CODE (TREE_TYPE (e)) == ERROR_MARK) + if (e == error_mark_node + || TREE_TYPE (e) == error_mark_node) return error_mark_node; - if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)) + if (TREE_READONLY_DECL_P (e)) + e = decl_constant_value (e); + + if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP) + /* Some internal structures (vtable_entry_type, sigtbl_ptr_type) + don't go through finish_struct, so they don't have the synthesized + constructors. So don't force a temporary. */ + && 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. */ @@ -1203,7 +673,7 @@ cp_convert (type, expr, convtype, flags) /* This is incorrect. A truncation can't be stripped this way. Extensions will be stripped by the use of get_unwidened. */ if (TREE_CODE (e) == NOP_EXPR) - return convert (type, TREE_OPERAND (e, 0)); + return cp_convert (type, TREE_OPERAND (e, 0)); #endif /* Just convert to the type of the member. */ @@ -1223,18 +693,15 @@ cp_convert (type, expr, convtype, flags) if (TREE_CODE (e) == OFFSET_REF) e = resolve_offset_ref (e); - if (TREE_READONLY_DECL_P (e)) - e = decl_constant_value (e); - if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); - enum tree_code form = TREE_CODE (intype); - /* enum = enum, enum = int, enum = float are all errors. */ + /* enum = enum, enum = int, enum = float, (enum)pointer are all + errors. */ if (flag_int_enum_equivalence == 0 && TREE_CODE (type) == ENUMERAL_TYPE - && ARITHMETIC_TYPE_P (intype) - && ! (convtype & CONV_STATIC)) + && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC)) + || (TREE_CODE (intype) == POINTER_TYPE))) { cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type); @@ -1254,13 +721,19 @@ cp_convert (type, expr, convtype, flags) return error_mark_node; } if (code == BOOLEAN_TYPE) - return truthvalue_conversion (e); + { + /* Common Ada/Pascal programmer's mistake. We always warn + about this since it is so bad. */ + if (TREE_CODE (expr) == FUNCTION_DECL) + cp_warning ("the address of `%D', will always be `true'", expr); + return truthvalue_conversion (e); + } return fold (convert_to_integer (type, e)); } if (code == POINTER_TYPE || code == REFERENCE_TYPE || TYPE_PTRMEMFUNC_P (type)) return fold (cp_convert_to_pointer (type, e)); - if (code == REAL_TYPE) + if (code == REAL_TYPE || code == COMPLEX_TYPE) { if (IS_AGGR_TYPE (TREE_TYPE (e))) { @@ -1273,7 +746,10 @@ cp_convert (type, expr, convtype, flags) cp_error ("`%#T' used where a floating point value was expected", TREE_TYPE (e)); } - return fold (convert_to_real (type, e)); + if (code == REAL_TYPE) + return fold (convert_to_real (type, e)); + else if (code == COMPLEX_TYPE) + return fold (convert_to_complex (type, e)); } /* New C++ semantics: since assignment is now based on @@ -1283,7 +759,6 @@ cp_convert (type, expr, convtype, flags) { tree dtype = TREE_TYPE (e); tree ctor = NULL_TREE; - tree conversion = NULL_TREE; dtype = TYPE_MAIN_VARIANT (dtype); @@ -1317,53 +792,24 @@ cp_convert (type, expr, convtype, flags) There may be some ambiguity between using a constructor vs. using a type conversion operator when both apply. */ - if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype) - && TYPE_HAS_CONVERSION (dtype)) - conversion = build_type_conversion (CONVERT_EXPR, type, e, 1); - - if (conversion == error_mark_node) - { - if (flags & LOOKUP_COMPLAIN) - error ("ambiguous pointer conversion"); - return conversion; - } - - if (TYPE_HAS_CONSTRUCTOR (type)) - ctor = build_method_call (NULL_TREE, constructor_name_full (type), - build_tree_list (NULL_TREE, e), - TYPE_BINFO (type), - (flags & LOOKUP_NORMAL) | LOOKUP_SPECULATIVELY - | (convtype&CONV_NONCONVERTING ? 0 : LOOKUP_ONLYCONVERTING) - | (conversion ? LOOKUP_NO_CONVERSION : 0)); - - if (ctor == error_mark_node) - { - if (flags & LOOKUP_COMPLAIN) - cp_error ("in conversion to type `%T'", type); - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; - return error_mark_node; - } - - if (conversion && ctor) - { - if (flags & LOOKUP_COMPLAIN) - error ("both constructor and type conversion operator apply"); - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; - return error_mark_node; - } - else if (conversion) - return conversion; - else if (ctor) - { - ctor = build_cplus_new (type, ctor, 0); - return ctor; - } + ctor = e; + + 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 + with a user-defined conversion sequence, then we direct-initialize + the target with the temp (see [dcl.init]). */ + ctor = build_user_type_conversion (type, ctor, flags); + if (ctor) + ctor = build_method_call (NULL_TREE, ctor_identifier, + build_expr_list (NULL_TREE, ctor), + TYPE_BINFO (type), flags); + if (ctor) + return build_cplus_new (type, ctor); } /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack, - then the it won't be hashed and hence compare as not equal, + then it won't be hashed and hence compare as not equal, even when it is. */ if (code == ARRAY_TYPE && TREE_TYPE (TREE_TYPE (e)) == TREE_TYPE (type) @@ -1382,18 +828,45 @@ cp_convert (type, expr, convtype, flags) converted to type TYPE. The TREE_TYPE of the value is always TYPE. This function implements all reasonable conversions; callers should filter out those that are - not permitted by the language being compiled. */ + not permitted by the language being compiled. + + Most of this routine is from build_reinterpret_cast. + + The backend cannot call cp_convert (what was convert) because + conversions to/from basetypes may involve memory references + (vbases) and adding or subtracting small values (multiple + inheritance), but it calls convert from the constant folding code + on subtrees of already build trees after it has ripped them apart. + + Also, if we ever support range variables, we'll probably also have to + do a little bit more work. */ tree convert (type, expr) tree type, expr; { - return cp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); + tree intype; + + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; + + intype = TREE_TYPE (expr); + + if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype)) + { + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return fold (build1 (NOP_EXPR, type, expr)); + } + + return ocp_convert (type, expr, CONV_OLD_CONVERT, + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); } -/* Like convert, except permit conversions to take place which +/* Like cp_convert, except permit conversions to take place which are not normally allowed due to access restrictions (such as conversion from sub-type to private super-type). */ + tree convert_force (type, expr, convtype) tree type; @@ -1420,46 +893,11 @@ convert_force (type, expr, convtype) || TYPE_PTRMEMFUNC_P (TREE_TYPE (e))) && TYPE_PTRMEMFUNC_P (type)) { - /* compatible pointer to member functions. */ + /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); } - return cp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); -} - -/* Subroutine of build_type_conversion. */ -static tree -build_type_conversion_1 (xtype, basetype, expr, typename, for_sure) - tree xtype, basetype; - tree expr; - tree typename; - int for_sure; -{ - tree rval; - int flags; - - if (for_sure == 0) - flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING; - else - flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING; - - rval = build_method_call (expr, typename, NULL_TREE, NULL_TREE, flags); - if (rval == error_mark_node) - { - if (for_sure == 0) - return NULL_TREE; - return error_mark_node; - } - - if (IS_AGGR_TYPE (TREE_TYPE (rval))) - return rval; - - if (warn_cast_qual - && TREE_TYPE (xtype) - && (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval))) - > TREE_READONLY (TREE_TYPE (xtype)))) - warning ("user-defined conversion casting away `const'"); - return convert (xtype, rval); + return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); } /* Convert an aggregate EXPR to type XTYPE. If a conversion @@ -1487,58 +925,8 @@ build_type_conversion (code, xtype, expr, for_sure) { /* C++: check to see if we can convert this aggregate type into the required type. */ - tree basetype; - tree conv; - tree winner = NULL_TREE; - - if (expr == error_mark_node) - return error_mark_node; - - basetype = TREE_TYPE (expr); - if (TREE_CODE (basetype) == REFERENCE_TYPE) - basetype = TREE_TYPE (basetype); - - basetype = TYPE_MAIN_VARIANT (basetype); - if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype)) - return NULL_TREE; - - /* Do we have an exact match? */ - { - tree typename = build_typename_overload (xtype); - if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) - return build_type_conversion_1 (xtype, basetype, expr, typename, - for_sure); - } - - /* Nope; try looking for others. */ - for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) - { - if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) - continue; - - if (can_convert (xtype, TREE_VALUE (conv))) - { - if (winner) - { - if (for_sure) - { - cp_error ("ambiguous conversion from `%T' to `%T'", basetype, - xtype); - cp_error (" candidate conversions include `%T' and `%T'", - TREE_VALUE (winner), TREE_VALUE (conv)); - } - return NULL_TREE; - } - else - winner = conv; - } - } - - if (winner) - return build_type_conversion_1 (xtype, basetype, expr, - TREE_PURPOSE (winner), for_sure); - - return NULL_TREE; + return build_user_type_conversion + (xtype, expr, for_sure ? LOOKUP_NORMAL : 0); } /* Convert the given EXPR to one of a group of types suitable for use in an @@ -1568,7 +956,7 @@ build_expr_type_conversion (desires, expr, complain) if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST && integer_zerop (expr)) return expr; - /* else fall through... */ + /* else fall through... */ case BOOLEAN_TYPE: return (desires & WANT_INT) ? expr : NULL_TREE; @@ -1587,6 +975,9 @@ build_expr_type_conversion (desires, expr, complain) return NULL_TREE; } + /* The code for conversions from class type is currently only used for + delete expressions. Other expressions are handled by build_new_op. */ + if (! TYPE_HAS_CONVERSION (basetype)) return NULL_TREE; @@ -1594,11 +985,12 @@ build_expr_type_conversion (desires, expr, complain) { int win = 0; tree candidate; + tree cand = TREE_VALUE (conv); - if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + if (winner && winner == cand) continue; - candidate = TREE_VALUE (conv); + candidate = TREE_TYPE (TREE_TYPE (cand)); if (TREE_CODE (candidate) == REFERENCE_TYPE) candidate = TREE_TYPE (candidate); @@ -1613,6 +1005,9 @@ build_expr_type_conversion (desires, expr, complain) win = (desires & WANT_FLOAT); break; case POINTER_TYPE: win = (desires & WANT_POINTER); break; + + default: + break; } if (win) @@ -1623,153 +1018,29 @@ build_expr_type_conversion (desires, expr, complain) { cp_error ("ambiguous default type conversion from `%T'", basetype); - cp_error (" candidate conversions include `%T' and `%T'", - TREE_VALUE (winner), TREE_VALUE (conv)); + cp_error (" candidate conversions include `%D' and `%D'", + winner, cand); } return error_mark_node; } else - winner = conv; + winner = cand; } } if (winner) - return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr, - TREE_PURPOSE (winner), 1); - - return NULL_TREE; -} - -/* Must convert two aggregate types to non-aggregate type. - Attempts to find a non-ambiguous, "best" type conversion. - - Return 1 on success, 0 on failure. - - @@ What are the real semantics of this supposed to be??? */ -int -build_default_binary_type_conversion (code, arg1, arg2) - enum tree_code code; - tree *arg1, *arg2; -{ - switch (code) { - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case CEIL_DIV_EXPR: - case FLOOR_DIV_EXPR: - case ROUND_DIV_EXPR: - case EXACT_DIV_EXPR: - *arg1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); - *arg2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); - break; - - case TRUNC_MOD_EXPR: - case FLOOR_MOD_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case BIT_AND_EXPR: - case BIT_XOR_EXPR: - case BIT_IOR_EXPR: - *arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0); - *arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0); - break; - - case PLUS_EXPR: - { - tree a1, a2, p1, p2; - int wins; - - a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); - a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); - p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0); - p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0); - - wins = (a1 && a2) + (a1 && p2) + (p1 && a2); - - if (wins > 1) - error ("ambiguous default type conversion for `operator +'"); - - if (a1 && a2) - *arg1 = a1, *arg2 = a2; - else if (a1 && p2) - *arg1 = a1, *arg2 = p2; - else - *arg1 = p1, *arg2 = a2; - break; - } - - case MINUS_EXPR: - { - tree a1, a2, p1, p2; - int wins; - - a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); - a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); - p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0); - p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0); - - wins = (a1 && a2) + (p1 && p2) + (p1 && a2); - - if (wins > 1) - error ("ambiguous default type conversion for `operator -'"); - - if (a1 && a2) - *arg1 = a1, *arg2 = a2; - else if (p1 && p2) - *arg1 = p1, *arg2 = p2; - else - *arg1 = p1, *arg2 = a2; - break; - } - - case GT_EXPR: - case LT_EXPR: - case GE_EXPR: - case LE_EXPR: - case EQ_EXPR: - case NE_EXPR: - { - tree a1, a2, p1, p2; - int wins; - - a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); - a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); - p1 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg1, 0); - p2 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg2, 0); - - wins = (a1 && a2) + (p1 && p2); - - if (wins > 1) - cp_error ("ambiguous default type conversion for `%O'", code); - - if (a1 && a2) - *arg1 = a1, *arg2 = a2; - else - *arg1 = p1, *arg2 = p2; - break; - } - - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - *arg1 = convert (boolean_type_node, *arg1); - *arg2 = convert (boolean_type_node, *arg2); - break; - - default: - *arg1 = NULL_TREE; - *arg2 = NULL_TREE; + tree type = TREE_TYPE (TREE_TYPE (winner)); + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + return build_user_type_conversion (type, expr, LOOKUP_NORMAL); } - if (*arg1 == error_mark_node || *arg2 == error_mark_node) - cp_error ("ambiguous default type conversion for `%O'", code); - - if (*arg1 && *arg2) - return 1; - - return 0; + return NULL_TREE; } -/* Implements integral promotion (4.1) and float->double promotion. */ +/* Implements integral promotion (4.1) and float->double promotion. */ + tree type_promotes_to (type) tree type; @@ -1804,11 +1075,9 @@ type_promotes_to (type) } else if (C_PROMOTING_INTEGER_TYPE_P (type)) { - /* Traditionally, unsignedness is preserved in default promotions. - Otherwise, retain unsignedness if really not getting bigger. */ + /* Retain unsignedness if really not getting bigger. */ if (TREE_UNSIGNED (type) - && (flag_traditional - || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) + && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) type = unsigned_type_node; else type = integer_type_node; @@ -1818,3 +1087,24 @@ type_promotes_to (type) return cp_build_type_variant (type, constp, volatilep); } + + +/* 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 + should presumably be used everywhere in the future. */ + +/* Attempt to perform qualification conversions on EXPR to convert it + to TYPE. Return the resulting expression, or error_mark_node if + the conversion was impossible. */ + +tree +perform_qualification_conversions (type, expr) + tree type; + tree expr; +{ + if (comp_target_types (type, TREE_TYPE (expr), 0) == 1) + 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 103cb0d..68f62ae 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -1,6 +1,6 @@ /* Process declarations and variables for C compiler. - Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Hacked by Michael Tiemann (tiemann@cygnus.com) + Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -27,17 +27,20 @@ Boston, MA 02111-1307, USA. */ /* ??? not all decl nodes are given the most useful possible line numbers. For example, the CONST_DECLs for enum values. */ -#include #include "config.h" +#include "system.h" #include "tree.h" #include "rtl.h" #include "flags.h" #include "cp-tree.h" #include "decl.h" #include "lex.h" -#include #include #include "obstack.h" +#include "defaults.h" +#include "output.h" +#include "except.h" +#include "toplev.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free @@ -45,19 +48,25 @@ Boston, MA 02111-1307, USA. */ extern tree builtin_return_address_fndecl; extern struct obstack permanent_obstack; +extern struct obstack* saveable_obstack; extern int current_class_depth; -extern tree cleanups_this_call; - extern tree static_ctors, static_dtors; +extern int static_labelno; + +extern tree current_namespace; +extern tree global_namespace; + +extern void (*print_error_function) PROTO((char *)); + /* 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" -static struct obstack decl_obstack; +struct obstack decl_obstack; static struct stack_level *decl_stack; #ifndef CHAR_TYPE_SIZE @@ -98,9 +107,9 @@ static struct stack_level *decl_stack; #ifndef BOOL_TYPE_SIZE #ifdef SLOW_BYTE_ACCESS -#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (BITS_PER_WORD) : (BITS_PER_UNIT)) +#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (POINTER_SIZE) : (CHAR_TYPE_SIZE)) #else -#define BOOL_TYPE_SIZE BITS_PER_UNIT +#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE #endif #endif @@ -125,12 +134,54 @@ 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 void grok_op_properties PROTO((tree, int, int)); - -tree define_function - PROTO((char *, tree, enum built_in_function, void (*)(), char *)); +static tree push_overloaded_decl PROTO((tree, int)); + +static struct stack_level *push_decl_level PROTO((struct stack_level *, + struct obstack *)); +static void push_binding_level PROTO((struct binding_level *, int, + int)); +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 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)); +static int unary_op_p PROTO((tree)); +static tree store_bindings PROTO((tree, tree)); +static tree lookup_tag_reverse PROTO((tree, tree)); +static tree obscure_complex_init PROTO((tree, tree)); +static tree maybe_build_cleanup_1 PROTO((tree, tree)); +static tree lookup_name_real PROTO((tree, int, int, int)); +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)); +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, + int)); +static void lang_print_error_function PROTO((char *)); + +#if defined (DEBUG_CP_BINDING_LEVELS) +static void indent PROTO((void)); +#endif -/* a node which has tree code ERROR_MARK, and whose type is itself. +/* A node which has tree code ERROR_MARK, and whose type is itself. All erroneous expressions are replaced with this node. All functions that accept nodes as arguments should avoid generating error messages if this node is one of the arguments, since it is undesirable to get @@ -168,24 +219,41 @@ tree float_type_node; tree double_type_node; tree long_double_type_node; +tree complex_integer_type_node; +tree complex_float_type_node; +tree complex_double_type_node; +tree complex_long_double_type_node; + tree intQI_type_node; tree intHI_type_node; tree intSI_type_node; tree intDI_type_node; +tree intTI_type_node; tree unsigned_intQI_type_node; tree unsigned_intHI_type_node; tree unsigned_intSI_type_node; tree unsigned_intDI_type_node; +tree unsigned_intTI_type_node; + +tree java_byte_type_node; +tree java_short_type_node; +tree java_int_type_node; +tree java_long_type_node; +tree java_float_type_node; +tree java_double_type_node; +tree java_char_type_node; +tree java_boolean_type_node; -/* a VOID_TYPE node, and the same, packaged in a TREE_LIST. */ +/* A VOID_TYPE node, and the same, packaged in a TREE_LIST. */ tree void_type_node, void_list_node; tree void_zero_node; /* Nodes for types `void *' and `const void *'. */ -tree ptr_type_node, const_ptr_type_node; +tree ptr_type_node; +tree const_ptr_type_node; /* Nodes for types `char *' and `const char *'. */ @@ -209,38 +277,33 @@ tree wchar_array_type_node; /* The bool data type, and constants */ tree boolean_type_node, boolean_true_node, boolean_false_node; -/* type `int ()' -- used for implicit declaration of functions. */ +/* Type `int ()' -- used for implicit declaration of functions. */ tree default_function_type; -/* function types `double (double)' and `double (double, double)', etc. */ +/* Function types `double (double)' and `double (double, double)', etc. */ -tree double_ftype_double, double_ftype_double_double; -tree int_ftype_int, long_ftype_long; - -/* Function type `void (void *, void *, int)' and similar ones. */ - -tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int; - -/* Function type `char *(char *, char *)' and similar ones */ -tree string_ftype_ptr_ptr, int_ftype_string_string; - -/* Function type `size_t (const char *)' */ -tree sizet_ftype_string; +static tree double_ftype_double, double_ftype_double_double; +static tree int_ftype_int, long_ftype_long; +static tree float_ftype_float; +static tree ldouble_ftype_ldouble; /* Function type `int (const void *, const void *, size_t)' */ -tree int_ftype_cptr_cptr_sizet; +static tree int_ftype_cptr_cptr_sizet; /* C++ extensions */ tree vtable_entry_type; tree delta_type_node; #if 0 -/* Old rtti stuff. */ +/* Old rtti stuff. */ tree __baselist_desc_type_node; tree __i_desc_type_node, __m_desc_type_node; tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type; #endif -tree __t_desc_type_node, __tp_desc_type_node; +tree __t_desc_type_node; +#if 0 +tree __tp_desc_type_node; +#endif tree __access_mode_type_node; tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node; tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node; @@ -252,21 +315,44 @@ tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type; tree __ptmf_desc_array_type, __ptmd_desc_array_type; #endif +/* Indicates that there is a type value in some namespace, although + that is not necessarily in scope at the moment. */ + +static tree global_type_node; + tree class_star_type_node; tree class_type_node, record_type_node, union_type_node, enum_type_node; tree unknown_type_node; tree opaque_type_node, signature_type_node; tree sigtable_entry_type; -tree maybe_gc_cleanup; /* Array type `vtable_entry_type[]' */ tree vtbl_type_node; +/* namespace std */ +tree std_node; +int in_std = 0; + +/* Expect only namespace names now. */ +static int only_namespace_names; + /* In a destructor, the point at which all derived class destroying has been done, just before any base class destroying will be done. */ tree dtor_label; +/* In a destructor, the last insn emitted after the start of the + function and the parms. */ + +static rtx last_dtor_insn; + +/* In a constructor, the last insn emitted after the start of the + function and the parms, the exception specification and any + function-try-block. The constructor initializers are emitted after + this insn. */ + +static rtx last_parm_cleanup_insn; + /* In a constructor, the point at which we are ready to return the pointer to the initialized object. */ @@ -284,7 +370,7 @@ extern rtx cleanup_label, return_label; but due to being an addressable named return value, would up on the stack, this variable holds the named return value's original location. */ -rtx original_result_rtx; +static rtx original_result_rtx; /* Sequence of insns which represents base initialization. */ tree base_init_expr; @@ -293,23 +379,40 @@ tree base_init_expr; Identifiers for `this' in member functions and the auto-delete parameter for destructors. */ tree this_identifier, in_charge_identifier; -/* Used in pointer to member functions, in vtables, and in sigtables. */ +tree ctor_identifier, dtor_identifier; +/* Used in pointer to member functions, in vtables, and in sigtables. */ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier; tree pfn_or_delta2_identifier, tag_identifier; -tree vb_off_identifier, vt_off_identifier; +tree vt_off_identifier; + +struct named_label_list +{ + struct binding_level *binding_level; + tree names_in_scope; + tree label_decl; + char *filename_o_goto; + int lineno_o_goto; + struct named_label_list *next; +}; /* A list (chain of TREE_LIST nodes) of named label uses. The TREE_PURPOSE field is the list of variables defined - the the label's scope defined at the point of use. + in the label's scope defined at the point of use. The TREE_VALUE field is the LABEL_DECL used. The TREE_TYPE field holds `current_binding_level' at the point of the label's use. + BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken. + + Look at the pretty struct named_label_list. See the pretty struct + with the pretty named fields that describe what they do. See the + pretty lack of gratuitous casts. Notice the code got a lot cleaner. + Used only for jumps to as-yet undefined labels, since jumps to defined labels can have their validity checked by stmt.c. */ -static tree named_label_uses; +static struct named_label_list *named_label_uses = NULL; /* A list of objects which have constructors or destructors which reside in the global scope. The decl is stored in @@ -325,17 +428,14 @@ tree static_aggregates; tree integer_zero_node; tree null_pointer_node; -/* A node for the integer constants 1, 2, and 3. */ +/* The value for __null (NULL), either of type `void *' or, with -ansi, + an integer type of the same size. */ -tree integer_one_node, integer_two_node, integer_three_node; +tree null_node; -/* Nonzero if we have seen an invalid cross reference - to a struct, union, or enum, but not yet printed the message. */ +/* A node for the integer constants 1, 2, and 3. */ -tree pending_invalid_xref; -/* File and line to appear in the eventual error message. */ -char *pending_invalid_xref_file; -int pending_invalid_xref_line; +tree integer_one_node, integer_two_node, integer_three_node; /* While defining an enum type, this is 1 plus the last enumerator constant value. */ @@ -375,13 +475,6 @@ static tree named_labels; static tree shadowed_labels; -#if 0 /* Not needed by C++ */ -/* Nonzero when store_parm_decls is called indicates a varargs function. - Value not meaningful after store_parm_decls. */ - -static int c_function_varargs; -#endif - /* The FUNCTION_DECL for the function currently being compiled, or 0 if between functions. */ tree current_function_decl; @@ -427,7 +520,7 @@ extern int flag_no_nonansi_builtin; extern int flag_ansi; /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) - objects. */ + objects. */ extern int flag_huge_objects; /* Nonzero if we want to conserve space in the .o files. We do this @@ -445,7 +538,7 @@ extern tree *current_lang_base, *current_lang_stack; /* Set to 0 at beginning of a constructor, set to 1 if that function does an allocation before referencing its instance variable. */ -int current_function_assigns_this; +static int current_function_assigns_this; int current_function_just_assigned_this; /* Set to 0 at beginning of a function. Set non-zero when @@ -453,14 +546,6 @@ int current_function_just_assigned_this; if this flag is non-zero! */ int current_function_parms_stored; -/* Current end of entries in the gc obstack for stack pointer variables. */ - -int current_function_obstack_index; - -/* Flag saying whether we have used the obstack in this function or not. */ - -int current_function_obstack_usage; - /* Flag used when debugging spew.c */ extern int spew_debug; @@ -470,8 +555,14 @@ extern int spew_debug; when entering another class scope (i.e. a cache miss). */ extern tree previous_class_values; +/* A expression of value 0 with the same precision as a sizetype + node, but signed. */ +tree signed_size_zero_node; + /* Allocate a level of searching. */ + +static struct stack_level * push_decl_level (stack, obstack) struct stack_level *stack; @@ -484,24 +575,22 @@ push_decl_level (stack, obstack) } /* For each binding contour we allocate a binding_level structure - * which records the names defined in that contour. - * Contours include: - * 0) the global one - * 1) one for each function definition, - * where internal declarations of the parameters appear. - * 2) one for each compound statement, - * to record its declarations. - * - * The current meaning of a name can be found by searching the levels from - * the current one out to the global one. - * - * Off to the side, may be the class_binding_level. This exists - * only 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. - */ + which records the names defined in that contour. + Contours include: + 0) the global one + 1) one for each function definition, + where internal declarations of the parameters appear. + 2) one for each compound statement, + to record its declarations. + + The current meaning of a name can be found by searching the levels + from the current one out to the global one. + + Off to the side, may be the class_binding_level. This exists only + 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. */ /* Note that the information in the `names' component of the global contour is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */ @@ -509,21 +598,27 @@ push_decl_level (stack, obstack) 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. - */ + and typedef types. These are in the reverse of the order + supplied. */ tree names; - /* A list of structure, union and enum definitions, - * for looking up tag names. - * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name, - * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE, - * or ENUMERAL_TYPE node. - * - * C++: the TREE_VALUE nodes can be simple types for component_bindings. - * - */ + /* A list of structure, union and enum definitions, for looking up + tag names. + It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name, + or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE, + or ENUMERAL_TYPE node. + + C++: the TREE_VALUE nodes can be simple types for + component_bindings. */ tree tags; + /* A list of USING_DECL nodes. */ + tree usings; + + /* A list of used namespaces. PURPOSE is the namespace, + 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 @@ -554,7 +649,7 @@ 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 traditional code. */ + be referenced in ARM-era code. */ tree dead_vars_from_for; /* 1 for the level that holds the parameters of a function. @@ -574,24 +669,19 @@ struct binding_level unsigned more_cleanups_ok : 1; unsigned have_cleanups : 1; - /* Nonzero if we should accept any name as an identifier in - this scope. This happens in some template definitions. */ - unsigned accept_any : 1; - - /* Nonzero if this level is for completing a template class definition - inside a binding level that temporarily binds the parameters. This - means that definitions here should not be popped off when unwinding - this binding level. (Not actually implemented this way, - unfortunately.) */ + /* Nonzero if this level is for storing the decls for template + parameters and generic decls; these decls will be discarded and + replaced with a TEMPLATE_DECL. */ unsigned pseudo_global : 1; /* This is set for a namespace binding level. */ unsigned namespace_p : 1; - /* True if this level is that of a for-statement. */ + /* True if this level is that of a for-statement where we need to + worry about ambiguous (ARM or ANSI) scope rules. */ unsigned is_for_scope : 1; - /* One bit left for this word. */ + /* Two bits left for this word. */ #if defined(DEBUG_CP_BINDING_LEVELS) /* Binding depth at which this level began. */ @@ -687,7 +777,7 @@ pop_binding_level () if (global_binding_level) { - /* cannot pop a level, if there are none left to pop. */ + /* Cannot pop a level, if there are none left to pop. */ if (current_binding_level == global_binding_level) my_friendly_abort (123); } @@ -699,14 +789,10 @@ pop_binding_level () (is_class_level) ? "class" : "block", current_binding_level, lineno); if (is_class_level != (current_binding_level == class_binding_level)) -#if 0 /* XXX Don't abort when we're watching how things are being managed. */ - abort (); -#else - { - indent (); - fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); - } -#endif + { + indent (); + fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); + } is_class_level = 0; #endif /* defined(DEBUG_CP_BINDING_LEVELS) */ { @@ -735,7 +821,7 @@ suspend_binding_level () if (global_binding_level) { - /* cannot suspend a level, if there are none left to suspend. */ + /* Cannot suspend a level, if there are none left to suspend. */ if (current_binding_level == global_binding_level) my_friendly_abort (123); } @@ -747,24 +833,14 @@ suspend_binding_level () (is_class_level) ? "class" : "block", current_binding_level, lineno); if (is_class_level != (current_binding_level == class_binding_level)) -#if 0 /* XXX Don't abort when we're watching how things are being managed. */ - abort (); -#else - { - indent (); - fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); - } -#endif + { + indent (); + fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); + } is_class_level = 0; #endif /* defined(DEBUG_CP_BINDING_LEVELS) */ { - register struct binding_level *level = current_binding_level; current_binding_level = current_binding_level->level_chain; -#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */ - if (level->binding_depth != binding_depth) - abort (); -#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ - class_binding_level = current_binding_level; if (class_binding_level->parm_flag != 2) class_binding_level = 0; @@ -773,33 +849,15 @@ suspend_binding_level () } } -void +static void resume_binding_level (b) struct binding_level *b; { - if (class_binding_level) - { -#if 1 - /* These are here because we cannot deal with shadows yet. */ - sorry ("cannot resume a namespace inside class"); - return; -#else - b->level_chain = class_binding_level; - class_binding_level = (struct binding_level *)0; -#endif - } - else - { -#if 1 - /* These are here because we cannot deal with shadows yet. */ - if (b->level_chain != current_binding_level) - { - sorry ("cannot resume a namespace inside a different namespace"); - return; - } -#endif - b->level_chain = current_binding_level; - } + /* Resuming binding levels is meant only for namespaces, + and those cannot nest into classes. */ + my_friendly_assert(!class_binding_level, 386); + /* Also, resuming a non-directly nested namespace is a no-no. */ + my_friendly_assert(b->level_chain == current_binding_level, 386); current_binding_level = b; #if defined(DEBUG_CP_BINDING_LEVELS) b->binding_depth = binding_depth; @@ -811,6 +869,16 @@ resume_binding_level (b) #endif /* defined(DEBUG_CP_BINDING_LEVELS) */ } +/* Create a new `struct binding_level'. */ + +static +struct binding_level * +make_binding_level () +{ + /* NOSTRICT */ + return (struct binding_level *) xmalloc (sizeof (struct binding_level)); +} + /* Nonzero if we are currently in the global binding level. */ int @@ -821,26 +889,20 @@ global_bindings_p () /* 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. */ + binding level. + Since there are no non-toplevel namespace levels, this really + means any namespace or pseudo-global level. */ int toplevel_bindings_p () { - struct binding_level *b = current_binding_level; - - while (1) - { - if (b == global_binding_level) - return 1; - if (! b->namespace_p) - return 0; - b=b->level_chain; - } + return current_binding_level->namespace_p + || current_binding_level->pseudo_global; } /* Nonzero if this is a namespace scope. */ -int +static int namespace_bindings_p () { return current_binding_level->namespace_p; @@ -873,24 +935,12 @@ declare_parm_level () } void -declare_uninstantiated_type_level () -{ - current_binding_level->accept_any = 1; -} - -int -uninstantiated_type_level_p () -{ - return current_binding_level->accept_any; -} - -void declare_pseudo_global_level () { current_binding_level->pseudo_global = 1; } -void +static void declare_namespace_level () { current_binding_level->namespace_p = 1; @@ -939,15 +989,15 @@ pushlevel (tag_transparent) } else { - /* Create a new `struct binding_level'. */ - newlevel = (struct binding_level *) xmalloc (sizeof (struct binding_level)); + newlevel = make_binding_level (); } + push_binding_level (newlevel, tag_transparent, keep_next_level_flag); GNU_xref_start_scope ((HOST_WIDE_INT) newlevel); keep_next_level_flag = 0; } -int +void note_level_for_for () { current_binding_level->is_for_scope = 1; @@ -1000,7 +1050,6 @@ poplevel (keep, reverse, functionbody) Put it into forward order, just for cleanliness. */ tree decls; int tmp = functionbody; - int implicit_try_block = current_binding_level->parm_flag == 3; int real_functionbody = current_binding_level->keep == 2 ? ((functionbody = 0), tmp) : functionbody; tree tags = functionbody >= 0 ? current_binding_level->tags : 0; @@ -1012,41 +1061,11 @@ poplevel (keep, reverse, functionbody) GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level, (HOST_WIDE_INT) current_binding_level->level_chain, current_binding_level->parm_flag, - current_binding_level->keep, - current_binding_level->tag_transparent); + current_binding_level->keep); if (current_binding_level->keep == 1) keep = 1; - /* This warning is turned off because it causes warnings for - declarations like `extern struct foo *x'. */ -#if 0 - /* Warn about incomplete structure types in this level. */ - for (link = tags; link; link = TREE_CHAIN (link)) - if (TYPE_SIZE (TREE_VALUE (link)) == NULL_TREE) - { - tree type = TREE_VALUE (link); - char *errmsg; - switch (TREE_CODE (type)) - { - case RECORD_TYPE: - errmsg = "`struct %s' incomplete in scope ending here"; - break; - case UNION_TYPE: - errmsg = "`union %s' incomplete in scope ending here"; - break; - case ENUMERAL_TYPE: - errmsg = "`enum %s' incomplete in scope ending here"; - 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, TYPE_NAME_STRING (type)); - } -#endif /* 0 */ - /* 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. */ @@ -1092,15 +1111,35 @@ poplevel (keep, reverse, functionbody) block = make_node (BLOCK); if (block != NULL_TREE) { - BLOCK_VARS (block) = decls; - BLOCK_TYPE_TAGS (block) = tags; - BLOCK_SUBBLOCKS (block) = subblocks; - /* If we created the block earlier on, and we are just diddling it now, - then it already should have a proper BLOCK_END_NOTE value associated - with it, so avoid trashing that. Otherwise, for a new block, install - a new BLOCK_END_NOTE value. */ - if (! block_previously_created) - remember_end_note (block); + if (block_previously_created) + { + if (decls || tags || subblocks) + { + if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block)) + { + warning ("internal compiler error: debugging info corrupted"); + } + BLOCK_VARS (block) = decls; + BLOCK_TYPE_TAGS (block) = tags; + + /* We can have previous subblocks and new subblocks when + doing fixup_gotos with complex cleanups. We chain the new + subblocks onto the end of any pre-existing subblocks. */ + BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block), + subblocks); + } + /* If we created the block earlier on, and we are just + diddling it now, then it already should have a proper + BLOCK_END_NOTE value associated with it. */ + } + else + { + 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. */ + remember_end_note (block); + } } /* In each subblock, record that this is its superior. */ @@ -1111,26 +1150,38 @@ poplevel (keep, reverse, functionbody) /* Clear out the meanings of the local variables of this level. */ - for (link = current_binding_level->dead_vars_from_for; - link != NULL_TREE; link = TREE_CHAIN (link)) - { - if (DECL_DEAD_FOR_LOCAL (link)) - { - tree id = DECL_NAME (link); - if (IDENTIFIER_LOCAL_VALUE (id) == link) - IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link); - } - } - if (current_binding_level->is_for_scope && flag_new_for_scope == 1) { + struct binding_level *outer = current_binding_level->level_chain; for (link = decls; link; link = TREE_CHAIN (link)) { 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. */ + + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + { + tree id = TREE_PURPOSE (link); + tree decl = IDENTIFIER_LOCAL_VALUE (id); + + 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; + } + else + IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link); } } - else + else /* Not special for scope. */ { for (link = decls; link; link = TREE_CHAIN (link)) { @@ -1148,50 +1199,42 @@ poplevel (keep, reverse, functionbody) IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; } } - } - /* Restore all name-meanings of the outer levels - that were shadowed by this level. */ + /* Restore all name-meanings of the outer levels + that were shadowed by this level. */ - if (current_binding_level->is_for_scope && flag_new_for_scope == 1) - { - struct binding_level *outer = current_binding_level->level_chain; - for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + 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 + + 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. */ + + link = current_binding_level->dead_vars_from_for; + for (; link != NULL_TREE; link = TREE_CHAIN (link)) { - tree id = TREE_PURPOSE (link); - tree decl = IDENTIFIER_LOCAL_VALUE (id); - if (DECL_DEAD_FOR_LOCAL (decl)) - DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link); - else - IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link); + tree id = DECL_NAME (link); + if (IDENTIFIER_LOCAL_VALUE (id) == link) + IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link); } - /* Save declarations made in a 'for' statement so we can support pre-ANSI - 'for' scoping semantics. */ - - /* We append the current names of for-variables to those from previous - declarations, so that when we get around to do an poplevel - on the OUTER level, we restore the any shadowed readl bindings. - Note that the new names are put first on the combined list, - so they get to be restored first. This is important if there are - two for-loops using the same for-variable in the same block. - The binding we really want restored is whatever binding was shadowed - by the *first* for-variable, not the binding shadowed by the - second for-variable (which would be the first for-variable). */ - outer->dead_vars_from_for - = chainon (current_binding_level->names, outer->dead_vars_from_for); - } - else - { - 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)); } - 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)) - IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); /* If the level being exited is the top level of a function, check over all the labels. */ @@ -1238,12 +1281,12 @@ poplevel (keep, reverse, functionbody) level_chain = current_binding_level->level_chain; if (level_chain) { - tree labels; - for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels)) - if (TREE_TYPE (labels) == (tree)current_binding_level) + struct named_label_list *labels; + for (labels = named_label_uses; labels; labels = labels->next) + if (labels->binding_level == current_binding_level) { - TREE_TYPE (labels) = (tree)level_chain; - TREE_PURPOSE (labels) = level_chain->names; + labels->binding_level = level_chain; + labels->names_in_scope = level_chain->names; } } } @@ -1277,11 +1320,6 @@ poplevel (keep, reverse, functionbody) /* Take care of compiler's internal binding structures. */ if (tmp == 2) { -#if 0 - /* We did not call push_momentary for this - binding contour, so there is nothing to pop. */ - pop_momentary (); -#endif expand_end_bindings (getdecls (), keep, 1); /* Each and every BLOCK node created here in `poplevel' is important (e.g. for proper debugging information) so if we created one @@ -1299,31 +1337,6 @@ poplevel (keep, reverse, functionbody) return block; } -/* Resume a binding level for a namespace. */ -void -resume_level (b) - struct binding_level *b; -{ - tree decls, link; - - resume_binding_level (b); - - /* Resume the variable caches. */ - decls = current_binding_level->names; - - /* Restore the meanings of the local variables of this level. */ - - for (link = decls; link; link = TREE_CHAIN (link)) - { - if (DECL_NAME (link) != NULL_TREE) - IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = link; - - /* If this is a TYPE_DECL, push it into the type value slot. */ - if (TREE_CODE (link) == TYPE_DECL) - SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (link), TREE_TYPE (link)); - } -} - /* 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. */ @@ -1361,15 +1374,6 @@ insert_block (block) = chainon (current_binding_level->blocks, block); } -/* Add BLOCK to the current list of blocks for this binding contour. */ -void -add_block_current_level (block) - tree block; -{ - current_binding_level->blocks - = chainon (current_binding_level->blocks, block); -} - /* Set the BLOCK node for the innermost scope (the one we are currently in). */ @@ -1381,6 +1385,7 @@ set_block (block) } /* Do a pushlevel for class declarations. */ + void pushlevel_class () { @@ -1398,8 +1403,7 @@ pushlevel_class () } else { - /* Create a new `struct binding_level'. */ - newlevel = (struct binding_level *) xmalloc (sizeof (struct binding_level)); + newlevel = make_binding_level (); } #if defined(DEBUG_CP_BINDING_LEVELS) @@ -1423,6 +1427,7 @@ pushlevel_class () /* ...and a poplevel for class declarations. FORCE is used to force clearing out of CLASS_VALUEs after a class definition. */ + tree poplevel_class (force) int force; @@ -1449,22 +1454,24 @@ poplevel_class (force) else /* Remember to save what IDENTIFIER's were bound in this scope so we can recover from cache misses. */ - previous_class_values = class_binding_level->class_shadowed; + { + previous_class_type = current_class_type; + previous_class_values = class_binding_level->class_shadowed; + } for (shadowed = level->type_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) - IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); + SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (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, - class_binding_level->tag_transparent); + class_binding_level->keep); if (class_binding_level->parm_flag != 2) class_binding_level = (struct binding_level *)0; - /* Now, pop out of the the binding level which we created up in the + /* Now, pop out of the binding level which we created up in the `pushlevel_class' routine. */ #if defined(DEBUG_CP_BINDING_LEVELS) is_class_level = 1; @@ -1476,8 +1483,8 @@ poplevel_class (force) } /* For debugging. */ -int no_print_functions = 0; -int no_print_builtins = 0; +static int no_print_functions = 0; +static int no_print_builtins = 0; void print_binding_level (lvl) @@ -1502,11 +1509,11 @@ print_binding_level (lvl) /* We can probably fit 3 names to a line? */ for (t = lvl->names; t; t = TREE_CHAIN (t)) { - if (no_print_functions && (TREE_CODE(t) == FUNCTION_DECL)) + if (no_print_functions && (TREE_CODE (t) == FUNCTION_DECL)) continue; if (no_print_builtins - && (TREE_CODE(t) == TYPE_DECL) - && (!strcmp(DECL_SOURCE_FILE(t),""))) + && (TREE_CODE (t) == TYPE_DECL) + && (!strcmp (DECL_SOURCE_FILE (t),""))) continue; /* Function decls tend to have longer names. */ @@ -1521,7 +1528,7 @@ print_binding_level (lvl) i = len; } print_node_brief (stderr, "", t, 0); - if (TREE_CODE (t) == ERROR_MARK) + if (t == error_mark_node) break; } if (i) @@ -1585,17 +1592,7 @@ print_binding_level (lvl) fprintf (stderr, " type-shadowed:"); for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t)) { -#if 0 - fprintf (stderr, "\n\t"); - print_node_brief (stderr, "<", TREE_PURPOSE (t), 0); - if (TREE_VALUE (t)) - print_node_brief (stderr, " ", TREE_VALUE (t), 0); - else - fprintf (stderr, " (none)"); - fprintf (stderr, ">"); -#else fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); -#endif } fprintf (stderr, "\n"); } @@ -1643,148 +1640,247 @@ print_binding_stack () print_binding_level (global_binding_level); } -extern char * first_global_object_name; +/* Namespace binding access routines: The namespace_bindings field of + the identifier is polymorphic, with three possible values: + NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node + indicating the BINDING_VALUE of global_namespace. */ + +/* Check whether the a binding for the name to scope is known. + Assumes that the bindings of the name are already a list + of bindings. Returns the binding found, or NULL_TREE. */ -/* Get a unique name for each call to this routine for unnamed namespaces. - Mostly copied from get_file_function_name. */ static tree -get_unique_name () +find_binding (name, scope) + tree name; + tree scope; { - static int temp_name_counter = 0; - char *buf; - register char *p; - - if (first_global_object_name) - p = first_global_object_name; - else if (main_input_filename) - p = main_input_filename; - else - p = input_filename; + tree iter, prev = NULL_TREE; -#define UNNAMED_NAMESPACE_FORMAT "__%s_%d" + scope = ORIGINAL_NAMESPACE (scope); + + for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter; + iter = TREE_CHAIN (iter)) + { + my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374); + if (BINDING_SCOPE (iter) == scope) + { + /* Move binding found to the fron of the list, so + subsequent lookups will find it faster. */ + if (prev) + { + TREE_CHAIN (prev) = TREE_CHAIN (iter); + TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name); + IDENTIFIER_NAMESPACE_BINDINGS (name) = iter; + } + return iter; + } + prev = iter; + } + return NULL_TREE; +} - buf = (char *) alloca (sizeof (UNNAMED_NAMESPACE_FORMAT) + strlen (p)); +/* Always returns a binding for name in scope. If the + namespace_bindings is not a list, convert it to one first. + If no binding is found, make a new one. */ - sprintf (buf, UNNAMED_NAMESPACE_FORMAT, p, temp_name_counter++); +tree +binding_for_name (name, scope) + tree name; + tree scope; +{ + tree b = IDENTIFIER_NAMESPACE_BINDINGS (name); + tree result; - /* Don't need to pull weird characters out of global names. */ - if (p != first_global_object_name) + scope = ORIGINAL_NAMESPACE (scope); + + if (b && TREE_CODE (b) != CPLUS_BINDING) { - for (p = buf+11; *p; p++) - if (! ((*p >= '0' && *p <= '9') -#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */ -#ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */ - || *p == '.' -#endif -#endif -#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */ - || *p == '$' -#endif -#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */ - || *p == '.' -#endif - || (*p >= 'A' && *p <= 'Z') - || (*p >= 'a' && *p <= 'z'))) - *p = '_'; + /* Get rid of optimization for global scope. */ + IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE; + BINDING_VALUE (binding_for_name (name, global_namespace)) = b; + b = IDENTIFIER_NAMESPACE_BINDINGS (name); } + if (b && (result = find_binding (name, scope))) + return result; + /* Not found, make a new permanent one. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + result = make_node (CPLUS_BINDING); + TREE_CHAIN (result) = b; + IDENTIFIER_NAMESPACE_BINDINGS (name) = result; + BINDING_SCOPE (result) = scope; + BINDING_TYPE (result) = NULL_TREE; + BINDING_VALUE (result) = NULL_TREE; + pop_obstacks (); + return result; +} - return get_identifier (buf); +/* Return the binding value for name in scope, considering that + namespace_binding may or may not be a list of CPLUS_BINDINGS. */ + +tree +namespace_binding (name, scope) + tree name; + tree scope; +{ + tree b = IDENTIFIER_NAMESPACE_BINDINGS (name); + if (b == NULL_TREE) + return NULL_TREE; + if (scope == NULL_TREE) + scope = global_namespace; + if (TREE_CODE (b) != CPLUS_BINDING) + return (scope == global_namespace) ? b : NULL_TREE; + name = find_binding (name,scope); + if (name == NULL_TREE) + return name; + return BINDING_VALUE (name); } -/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we - select a name that is unique to this compilation unit. */ +/* Set the binding value for name in scope. If modifying the binding + of global_namespace is attempted, try to optimize it. */ + void -push_namespace (name) +set_namespace_binding (name, scope, val) tree name; + tree scope; + tree val; { - extern tree current_namespace; - tree old_id = get_namespace_id (); - char *buf; - tree d = make_node (NAMESPACE_DECL); + tree b; - if (! name) + if (scope == NULL_TREE) + scope = global_namespace; + + if (scope == global_namespace) { - /* Create a truly ugly name! */ - name = get_unique_name (); + b = IDENTIFIER_NAMESPACE_BINDINGS (name); + if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING) + { + IDENTIFIER_NAMESPACE_BINDINGS (name) = val; + return; + } } + b = binding_for_name (name, scope); + BINDING_VALUE (b) = val; +} - DECL_NAME (d) = name; - DECL_ASSEMBLER_NAME (d) = name; - /* pushdecl wants to check the size of it to see if it is incomplete... */ - TREE_TYPE (d) = void_type_node; - /* Mark them as external, so redeclaration_error_message doesn't think - they are duplicates. */ - DECL_EXTERNAL (d) = 1; - d = pushdecl (d); +/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we + select a name that is unique to this compilation unit. */ - if (NAMESPACE_LEVEL (d) == 0) - { - /* This is new for this compilation unit. */ - pushlevel (0); - declare_namespace_level (); - NAMESPACE_LEVEL (d) = (tree)current_binding_level; +void +push_namespace (name) + tree name; +{ + tree d; + int need_new = 1; + int implicit_use = 0; + int global = 0; + if (!global_namespace) + { + /* This must be ::. */ + my_friendly_assert (name == get_identifier ("::"), 377); + global = 1; + } + else if (!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; + d = IDENTIFIER_NAMESPACE_VALUE (name); + if (d) + /* Reopening anonymous namespace. */ + need_new = 0; + implicit_use = 1; + } + else if (current_namespace == global_namespace + && name == DECL_NAME (std_node)) + { + in_std++; + return; } else { - resume_level ((struct binding_level*)NAMESPACE_LEVEL (d)); + /* Check whether this is an extended namespace definition. */ + d = IDENTIFIER_NAMESPACE_VALUE (name); + if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL) + { + need_new = 0; + if (DECL_NAMESPACE_ALIAS (d)) + { + cp_error ("namespace alias `%D' not allowed here, assuming `%D'", + d, DECL_NAMESPACE_ALIAS (d)); + d = DECL_NAMESPACE_ALIAS (d); + } + } + } + + if (need_new) + { + /* Make a new namespace, binding the name to it. */ + d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); + /* The global namespace is not pushed, and the global binding + level is set elsewhere. */ + if (!global) + { + d = pushdecl (d); + pushlevel (0); + declare_namespace_level (); + NAMESPACE_LEVEL (d) = current_binding_level; + } } + else + resume_binding_level (NAMESPACE_LEVEL (d)); - /* This code is just is bit old now... */ - current_namespace = tree_cons (NULL_TREE, name, current_namespace); - buf = (char *) alloca (4 + (old_id ? IDENTIFIER_LENGTH (old_id) : 0) - + IDENTIFIER_LENGTH (name)); - sprintf (buf, "%s%s", old_id ? IDENTIFIER_POINTER (old_id) : "", - IDENTIFIER_POINTER (name)); - TREE_PURPOSE (current_namespace) = get_identifier (buf); + if (implicit_use) + do_using_directive (d); + /* Enter the name space. */ + current_namespace = d; } /* Pop from the scope of the current namespace. */ + void pop_namespace () { - extern tree current_namespace; - tree decls, link; - current_namespace = TREE_CHAIN (current_namespace); - - /* Just in case we get out of sync. */ - if (! namespace_bindings_p ()) - poplevel (0, 0, 0); + if (current_namespace == global_namespace) + { + my_friendly_assert (in_std>0, 980421); + in_std--; + return; + } + current_namespace = CP_DECL_CONTEXT (current_namespace); + /* The binding level is not popped, as it might be re-opened later. */ + suspend_binding_level (); +} - decls = current_binding_level->names; +/* Concatenate the binding levels of all namespaces. */ - /* Clear out the meanings of the local variables of this level. */ +void +cat_namespace_levels() +{ + tree current; + tree last; + struct binding_level *b; - for (link = decls; link; link = TREE_CHAIN (link)) + 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 (DECL_NAME (link) != NULL_TREE) + if (TREE_CODE (current) != NAMESPACE_DECL + || DECL_NAMESPACE_ALIAS (current)) + continue; + if (!DECL_LANG_SPECIFIC (current)) { - /* 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; + /* 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; } - - /* 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)) - IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); - - /* suspend a level. */ - suspend_binding_level (); } /* Subroutines for reverting temporarily to top-level for instantiation @@ -1795,107 +1891,166 @@ pop_namespace () struct saved_scope { struct binding_level *old_binding_level; tree old_bindings; + tree old_namespace; struct saved_scope *prev; tree class_name, class_type, function_decl; - tree base_init_list, member_init_list; struct binding_level *class_bindings; - tree previous_class_type; tree *lang_base, *lang_stack, lang_name; int lang_stacksize; - tree named_labels; + int minimal_parse_mode; + tree last_function_parms; + tree template_parms; + HOST_WIDE_INT processing_template_decl; + tree previous_class_type, previous_class_values; + int processing_specialization; + int processing_explicit_instantiation; }; static struct saved_scope *current_saved_scope; -extern tree prev_class_type; + +/* A chain of the binding vecs created by store_bindings. We create a + whole bunch of these during compilation, on permanent_obstack, so we + can't just throw them away. */ +static tree free_binding_vecs; + +static tree +store_bindings (names, old_bindings) + tree names, old_bindings; +{ + tree t; + for (t = names; t; t = TREE_CHAIN (t)) + { + tree binding, t1, id; + + if (TREE_CODE (t) == TREE_LIST) + id = TREE_PURPOSE (t); + else + id = DECL_NAME (t); + + if (!id + || (!IDENTIFIER_LOCAL_VALUE (id) + && !IDENTIFIER_CLASS_VALUE (id))) + continue; + + for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1)) + if (TREE_VEC_ELT (t1, 0) == id) + goto skip_it; + + if (free_binding_vecs) + { + binding = free_binding_vecs; + free_binding_vecs = TREE_CHAIN (free_binding_vecs); + } + else + binding = make_tree_vec (4); + + if (id) + { + 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, 3) = IDENTIFIER_CLASS_VALUE (id); + IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE; + IDENTIFIER_CLASS_VALUE (id) = NULL_TREE; + } + TREE_CHAIN (binding) = old_bindings; + old_bindings = binding; + skip_it: + ; + } + return old_bindings; +} void -push_to_top_level () +maybe_push_to_top_level (pseudo) + int pseudo; { extern int current_lang_stacksize; - struct saved_scope *s = - (struct saved_scope *) xmalloc (sizeof (struct saved_scope)); - struct binding_level *b = current_binding_level; + struct saved_scope *s + = (struct saved_scope *) xmalloc (sizeof (struct saved_scope)); + struct binding_level *b = inner_binding_level; tree old_bindings = NULL_TREE; + if (current_function_decl) + push_cp_function_context (NULL_TREE); + + if (previous_class_type) + old_bindings = store_bindings (previous_class_values, old_bindings); + /* Have to include global_binding_level, because class-level decls aren't listed anywhere useful. */ for (; b; b = b->level_chain) { tree t; - if (b == global_binding_level) - continue; - - for (t = b->names; t; t = TREE_CHAIN (t)) - { - tree binding, t1, t2 = t; - tree id = DECL_ASSEMBLER_NAME (t2); + /* Template IDs are inserted into the global level. If they were + inserted into namespace level, finish_file wouldn't find them + when doing pending instantiations. Therefore, don't stop at + namespace level, but continue until :: . */ + if (b == global_binding_level || (pseudo && b->pseudo_global)) + break; - if (!id - || (!IDENTIFIER_LOCAL_VALUE (id) - && !IDENTIFIER_CLASS_VALUE (id))) - continue; + old_bindings = store_bindings (b->names, old_bindings); + /* We also need to check class_shadowed to save class-level type + bindings, since pushclass doesn't fill in b->names. */ + if (b->parm_flag == 2) + old_bindings = store_bindings (b->class_shadowed, old_bindings); - for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1)) - if (TREE_VEC_ELT (t1, 0) == id) - goto skip_it; - - binding = make_tree_vec (4); - if (id) - { - my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135); - TREE_VEC_ELT (binding, 0) = id; - TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id); - TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id); - TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id); - IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE; - IDENTIFIER_CLASS_VALUE (id) = NULL_TREE; - } - TREE_CHAIN (binding) = old_bindings; - old_bindings = binding; - skip_it: - ; - } /* Unwind type-value slots back to top level. */ for (t = b->type_shadowed; t; t = TREE_CHAIN (t)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t)); } - /* Clear out class-level bindings cache. */ - if (current_binding_level == global_binding_level - && previous_class_type != NULL_TREE) - { - popclass (-1); - previous_class_type = NULL_TREE; - } s->old_binding_level = current_binding_level; - current_binding_level = global_binding_level; + current_binding_level = b; + s->old_namespace = current_namespace; s->class_name = current_class_name; s->class_type = current_class_type; s->function_decl = current_function_decl; - s->base_init_list = current_base_init_list; - s->member_init_list = current_member_init_list; s->class_bindings = class_binding_level; - s->previous_class_type = previous_class_type; s->lang_stack = current_lang_stack; s->lang_base = current_lang_base; s->lang_stacksize = current_lang_stacksize; s->lang_name = current_lang_name; - s->named_labels = named_labels; + s->minimal_parse_mode = minimal_parse_mode; + s->last_function_parms = last_function_parms; + s->template_parms = current_template_parms; + s->processing_template_decl = processing_template_decl; + s->previous_class_type = previous_class_type; + s->previous_class_values = previous_class_values; + s->processing_specialization = processing_specialization; + s->processing_explicit_instantiation = processing_explicit_instantiation; + current_class_name = current_class_type = NULL_TREE; current_function_decl = NULL_TREE; class_binding_level = (struct binding_level *)0; - previous_class_type = NULL_TREE; current_lang_stacksize = 10; current_lang_stack = current_lang_base = (tree *) xmalloc (current_lang_stacksize * sizeof (tree)); current_lang_name = lang_name_cplusplus; strict_prototype = strict_prototypes_lang_cplusplus; named_labels = NULL_TREE; + shadowed_labels = NULL_TREE; + minimal_parse_mode = 0; + previous_class_type = previous_class_values = NULL_TREE; + processing_specialization = 0; + processing_explicit_instantiation = 0; + current_template_parms = NULL_TREE; + processing_template_decl = 0; + current_namespace = global_namespace; s->prev = current_saved_scope; s->old_bindings = old_bindings; current_saved_scope = s; + + push_obstacks (&permanent_obstack, &permanent_obstack); +} + +void +push_to_top_level () +{ + maybe_push_to_top_level (0); } void @@ -1905,28 +2060,36 @@ pop_from_top_level () struct saved_scope *s = current_saved_scope; tree t; + /* Clear out class-level bindings cache. */ if (previous_class_type) - previous_class_type = NULL_TREE; + { + popclass (-1); + previous_class_type = NULL_TREE; + } + + pop_obstacks (); current_binding_level = s->old_binding_level; current_saved_scope = s->prev; - for (t = s->old_bindings; t; t = TREE_CHAIN (t)) + for (t = s->old_bindings; t; ) { + tree save = t; tree id = TREE_VEC_ELT (t, 0); if (id) { - IDENTIFIER_TYPE_VALUE (id) = TREE_VEC_ELT (t, 1); + SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1)); IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2); IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3); } + t = TREE_CHAIN (t); + TREE_CHAIN (save) = free_binding_vecs; + free_binding_vecs = save; } + current_namespace = s->old_namespace; current_class_name = s->class_name; current_class_type = s->class_type; - current_base_init_list = s->base_init_list; - current_member_init_list = s->member_init_list; current_function_decl = s->function_decl; class_binding_level = s->class_bindings; - previous_class_type = s->previous_class_type; free (current_lang_base); current_lang_base = s->lang_base; current_lang_stack = s->lang_stack; @@ -1936,9 +2099,19 @@ pop_from_top_level () strict_prototype = strict_prototypes_lang_cplusplus; else if (current_lang_name == lang_name_c) strict_prototype = strict_prototypes_lang_c; - named_labels = s->named_labels; + minimal_parse_mode = s->minimal_parse_mode; + last_function_parms = s->last_function_parms; + current_template_parms = s->template_parms; + processing_template_decl = s->processing_template_decl; + previous_class_type = s->previous_class_type; + previous_class_values = s->previous_class_values; + processing_specialization = s->processing_specialization; + processing_explicit_instantiation = s->processing_explicit_instantiation; free (s); + + if (current_function_decl) + pop_cp_function_context (NULL_TREE); } /* Push a definition of struct, union or enum tag "name". @@ -1948,7 +2121,7 @@ pop_from_top_level () Note that the definition may really be just a forward reference. In that case, the TYPE_SIZE will be a NULL_TREE. - C++ gratuitously puts all these tags in the name space. */ + C++ gratuitously puts all these tags in the name space. */ /* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID, record the shadowed value for this binding contour. TYPE is @@ -1960,16 +2133,25 @@ set_identifier_type_value_with_scope (id, type, b) tree type; struct binding_level *b; { - if (b != global_binding_level) + if (!b->namespace_p) { - tree old_type_value = IDENTIFIER_TYPE_VALUE (id); + /* Shadow the marker, not the real thing, so that the marker + gets restored later. */ + tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id); b->type_shadowed = tree_cons (id, old_type_value, b->type_shadowed); } + else + { + tree binding = binding_for_name (id, current_namespace); + BINDING_TYPE (binding) = type; + /* Store marker instead of real type. */ + type = global_type_node; + } 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 inner_binding_level. */ void set_identifier_type_value (id, type) @@ -1979,59 +2161,50 @@ set_identifier_type_value (id, type) set_identifier_type_value_with_scope (id, type, inner_binding_level); } -/* Subroutine "set_nested_typename" builds the nested-typename of - the type decl in question. (Argument CLASSNAME can actually be - a function as well, if that's the smallest containing scope.) */ - static void -set_nested_typename (decl, classname, name, type) - tree decl, classname, name, type; +set_identifier_local_value_with_scope (id, val, b) + tree id, val; + struct binding_level *b; { - char *buf; - my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136); + tree oldlocal; + my_friendly_assert (! b->namespace_p, 980716); - /* No need to do this for anonymous names, since they're unique. */ - if (ANON_AGGRNAME_P (name)) - { - DECL_NESTED_TYPENAME (decl) = name; - return; - } + oldlocal = IDENTIFIER_LOCAL_VALUE (id); + b->shadowed = tree_cons (id, oldlocal, b->shadowed); + IDENTIFIER_LOCAL_VALUE (id) = val; +} - if (classname == NULL_TREE) - classname = get_identifier (""); +void +set_identifier_local_value (id, val) + tree id, val; +{ + set_identifier_local_value_with_scope (id, val, current_binding_level); +} - my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137); - my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138); - buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname) - + IDENTIFIER_LENGTH (name)); - sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname), - IDENTIFIER_POINTER (name)); - DECL_NESTED_TYPENAME (decl) = get_identifier (buf); - TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1; +/* Return the type associated with id. */ - /* Create an extra decl so that the nested name will have a type value - where appropriate. */ - { - tree nested, type_decl; - nested = DECL_NESTED_TYPENAME (decl); - type_decl = build_decl (TYPE_DECL, nested, type); - DECL_NESTED_TYPENAME (type_decl) = nested; - SET_DECL_ARTIFICIAL (type_decl); - /* Mark the TYPE_DECL node created just above as a gratuitous one so that - dwarfout.c will know not to generate a TAG_typedef DIE for it, and - sdbout.c won't try to output a .def for "::foo". */ - DECL_IGNORED_P (type_decl) = 1; - - /* Remove this when local classes are fixed. */ - SET_IDENTIFIER_TYPE_VALUE (nested, type); - - pushdecl_nonclass_level (type_decl); - } +tree +identifier_type_value (id) + tree id; +{ + /* There is no type with that name, anywhere. */ + if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE) + return NULL_TREE; + /* This is not the type marker, but the real thing. */ + if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node) + return REAL_IDENTIFIER_TYPE_VALUE (id); + /* Have to search for it. It must be on the global level, now. + Ask lookup_name not to return non-types. */ + id = lookup_name_real (id, 2, 1, 0); + if (id) + return TREE_TYPE (id); + return NULL_TREE; } /* Pop off extraneous binding levels left over due to syntax errors. We don't pop past namespaces, as they might be valid. */ + void pop_everything () { @@ -2050,41 +2223,10 @@ pop_everything () #endif } -#if 0 /* not yet, should get fixed properly later */ -/* Create a TYPE_DECL node with the correct DECL_ASSEMBLER_NAME. - Other routines shouldn't use build_decl directly; they'll produce - incorrect results with `-g' unless they duplicate this code. - - This is currently needed mainly for dbxout.c, but we can make - use of it in method.c later as well. */ -tree -make_type_decl (name, type) - tree name, type; -{ - tree decl, id; - decl = build_decl (TYPE_DECL, name, type); - if (TYPE_NAME (type) == name) - /* Class/union/enum definition, or a redundant typedef for same. */ - { - id = get_identifier (build_overload_name (type, 1, 1)); - DECL_ASSEMBLER_NAME (decl) = id; - } - else if (TYPE_NAME (type) != NULL_TREE) - /* Explicit typedef, or implicit typedef for template expansion. */ - DECL_ASSEMBLER_NAME (decl) = DECL_ASSEMBLER_NAME (TYPE_NAME (type)); - else - { - /* XXX: Typedef for unnamed struct; some other situations. - TYPE_NAME is null; what's right here? */ - } - return decl; -} -#endif - /* Push a tag name NAME for struct/class/union/enum type TYPE. - Normally put into into the inner-most non-tag-transparent scope, + 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. - The latter is needed for implicit declarations. */ + The latter is needed for implicit declarations. */ void pushtag (name, type, globalize) @@ -2108,117 +2250,124 @@ pushtag (name, type, globalize) if (name) { context = type ? TYPE_CONTEXT (type) : NULL_TREE; - if (! context && ! globalize) - context = current_scope (); + 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 0 - /* Record the identifier as the type's name if it has none. */ - if (TYPE_NAME (type) == NULL_TREE) - TYPE_NAME (type) = name; -#endif - + if (!context) + context = current_namespace; + /* Do C++ gratuitous typedefing. */ if (IDENTIFIER_TYPE_VALUE (name) != type) { - register tree d; - int newdecl = 0; - - if (b->parm_flag != 2 - || TYPE_SIZE (current_class_type) != NULL_TREE) - { - d = lookup_nested_type (type, c_decl); - - if (d == NULL_TREE) - { - newdecl = 1; -#if 0 /* not yet, should get fixed properly later */ - d = make_type_decl (name, type); -#else - d = build_decl (TYPE_DECL, name, type); - DECL_ASSEMBLER_NAME (d) = current_namespace_id (DECL_ASSEMBLER_NAME (d)); -#endif - SET_DECL_ARTIFICIAL (d); -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) - { - /* Mark the TYPE_DECL node we created just above as an - gratuitous one. We need to do this so that dwarfout.c - will understand that it is not supposed to output a - TAG_typedef DIE for it. */ - DECL_IGNORED_P (d) = 1; - } -#endif /* DWARF_DEBUGGING_INFO */ - set_identifier_type_value_with_scope (name, type, b); - } - else - d = TYPE_NAME (d); - - TYPE_NAME (type) = d; + register tree d = NULL_TREE; + int newdecl = 0, in_class = 0; - /* If it is anonymous, then we are called from pushdecl, - and we don't want to infinitely recurse. */ - if (! ANON_AGGRNAME_P (name)) - { - if (b->parm_flag == 2) - d = pushdecl_class_level (d); - else - d = pushdecl_with_scope (d, b); - } - } + if ((b->pseudo_global && b->level_chain->parm_flag == 2) + || b->parm_flag == 2) + in_class = 1; else + d = lookup_nested_type (type, c_decl); + + if (d == NULL_TREE) { - /* Make nested declarations go into class-level scope. */ newdecl = 1; d = build_decl (TYPE_DECL, name, type); + if (current_lang_name == lang_name_java) + TYPE_FOR_JAVA (type) = 1; SET_DECL_ARTIFICIAL (d); -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) + if (! in_class) + set_identifier_type_value_with_scope (name, type, b); + } + else + d = TYPE_MAIN_DECL (d); + + 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 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 + 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 + struct S1 { + template + friend class S2; + }; + + declares S2 to be at global scope. */ + || (processing_template_decl > + template_class_depth (current_class_type)))) + { + 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) { - /* Mark the TYPE_DECL node we created just above as an - gratuitous one. We need to do this so that dwarfout.c - will understand that it is not supposed to output a - TAG_typedef DIE for it. */ - DECL_IGNORED_P (d) = 1; + 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; } -#endif /* DWARF_DEBUGGING_INFO */ + } - TYPE_MAIN_DECL (type) = d; + if (b->parm_flag == 2) + d = pushdecl_class_level (d); + else + d = pushdecl_with_scope (d, b); - /* Make sure we're in this type's scope when we push the - decl for a template, otherwise class_binding_level will - be NULL and we'll end up dying inside of - push_class_level_binding. */ - if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) - pushclass (type, 0); - d = pushdecl_class_level (d); - if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) - popclass (0); - } if (newdecl) { - if (write_symbols != DWARF_DEBUG) - { - if (ANON_AGGRNAME_P (name)) - DECL_IGNORED_P (d) = 1; - } + if (ANON_AGGRNAME_P (name)) + DECL_IGNORED_P (d) = 1; - if (context == NULL_TREE) - /* Non-nested class. */ - set_nested_typename (d, NULL_TREE, name, type); - else if (context && TREE_CODE (context) == FUNCTION_DECL) - /* Function-nested class. */ - set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl), - name, type); - else /* if (context && IS_AGGR_TYPE (context)) */ - /* Class-nested class. */ - set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), - name, type); - - DECL_CONTEXT (d) = context; 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)); } @@ -2244,20 +2393,18 @@ pushtag (name, type, globalize) convenient place to record the "scope start" address for the tagged type. */ -#if 0 /* not yet, should get fixed properly later */ - tree d = make_type_decl (NULL_TREE, type); -#else tree d = build_decl (TYPE_DECL, NULL_TREE, type); -#endif TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b); } } /* Counter used to create anonymous type names. */ + static int anon_cnt = 0; /* Return an IDENTIFIER which can be used as a name for anonymous structs and unions. */ + tree make_anon_name () { @@ -2269,6 +2416,7 @@ make_anon_name () /* Clear the TREE_PURPOSE slot of tags which have anonymous typenames. This keeps dbxout from getting confused. */ + void clear_anon_tags () { @@ -2303,6 +2451,7 @@ clear_anon_tags () For C++, we must compare the parameter list so that `int' can match `int&' in a parameter position, but `int&' is not confused with `const int&'. */ + int decls_match (newdecl, olddecl) tree newdecl, olddecl; @@ -2317,6 +2466,11 @@ decls_match (newdecl, olddecl) tree p1 = TYPE_ARG_TYPES (f1); tree p2 = TYPE_ARG_TYPES (f2); + if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl) + && ! (DECL_LANGUAGE (newdecl) == lang_c + && DECL_LANGUAGE (olddecl) == lang_c)) + return 0; + /* When we parse a static member function definition, we put together a FUNCTION_DECL which thinks its type is METHOD_TYPE. Change that to FUNCTION_TYPE, and @@ -2364,33 +2518,15 @@ decls_match (newdecl, olddecl) else if (TREE_CODE (newdecl) == TEMPLATE_DECL && TREE_CODE (olddecl) == TEMPLATE_DECL) { - tree newargs = DECL_TEMPLATE_PARMS (newdecl); - tree oldargs = DECL_TEMPLATE_PARMS (olddecl); - int i, len = TREE_VEC_LENGTH (newargs); - - if (TREE_VEC_LENGTH (oldargs) != len) - return 0; - - for (i = 0; i < len; i++) - { - tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i)); - tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i)); - if (TREE_CODE (newarg) != TREE_CODE (oldarg)) - return 0; - else if (TREE_CODE (newarg) == TYPE_DECL) - /* continue */; - else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1)) - return 0; - } - - if (DECL_TEMPLATE_IS_CLASS (newdecl) - != DECL_TEMPLATE_IS_CLASS (olddecl)) - types_match = 0; - else if (DECL_TEMPLATE_IS_CLASS (newdecl)) - types_match = 1; - else - types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl), - DECL_TEMPLATE_RESULT (newdecl)); + if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), + DECL_TEMPLATE_PARMS (olddecl))) + return 0; + + if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) + types_match = 1; + else + types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl), + DECL_TEMPLATE_RESULT (newdecl)); } else { @@ -2400,8 +2536,20 @@ 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 = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1); + types_match = 0; } return types_match; @@ -2414,9 +2562,6 @@ decls_match (newdecl, olddecl) Note that this does not apply to the C++ case of declaring a variable `extern const' and then later `const'. - Don't complain if -traditional, since traditional compilers - don't complain. - Don't complain about built-in functions, since they are beyond the user's control. */ @@ -2431,8 +2576,7 @@ warn_extern_redeclared_static (newdecl, olddecl) static char *implicit_extern_static_warning = "`%D' was declared implicitly `extern' and later `static'"; - if (flag_traditional - || TREE_CODE (newdecl) == TYPE_DECL) + if (TREE_CODE (newdecl) == TYPE_DECL) return; name = DECL_ASSEMBLER_NAME (newdecl); @@ -2464,46 +2608,36 @@ warn_extern_redeclared_static (newdecl, olddecl) int duplicate_decls (newdecl, olddecl) - register tree newdecl, olddecl; + tree newdecl, olddecl; { extern struct obstack permanent_obstack; unsigned olddecl_uid = DECL_UID (olddecl); int olddecl_friend = 0, types_match = 0; - int new_defines_function; - tree previous_c_decl = NULL_TREE; + int new_defines_function = 0; - if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd') - DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl); + if (newdecl == olddecl) + return 1; types_match = decls_match (newdecl, olddecl); - if (TREE_CODE (olddecl) != TREE_LIST) - olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl); - /* If either the type of the new decl or the type of the old decl is an error_mark_node, then that implies that we have already issued an error (earlier) for some bogus type specification, and in that case, it is rather pointless to harass the user with yet more error message - about the same declaration, so well just pretent the types match here. */ - if ((TREE_TYPE (newdecl) - && TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK) - || (TREE_TYPE (olddecl) - && TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK)) + about the same declaration, so just pretend the types match here. */ + if (TREE_TYPE (newdecl) == error_mark_node + || TREE_TYPE (olddecl) == error_mark_node) types_match = 1; - - if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL - && IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl) - /* If -traditional, avoid error for redeclaring fcn - after implicit decl. */ - ; - else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_ARTIFICIAL (olddecl) - && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))) + + /* Check for redeclaration and other discrepancies. */ + if (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_ARTIFICIAL (olddecl) + && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))) { /* If you declare a built-in or predefined function name as static, the old definition is overridden, but optionally warn this was a bad choice of name. Ditto for overloads. */ - if (! DECL_PUBLIC (newdecl) + if (! TREE_PUBLIC (newdecl) || (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))) { @@ -2539,14 +2673,30 @@ duplicate_decls (newdecl, olddecl) } else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) { + if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl) + && TREE_CODE (newdecl) != TYPE_DECL + && ! (TREE_CODE (newdecl) == TEMPLATE_DECL + && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)) + || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl) + && TREE_CODE (olddecl) != TYPE_DECL + && ! (TREE_CODE (olddecl) == TEMPLATE_DECL + && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) + == TYPE_DECL)))) + { + /* We do nothing special here, because C++ does such nasty + things with TYPE_DECLs. Instead, just let the TYPE_DECL + get shadowed, and know that if we need to find a TYPE_DECL + for a given name, we can look in the IDENTIFIER_TYPE_VALUE + slot of the identifier. */ + return 0; + } + if ((TREE_CODE (newdecl) == FUNCTION_DECL - && TREE_CODE (olddecl) == TEMPLATE_DECL - && ! DECL_TEMPLATE_IS_CLASS (olddecl)) + && DECL_FUNCTION_TEMPLATE_P (olddecl)) || (TREE_CODE (olddecl) == FUNCTION_DECL - && TREE_CODE (newdecl) == TEMPLATE_DECL - && ! DECL_TEMPLATE_IS_CLASS (newdecl))) + && DECL_FUNCTION_TEMPLATE_P (newdecl))) return 0; - + cp_error ("`%#D' redeclared as different kind of symbol", newdecl); if (TREE_CODE (olddecl) == TREE_LIST) olddecl = TREE_VALUE (olddecl); @@ -2563,14 +2713,24 @@ duplicate_decls (newdecl, olddecl) { /* The name of a class template may not be declared to refer to any other template, class, function, object, namespace, value, - or type in the same scope. */ - if (DECL_TEMPLATE_IS_CLASS (olddecl) - || DECL_TEMPLATE_IS_CLASS (newdecl)) + or type in the same scope. */ + if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL + || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) { cp_error ("declaration of template `%#D'", newdecl); cp_error_at ("conflicts with previous declaration `%#D'", 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) + && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), + DECL_TEMPLATE_PARMS (olddecl))) + { + cp_error ("new declaration `%#D'", newdecl); + cp_error_at ("ambiguates old declaration `%#D'", olddecl); + } return 0; } if (TREE_CODE (newdecl) == FUNCTION_DECL) @@ -2600,6 +2760,37 @@ duplicate_decls (newdecl, olddecl) cp_error_at ("previous declaration as `%#D'", olddecl); } } + else if (TREE_CODE (newdecl) == FUNCTION_DECL + && ((DECL_TEMPLATE_SPECIALIZATION (olddecl) + && (!DECL_TEMPLATE_INFO (newdecl) + || (DECL_TI_TEMPLATE (newdecl) + != DECL_TI_TEMPLATE (olddecl)))) + || (DECL_TEMPLATE_SPECIALIZATION (newdecl) + && (!DECL_TEMPLATE_INFO (olddecl) + || (DECL_TI_TEMPLATE (olddecl) + != DECL_TI_TEMPLATE (newdecl)))))) + /* It's OK to have a template specialization and a non-template + with the same type, or to have specializations of two + different templates with the same type. Note that if one is a + specialization, and the other is an instantiation of the same + template, that we do not exit at this point. That situation + can occur if we instantiate a template class, and then + specialize one of its methods. This situation is legal, but + the declarations must be merged in the usual way. */ + return 0; + else if (TREE_CODE (newdecl) == FUNCTION_DECL + && ((DECL_TEMPLATE_INSTANTIATION (olddecl) + && !DECL_USE_TEMPLATE (newdecl)) + || (DECL_TEMPLATE_INSTANTIATION (newdecl) + && !DECL_USE_TEMPLATE (olddecl)))) + /* One of the declarations is a template instantiation, and the + other is not a template at all. That's OK. */ + return 0; + else if (TREE_CODE (newdecl) == NAMESPACE_DECL + && DECL_NAMESPACE_ALIAS (newdecl) + && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl)) + /* Redeclaration of namespace alias, ignore it. */ + return 1; else { char *errmsg = redeclaration_error_message (newdecl, olddecl); @@ -2608,7 +2799,7 @@ duplicate_decls (newdecl, olddecl) cp_error (errmsg, newdecl); if (DECL_NAME (olddecl) != NULL_TREE) cp_error_at ((DECL_INITIAL (olddecl) - && current_binding_level == global_binding_level) + && namespace_bindings_p ()) ? "`%#D' previously defined here" : "`%#D' previously declared here", olddecl); } @@ -2638,7 +2829,9 @@ duplicate_decls (newdecl, olddecl) } } - if (TREE_CODE (olddecl) == FUNCTION_DECL) + if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl)) + ; + else if (TREE_CODE (olddecl) == FUNCTION_DECL) { tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); @@ -2666,32 +2859,18 @@ duplicate_decls (newdecl, olddecl) { cp_error ("default argument given for parameter %d of `%#D'", i, newdecl); - cp_error_at ("conflicts with previous specification in `%#D'", + cp_error_at ("after previous specification in `%#D'", olddecl); } } - if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl)) + if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl) + && TREE_ADDRESSABLE (olddecl) && warn_inline) { -#if 0 /* I think this will be correct, but it's really annoying. We should - fix the compiler to find vtables by indirection so it isn't - necessary. (jason 8/25/95) */ - if (DECL_VINDEX (olddecl) && ! DECL_ABSTRACT_VIRTUAL_P (olddecl)) - { - cp_pedwarn ("virtual function `%#D' redeclared inline", - newdecl); - cp_pedwarn_at ("previous non-inline declaration here", - olddecl); - } - else -#endif - if (TREE_ADDRESSABLE (olddecl)) - { - cp_pedwarn ("`%#D' was used before it was declared inline", - newdecl); - cp_pedwarn_at ("previous non-inline declaration here", - olddecl); - } + cp_warning ("`%#D' was used before it was declared inline", + newdecl); + cp_warning_at ("previous non-inline declaration here", + olddecl); } } /* These bits are logically part of the type for non-functions. */ @@ -2707,7 +2886,7 @@ duplicate_decls (newdecl, olddecl) warn about it. */ warn_extern_redeclared_static (newdecl, olddecl); - /* We have committed to returning 1 at this point. */ + /* We have committed to returning 1 at this point. */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { /* Now that functions must hold information normally held @@ -2720,15 +2899,28 @@ duplicate_decls (newdecl, olddecl) DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); if (DECL_CLASS_CONTEXT (olddecl)) DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl); - if (DECL_CHAIN (newdecl) == NULL_TREE) - DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl); - if (DECL_NEXT_METHOD (newdecl) == NULL_TREE) - DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl); if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0) DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl); DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl); DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl); + DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl); + DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl); + new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE; + + /* Optionally warn about more than one declaration for the same + name, but don't warn about a function declaration followed by a + definition. */ + if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl) + && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE) + /* Don't warn about extern decl followed by definition. */ + && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)) + /* Don't warn about friends, let add_friend take care of it. */ + && ! DECL_FRIEND_P (newdecl)) + { + cp_warning ("redundant redeclaration of `%D' in same scope", newdecl); + cp_warning_at ("previous declaration of `%D'", olddecl); + } } /* Deal with C++: must preserve virtual function table size. */ @@ -2737,8 +2929,6 @@ duplicate_decls (newdecl, olddecl) register tree newtype = TREE_TYPE (newdecl); register tree oldtype = TREE_TYPE (olddecl); - DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl); - if (newtype != error_mark_node && oldtype != error_mark_node && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype)) { @@ -2746,39 +2936,30 @@ duplicate_decls (newdecl, olddecl) CLASSTYPE_FRIEND_CLASSES (newtype) = CLASSTYPE_FRIEND_CLASSES (oldtype); } -#if 0 - /* why assert here? Just because debugging information is - messed up? (mrs) */ - /* it happens on something like: - typedef struct Thing { - Thing(); - int x; - } Thing; - */ - my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), - 139); -#endif - } - - /* Special handling ensues if new decl is a function definition. */ - new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL - && DECL_INITIAL (newdecl) != NULL_TREE); - - /* Optionally warn about more than one declaration for the same name, - but don't warn about a function declaration followed by a definition. */ - if (warn_redundant_decls - && ! DECL_ARTIFICIAL (olddecl) - && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE) - /* Don't warn about extern decl followed by (tentative) definition. */ - && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))) - { - cp_warning ("redundant redeclaration of `%D' in same scope", newdecl); - cp_warning_at ("previous declaration of `%D'", olddecl); } /* Copy all the DECL_... slots specified in the new decl except for any that we copy here from the old type. */ + DECL_MACHINE_ATTRIBUTES (newdecl) + = merge_machine_decl_attributes (olddecl, newdecl); + 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); + + return 1; + } + if (types_match) { /* Automatically handles default parameters. */ @@ -2805,32 +2986,35 @@ duplicate_decls (newdecl, olddecl) && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)) != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)))) { - tree ctype = NULL_TREE; - ctype = DECL_CLASS_CONTEXT (newdecl); TREE_TYPE (newdecl) = build_exception_variant (newtype, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))); TREE_TYPE (olddecl) = build_exception_variant (newtype, TYPE_RAISES_EXCEPTIONS (oldtype)); - if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0)) + if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl)) + && DECL_SOURCE_LINE (olddecl) != 0 + && flag_exceptions + && ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl))) { - cp_error ("declaration of `%D' throws different exceptions...", + cp_pedwarn ("declaration of `%D' throws different exceptions", newdecl); - cp_error_at ("...from previous declaration here", olddecl); + cp_pedwarn_at ("previous declaration here", olddecl); } } TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; /* Lay the type out, unless already done. */ - if (oldtype != TREE_TYPE (newdecl) - && TREE_TYPE (newdecl) != error_mark_node) + if (newtype != canonical_type_variant (oldtype) + && TREE_TYPE (newdecl) != error_mark_node + && !(processing_template_decl && uses_template_parms (newdecl))) layout_type (TREE_TYPE (newdecl)); - if (TREE_CODE (newdecl) == VAR_DECL - || TREE_CODE (newdecl) == PARM_DECL - || TREE_CODE (newdecl) == RESULT_DECL - || TREE_CODE (newdecl) == FIELD_DECL - || TREE_CODE (newdecl) == TYPE_DECL) + if ((TREE_CODE (newdecl) == VAR_DECL + || TREE_CODE (newdecl) == PARM_DECL + || TREE_CODE (newdecl) == RESULT_DECL + || TREE_CODE (newdecl) == FIELD_DECL + || TREE_CODE (newdecl) == TYPE_DECL) + && !(processing_template_decl && uses_template_parms (newdecl))) layout_decl (newdecl, 0); /* Merge the type qualifiers. */ @@ -2881,20 +3065,55 @@ duplicate_decls (newdecl, olddecl) /* Merge the storage class information. */ DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl); TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl); if (! DECL_EXTERNAL (olddecl)) DECL_EXTERNAL (newdecl) = 0; - - if (TREE_CODE (newdecl) == FUNCTION_DECL) + + if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl)) { - DECL_C_STATIC (newdecl) = DECL_C_STATIC (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); + /* 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); + } + olddecl_friend = DECL_FRIEND_P (olddecl); } if (TREE_CODE (newdecl) == FUNCTION_DECL) { + if (DECL_TEMPLATE_INSTANTIATION (olddecl) + && !DECL_TEMPLATE_INSTANTIATION (newdecl)) + { + /* If newdecl is not a specialization, then it is not a + template-related function at all. And that means that we + shoud have exited above, returning 0. */ + my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl), + 0); + + if (TREE_USED (olddecl)) + /* From [temp.expl.spec]: + + If a template, a member template or the member of a class + template is explicitly specialized then that + specialization shall be declared before the first use of + that specialization that would cause an implicit + instantiation to take place, in every translation unit in + which such a use occurs. */ + cp_error ("explicit specialization of %D after first use", + olddecl); + + SET_DECL_TEMPLATE_SPECIALIZATION (olddecl); + } DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl); /* If either decl says `inline', this fn is inline, unless its @@ -2907,10 +3126,14 @@ duplicate_decls (newdecl, olddecl) { DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl); - DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl); - DECL_RESULT (olddecl) = DECL_RESULT (newdecl); DECL_RTL (olddecl) = DECL_RTL (newdecl); } + if (! types_match || new_defines_function) + { + /* These need to be copied so that the names are available. */ + DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl); + DECL_RESULT (olddecl) = DECL_RESULT (newdecl); + } if (new_defines_function) /* If defining a function declared with other language linkage, use the previously declared language linkage. */ @@ -2948,32 +3171,12 @@ duplicate_decls (newdecl, olddecl) NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl); } - if (TREE_CODE (newdecl) == TEMPLATE_DECL) - { - if (DECL_TEMPLATE_INFO (olddecl)->length) - DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); - DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl); - DECL_TEMPLATE_INSTANTIATIONS (newdecl) - = DECL_TEMPLATE_INSTANTIATIONS (olddecl); - if (DECL_CHAIN (newdecl) == NULL_TREE) - DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl); - } - /* Now preserve various other info from the definition. */ TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl); TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl); DECL_COMMON (newdecl) = DECL_COMMON (olddecl); DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl); - /* Don't really know how much of the language-specific - values we should copy from old to new. */ - if (DECL_LANG_SPECIFIC (olddecl)) - { - 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 (TREE_CODE (newdecl) == FUNCTION_DECL) { int function_size; @@ -2991,9 +3194,44 @@ duplicate_decls (newdecl, olddecl) #define ROUND(x) ((x + obstack_alignment_mask (&permanent_obstack)) \ & ~ obstack_alignment_mask (&permanent_obstack)) - if ((char *)newdecl + ROUND (function_size) - + ROUND (sizeof (struct lang_decl)) - == obstack_next_free (&permanent_obstack)) + if (DECL_TEMPLATE_INSTANTIATION (newdecl)) + { + /* If newdecl is a template instantiation, it is possible that + the following sequence of events has occurred: + + o A friend function was declared in a class template. The + class template was instantiated. + + o The instantiation of the friend declaration was + recorded on the instantiation list, and is newdecl. + + o Later, however, instantiate_class_template called pushdecl + on the newdecl to perform name injection. But, pushdecl in + turn called duplicate_decls when it discovered that another + declaration of a global function with the same name already + existed. + + o Here, in duplicate_decls, we decided to clobber newdecl. + + If we're going to do that, we'd better make sure that + olddecl, and not newdecl, is on the list of + instantiations so that if we try to do the instantiation + again we won't get the clobbered declaration. */ + + tree tmpl = DECL_TI_TEMPLATE (newdecl); + tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + + for (; decls; decls = TREE_CHAIN (decls)) + if (TREE_VALUE (decls) == newdecl) + TREE_VALUE (decls) = olddecl; + } + + if (((char *)newdecl + ROUND (function_size) == (char *)nl + && ((char *)newdecl + ROUND (function_size) + + ROUND (sizeof (struct lang_decl)) + == obstack_next_free (&permanent_obstack))) + || ((char *)newdecl + ROUND (function_size) + == obstack_next_free (&permanent_obstack))) { DECL_MAIN_VARIANT (newdecl) = olddecl; DECL_LANG_SPECIFIC (olddecl) = ol; @@ -3001,19 +3239,23 @@ duplicate_decls (newdecl, olddecl) obstack_free (&permanent_obstack, newdecl); } - else if (LANG_DECL_PERMANENT (ol)) + else if (LANG_DECL_PERMANENT (ol) && ol != nl) { if (DECL_MAIN_VARIANT (olddecl) == olddecl) { /* Save these lang_decls that would otherwise be lost. */ extern tree free_lang_decl_chain; tree free_lang_decl = (tree) ol; + + if (DECL_LANG_SPECIFIC (olddecl) == ol) + abort (); + TREE_CHAIN (free_lang_decl) = free_lang_decl_chain; free_lang_decl_chain = free_lang_decl; } else { - /* Storage leak. */ + /* Storage leak. */; } } } @@ -3029,6 +3271,10 @@ duplicate_decls (newdecl, olddecl) if (olddecl_friend) DECL_FRIEND_P (olddecl) = 1; + /* NEWDECL contains the merged attribute lists. + Update OLDDECL to be the same. */ + DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl); + return 1; } @@ -3045,54 +3291,41 @@ pushdecl (x) tree x; { register tree t; -#if 0 /* not yet, should get fixed properly later */ - register tree name; -#else register tree name = DECL_ASSEMBLER_NAME (x); -#endif register struct binding_level *b = current_binding_level; -#if 0 - static int nglobals; int len; - - len = list_length (global_binding_level->names); - if (len < nglobals) - my_friendly_abort (8); - else if (len > nglobals) - nglobals = len; -#endif - - if (x != current_function_decl + 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; - /* A local declaration for a function doesn't constitute nesting. */ - if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0) - DECL_CONTEXT (x) = 0; - -#if 0 /* not yet, should get fixed properly later */ - /* For functions and class static data, we currently look up the encoded - form of the name. For types, we want the real name. The former will - probably be changed soon, according to MDT. */ - if (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL) - name = DECL_ASSEMBLER_NAME (x); - else - name = DECL_NAME (x); -#else + 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. */ + compiler wants to use. */ if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL - || TREE_CODE (x) == NAMESPACE_DECL) + || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM + || TREE_CODE (x) == TEMPLATE_TEMPLATE_PARM) name = DECL_NAME (x); -#endif if (name) { +#if 0 + /* Not needed...see below. */ char *file; int line; - - t = lookup_name_current_level (name); +#endif + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + name = TREE_OPERAND (name, 0); + + /* Namespace-scoped variables are not found in the current level. */ + if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x)) + t = namespace_binding (name, DECL_CONTEXT (x)); + else + t = lookup_name_current_level (name); if (t == error_mark_node) { /* error_mark_node is 0 for a while during initialization! */ @@ -3102,20 +3335,25 @@ pushdecl (x) else if (t != NULL_TREE) { +#if 0 + /* This is turned off until I have time to do it right (bpk). */ + /* With the code below that uses it... */ file = DECL_SOURCE_FILE (t); line = DECL_SOURCE_LINE (t); - if (TREE_CODE (x) == VAR_DECL && DECL_DEAD_FOR_LOCAL (x)) - ; /* This is OK. */ - else if (TREE_CODE (t) == PARM_DECL) +#endif + if (TREE_CODE (t) == PARM_DECL) { if (DECL_CONTEXT (t) == NULL_TREE) fatal ("parse errors have confused me too much"); + + /* Check for duplicate params. */ + if (duplicate_decls (x, t)) + return t; } else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) - || (TREE_CODE (x) == TEMPLATE_DECL - && ! DECL_TEMPLATE_IS_CLASS (x))) - && is_overloaded_fn (t)) - /* don't do anything just yet */; + || DECL_FUNCTION_TEMPLATE_P (x)) + && is_overloaded_fn (t)) + /* Don't do anything just yet. */; else if (t == wchar_decl_node) { if (pedantic && ! DECL_IN_SYSTEM_HEADER (x)) @@ -3126,17 +3364,7 @@ pushdecl (x) } else if (TREE_CODE (t) != TREE_CODE (x)) { - if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)) - || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))) - { - /* We do nothing special here, because C++ does such nasty - things with TYPE_DECLs. Instead, just let the TYPE_DECL - get shadowed, and know that if we need to find a TYPE_DECL - for a given name, we can look in the IDENTIFIER_TYPE_VALUE - slot of the identifier. */ - ; - } - else if (duplicate_decls (x, t)) + if (duplicate_decls (x, t)) return t; } else if (duplicate_decls (x, t)) @@ -3178,6 +3406,20 @@ pushdecl (x) return t; } + else if (DECL_MAIN_P (x)) + { + /* A redeclaration of main, but not a duplicate of the + previous one. + + [basic.start.main] + + This function shall not be overloaded. */ + cp_error_at ("invalid redeclaration of `%D'", t); + cp_error ("as `%D'", x); + /* We don't try to push this declaration since that + causes a crash. */ + return x; + } } if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x)) @@ -3186,45 +3428,32 @@ pushdecl (x) if (t != x || DECL_LANGUAGE (x) == lang_c) return t; } - else if (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x)) + else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x)) return push_overloaded_decl (x, 0); - /* If declaring a type as a typedef, and the type has no known - typedef name, install this TYPE_DECL as its typedef name. */ + /* 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 + name. See the extensive comment in ../c-decl.c (pushdecl). */ if (TREE_CODE (x) == TYPE_DECL) { tree type = TREE_TYPE (x); - tree name = (type != error_mark_node) ? TYPE_NAME (type) : x; - - if (name == NULL_TREE || TREE_CODE (name) != TYPE_DECL) - { - /* If these are different names, and we're at the global - binding level, make two equivalent definitions. */ - name = x; - if (global_bindings_p ()) - TYPE_NAME (type) = x; - } - else - { - tree tname = DECL_NAME (name); + if (DECL_SOURCE_LINE (x) == 0) + { + if (TYPE_NAME (type) == 0) + TYPE_NAME (type) = x; + } + else if (type != error_mark_node && TYPE_NAME (type) != x) + { + push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); - /* This is a disgusting kludge for dealing with UPTs. */ - if (global_bindings_p () && ANON_AGGRNAME_P (tname)) - { - /* do gratuitous C++ typedefing, and make sure that - we access this type either through TREE_TYPE field - or via the tags list. */ - TYPE_NAME (TREE_TYPE (x)) = x; - pushtag (tname, TREE_TYPE (x), 0); - } - } - my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140); + DECL_ORIGINAL_TYPE (x) = type; + type = build_type_copy (type); + TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x)); + TYPE_NAME (type) = x; + TREE_TYPE (x) = type; - /* Don't set nested_typename on template type parms, for instance. - Any artificial decls that need DECL_NESTED_TYPENAME will have it - set in pushtag. */ - if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) - set_nested_typename (x, current_class_name, DECL_NAME (x), type); + pop_obstacks (); + } if (type != error_mark_node && TYPE_NAME (type) @@ -3241,11 +3470,12 @@ pushdecl (x) if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL) { tree decl; + tree bindings = binding_for_name (name, current_namespace); - if (IDENTIFIER_GLOBAL_VALUE (name) != NULL_TREE - && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) - || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name)))) - decl = IDENTIFIER_GLOBAL_VALUE (name); + if (BINDING_VALUE (bindings) != NULL_TREE + && (DECL_EXTERNAL (BINDING_VALUE (bindings)) + || TREE_PUBLIC (BINDING_VALUE (bindings)))) + decl = BINDING_VALUE (bindings); else decl = NULL_TREE; @@ -3259,21 +3489,16 @@ pushdecl (x) } } - /* In PCC-compatibility mode, extern decls of vars with no current decl - take effect at top level no matter where they are. */ - if (flag_traditional && DECL_EXTERNAL (x) - && lookup_name (name, 0) == NULL_TREE) - b = global_binding_level; - /* This name is new in its binding level. Install the new declaration and return it. */ - if (b == global_binding_level) + 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 (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && DECL_PUBLIC (x)) + if (BINDING_VALUE (bindings) == NULL_TREE && TREE_PUBLIC (x)) TREE_PUBLIC (name) = 1; /* Don't install an artificial TYPE_DECL if we already have @@ -3281,7 +3506,12 @@ pushdecl (x) if (TREE_CODE (x) != TYPE_DECL || t == NULL_TREE || ! DECL_ARTIFICIAL (x)) - IDENTIFIER_GLOBAL_VALUE (name) = x; + { + if (TREE_CODE (x) == FUNCTION_DECL) + my_friendly_assert ((BINDING_VALUE (bindings) == NULL_TREE) + || BINDING_VALUE (bindings) == x, 378); + BINDING_VALUE (bindings) = x; + } /* Don't forget if the function was used via an implicit decl. */ if (IDENTIFIER_IMPLICIT_DECL (name) @@ -3310,17 +3540,14 @@ pushdecl (x) { /* Here to install a non-global value. */ tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); - tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name); + tree oldglobal = binding_for_name (name, current_namespace); /* 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)) - { - b->shadowed = tree_cons (name, oldlocal, b->shadowed); - IDENTIFIER_LOCAL_VALUE (name) = x; - } + set_identifier_local_value_with_scope (name, x, b); /* If this is a TYPE_DECL, push it into the type value slot. */ if (TREE_CODE (x) == TYPE_DECL) @@ -3336,24 +3563,24 @@ pushdecl (x) have a global definition or declaration for the function. */ if (oldlocal == NULL_TREE && DECL_EXTERNAL (x) - && oldglobal != NULL_TREE + && BINDING_VALUE (oldglobal) != NULL_TREE && TREE_CODE (x) == FUNCTION_DECL - && TREE_CODE (oldglobal) == FUNCTION_DECL) + && TREE_CODE (BINDING_VALUE (oldglobal)) == FUNCTION_DECL) { /* We have one. Their types must agree. */ - if (decls_match (x, oldglobal)) + if (decls_match (x, BINDING_VALUE (oldglobal))) /* OK */; else { cp_warning ("extern declaration of `%#D' doesn't match", x); - cp_warning_at ("global declaration `%#D'", oldglobal); + cp_warning_at ("global declaration `%#D'", BINDING_VALUE (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 - && oldglobal == NULL_TREE + && BINDING_VALUE (oldglobal) == NULL_TREE && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { @@ -3379,7 +3606,7 @@ pushdecl (x) if (b->parm_flag == 1) cp_error ("declaration of `%#D' shadows a parameter", name); } - else if (oldlocal != NULL_TREE && b->is_for_scope + else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope && !DECL_DEAD_FOR_LOCAL (oldlocal)) { warning ("variable `%s' shadows local", @@ -3398,12 +3625,13 @@ pushdecl (x) if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL) warnstring = "declaration of `%s' shadows a parameter"; else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE - && current_class_decl + && current_class_ptr && !TREE_STATIC (name)) warnstring = "declaration of `%s' shadows a member of `this'"; else if (oldlocal != NULL_TREE) warnstring = "declaration of `%s' shadows previous local"; - else if (oldglobal != NULL_TREE) + else if (BINDING_VALUE (oldglobal) != NULL_TREE) + /* XXX shadow warnings in outer-more namespaces */ warnstring = "declaration of `%s' shadows global declaration"; if (warnstring) @@ -3435,29 +3663,47 @@ pushdecl (x) return x; } -/* Same as pushdecl, but define X in binding-level LEVEL. */ +/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the + caller to set DECL_CONTEXT properly. */ static tree pushdecl_with_scope (x, level) tree x; struct binding_level *level; { - register struct binding_level *b = current_binding_level; + register struct binding_level *b; + tree function_decl = current_function_decl; - current_binding_level = level; - x = pushdecl (x); - current_binding_level = b; + current_function_decl = NULL_TREE; + if (level->parm_flag == 2) + { + b = class_binding_level; + class_binding_level = level; + pushdecl_class_level (x); + class_binding_level = b; + } + else + { + b = current_binding_level; + current_binding_level = level; + x = pushdecl (x); + current_binding_level = b; + } + current_function_decl = function_decl; return x; } -/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, +/* Like pushdecl, only it places X in the current namespace, if appropriate. */ + tree -pushdecl_top_level (x) +pushdecl_namespace_level (x) tree x; { register struct binding_level *b = inner_binding_level; - register tree t = pushdecl_with_scope (x, global_binding_level); + register tree t; + + t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace)); /* Now, the type_shadowed stack may screw us. Munge it so it does what we want. */ @@ -3487,34 +3733,28 @@ pushdecl_top_level (x) } else { -#if 0 - /* Disabled this 11/10/92, since there are many cases which - behave just fine when *ptr doesn't satisfy either of these. - For example, nested classes declared as friends of their enclosing - class will not meet this criteria. (bpk) */ - my_friendly_assert (*ptr == NULL_TREE || *ptr == newval, 141); -#endif *ptr = newval; } } return t; } -/* Like push_overloaded_decl, only it places X in GLOBAL_BINDING_LEVEL, +/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */ -void -push_overloaded_decl_top_level (x, forget) + +tree +pushdecl_top_level (x) tree x; - int forget; { - struct binding_level *b = current_binding_level; - - current_binding_level = global_binding_level; - push_overloaded_decl (x, forget); - current_binding_level = b; + tree cur_namespace = current_namespace; + current_namespace = global_namespace; + x = pushdecl_namespace_level (x); + current_namespace = cur_namespace; + return x; } /* Make the declaration of X appear in CLASS scope. */ + tree pushdecl_class_level (x) tree x; @@ -3527,21 +3767,24 @@ pushdecl_class_level (x) { if (TYPE_BEING_DEFINED (current_class_type)) { - /* Check for inconsistent use of this name in the class body. + /* 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 + if (icv && icv != x + && flag_optional_diags /* Don't complain about inherited names. */ && id_in_current_class (name) /* Or shadowed tags. */ - && !(TREE_CODE (icv) == TYPE_DECL + && !(DECL_DECLARES_TYPE_P (icv) && DECL_CONTEXT (icv) == current_class_type)) { - cp_error ("declaration of identifier `%D' as `%#D'", name, x); - cp_error_at ("conflicts with previous use in class as `%#D'", - icv); + cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x); + cp_pedwarn_at ("conflicts with previous use in class as `%#D'", + icv); } } @@ -3549,49 +3792,47 @@ pushdecl_class_level (x) if (TREE_CODE (x) == TYPE_DECL) { set_identifier_type_value (name, TREE_TYPE (x)); - - /* Don't set nested_typename on template type parms, for instance. - Any artificial decls that need DECL_NESTED_TYPENAME will have it - set in pushtag. */ - if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) - set_nested_typename (x, current_class_name, name, TREE_TYPE (x)); } } return x; } +#if 0 /* This function is used to push the mangled decls for nested types into the appropriate scope. Previously pushdecl_top_level was used, but that is incorrect for members of local classes. */ -tree + +void pushdecl_nonclass_level (x) tree x; { struct binding_level *b = current_binding_level; -#if 0 - /* Get out of class scope -- this isn't necessary, because class scope - doesn't make it into current_binding_level. */ - while (b->parm_flag == 2) - b = b->level_chain; -#else my_friendly_assert (b->parm_flag != 2, 180); -#endif +#if 0 /* Get out of template binding levels */ while (b->pseudo_global) b = b->level_chain; +#endif pushdecl_with_scope (x, b); } +#endif /* Make the declaration(s) of X appear in CLASS scope under the name NAME. */ + void push_class_level_binding (name, x) tree name; tree x; { + /* 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; @@ -3605,22 +3846,55 @@ push_class_level_binding (name, x) obstack_ptr_grow (&decl_obstack, x); } -/* Tell caller how to interpret a TREE_LIST which contains - chains of FUNCTION_DECLS. */ -int -overloaded_globals_p (list) - tree list; +/* Insert another USING_DECL into the current binding level, + returning this declaration. If this is a redeclaration, + do nothing and return NULL_TREE. */ + +tree +push_using_decl (scope, name) + tree scope; + tree name; { - my_friendly_assert (TREE_CODE (list) == TREE_LIST, 142); + tree decl; + + my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384); + for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl)) + if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name) + break; + if (decl) + return NULL_TREE; + decl = build_lang_decl (USING_DECL, name, void_type_node); + DECL_INITIAL (decl) = scope; + TREE_CHAIN (decl) = current_binding_level->usings; + current_binding_level->usings = decl; + return decl; +} - /* Don't commit caller to seeing them as globals. */ - if (TREE_NONLOCAL_FLAG (list)) - return -1; - /* Do commit caller to seeing them as globals. */ - if (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE) - return 1; - /* Do commit caller to not seeing them as globals. */ - return 0; +/* Add namespace to using_directives. Return NULL_TREE if nothing was + changed (i.e. there was already a directive), or the fresh + TREE_LIST otherwise. */ + +tree +push_using_directive (used) + tree used; +{ + tree ud = current_binding_level->using_directives; + tree iter, ancestor; + + /* Check if we already have this. */ + if (purpose_member (used, ud) != NULL_TREE) + return NULL_TREE; + + /* Recursively add all namespaces used. */ + for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter)) + push_using_directive (TREE_PURPOSE (iter)); + + ancestor = namespace_ancestor (current_decl_namespace (), used); + ud = current_binding_level->using_directives; + ud = perm_tree_cons (used, ancestor, ud); + current_binding_level->using_directives = ud; + return ud; } /* DECL is a FUNCTION_DECL which may have other definitions already in @@ -3635,19 +3909,19 @@ overloaded_globals_p (list) 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). */ -tree + +static tree push_overloaded_decl (decl, forgettable) tree decl; int forgettable; { tree orig_name = DECL_NAME (decl); tree old; - int doing_global = (global_bindings_p () || ! forgettable - || flag_traditional || pseudo_global_level_p ()); + int doing_global = (namespace_bindings_p () || ! forgettable); if (doing_global) { - old = IDENTIFIER_GLOBAL_VALUE (orig_name); + old = namespace_binding (orig_name, DECL_CONTEXT (decl)); if (old && TREE_CODE (old) == FUNCTION_DECL && DECL_ARTIFICIAL (old) && (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old))) @@ -3671,18 +3945,12 @@ push_overloaded_decl (decl, forgettable) if (old) { -#if 0 - /* We cache the value of builtin functions as ADDR_EXPRs - in the name space. Convert it to some kind of _DECL after - remembering what to forget. */ - if (TREE_CODE (old) == ADDR_EXPR) - old = TREE_OPERAND (old, 0); - else -#endif if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old)) { tree t = TREE_TYPE (old); - if (IS_AGGR_TYPE (t) && warn_shadow) + if (IS_AGGR_TYPE (t) && warn_shadow + && (! DECL_IN_SYSTEM_HEADER (decl) + || ! DECL_IN_SYSTEM_HEADER (old))) cp_warning ("`%#D' hides constructor for `%#T'", decl, t); old = NULL_TREE; } @@ -3690,9 +3958,10 @@ push_overloaded_decl (decl, forgettable) { tree tmp; - for (tmp = get_first_fn (old); tmp; tmp = DECL_CHAIN (tmp)) - if (decl == tmp || duplicate_decls (decl, tmp)) - return tmp; + for (tmp = old; tmp; tmp = OVL_NEXT (tmp)) + if (decl == OVL_CURRENT (tmp) + || duplicate_decls (decl, OVL_CURRENT (tmp))) + return OVL_CURRENT (tmp); } else { @@ -3704,19 +3973,16 @@ push_overloaded_decl (decl, forgettable) if (old || TREE_CODE (decl) == TEMPLATE_DECL) { - if (old && is_overloaded_fn (old)) - DECL_CHAIN (decl) = get_first_fn (old); - else - DECL_CHAIN (decl) = NULL_TREE; - old = tree_cons (orig_name, decl, NULL_TREE); - TREE_TYPE (old) = unknown_type_node; + if (old && TREE_CODE (old) != OVERLOAD) + old = ovl_cons (old, NULL_TREE); + old = ovl_cons (decl, old); } else /* orig_name is not ambiguous. */ old = decl; if (doing_global) - IDENTIFIER_GLOBAL_VALUE (orig_name) = old; + set_namespace_binding (orig_name, current_namespace, old); else IDENTIFIER_LOCAL_VALUE (orig_name) = old; @@ -3738,7 +4004,7 @@ implicitly_declare (functionid) /* Save the decl permanently so we can warn if definition follows. In ANSI C, warn_implicit is usually false, so the saves little space. But in C++, it's usually true, hence the extra code. */ - if (temp && (flag_traditional || !warn_implicit || toplevel_bindings_p ())) + if (temp && (! warn_implicit || toplevel_bindings_p ())) end_temporary_allocation (); /* We used to reuse an old implicit decl here, @@ -3750,8 +4016,7 @@ implicitly_declare (functionid) TREE_PUBLIC (decl) = 1; /* ANSI standard says implicit declarations are in the innermost block. - So we record the decl in the standard fashion. - If flag_traditional is set, pushdecl does it top-level. */ + So we record the decl in the standard fashion. */ pushdecl (decl); rest_of_decl_compilation (decl, NULL_PTR, 0, 0); @@ -3797,10 +4062,16 @@ redeclaration_error_message (newdecl, olddecl) if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl)) return 0; + /* If both functions come from different namespaces, this is not + a redeclaration - this is a conflict with a used function. */ + if (DECL_NAMESPACE_SCOPE_P (olddecl) + && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)) + return "`%D' conflicts with used function"; + /* We'll complain about linkage mismatches in warn_extern_redeclared_static. */ - /* defining the same name twice is no good. */ + /* Defining the same name twice is no good. */ if (DECL_INITIAL (olddecl) != NULL_TREE && DECL_INITIAL (newdecl) != NULL_TREE) { @@ -3813,11 +4084,16 @@ redeclaration_error_message (newdecl, olddecl) } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) { - if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl)) + if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL + && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) + && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl))) + || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL + && TYPE_SIZE (TREE_TYPE (newdecl)) + && TYPE_SIZE (TREE_TYPE (olddecl)))) return "redefinition of `%#D'"; return 0; } - else if (current_binding_level == global_binding_level) + else if (toplevel_bindings_p ()) { /* Objects declared at top level: */ /* If at least one is a reference, it's ok. */ @@ -3856,13 +4132,20 @@ lookup_label (id) if ((decl == NULL_TREE || DECL_SOURCE_LINE (decl) == 0) - && (named_label_uses == NULL_TREE - || TREE_PURPOSE (named_label_uses) != current_binding_level->names - || TREE_VALUE (named_label_uses) != decl)) - { - named_label_uses - = tree_cons (current_binding_level->names, decl, named_label_uses); - TREE_TYPE (named_label_uses) = (tree)current_binding_level; + && (named_label_uses == NULL + || named_label_uses->names_in_scope != current_binding_level->names + || named_label_uses->label_decl != decl)) + { + struct named_label_list *new_ent; + new_ent + = (struct named_label_list*)oballoc (sizeof (struct named_label_list)); + new_ent->label_decl = decl; + new_ent->names_in_scope = current_binding_level->names; + new_ent->binding_level = current_binding_level; + new_ent->lineno_o_goto = lineno; + new_ent->filename_o_goto = input_filename; + new_ent->next = named_label_uses; + named_label_uses = new_ent; } /* Use a label already defined or ref'd with this name. */ @@ -3877,6 +4160,9 @@ lookup_label (id) decl = build_decl (LABEL_DECL, id, void_type_node); + /* Make sure every label has an rtx. */ + label_rtx (decl); + /* A label not explicitly declared must be local to where it's ref'd. */ DECL_CONTEXT (decl) = current_function_decl; @@ -3890,7 +4176,7 @@ lookup_label (id) SET_IDENTIFIER_LABEL_VALUE (id, decl); named_labels = tree_cons (NULL_TREE, decl, named_labels); - TREE_VALUE (named_label_uses) = decl; + named_label_uses->label_decl = decl; return decl; } @@ -3913,7 +4199,6 @@ shadow_label (name) { shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels); SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE); - SET_IDENTIFIER_LABEL_VALUE (decl, NULL_TREE); } return lookup_label (name); @@ -3929,7 +4214,20 @@ define_label (filename, line, name) int line; tree name; { - tree decl = lookup_label (name); + tree decl; + + if (minimal_parse_mode) + { + push_obstacks (&permanent_obstack, &permanent_obstack); + decl = build_decl (LABEL_DECL, name, void_type_node); + pop_obstacks (); + DECL_SOURCE_LINE (decl) = line; + DECL_SOURCE_FILE (decl) = filename; + add_tree (decl); + return decl; + } + + decl = lookup_label (name); /* After labels, make any new cleanups go into their own new (temporary) binding contour. */ @@ -3953,7 +4251,7 @@ define_label (filename, line, name) } else { - tree uses, prev; + struct named_label_list *uses, *prev; int identified = 0; /* Mark label as having been defined. */ @@ -3962,17 +4260,17 @@ define_label (filename, line, name) DECL_SOURCE_FILE (decl) = filename; DECL_SOURCE_LINE (decl) = line; - for (prev = NULL_TREE, uses = named_label_uses; - uses; - prev = uses, uses = TREE_CHAIN (uses)) - if (TREE_VALUE (uses) == decl) + prev = NULL; + uses = named_label_uses; + while (uses != NULL) + if (uses->label_decl == decl) { struct binding_level *b = current_binding_level; while (b) { tree new_decls = b->names; - tree old_decls = ((tree)b == TREE_TYPE (uses) - ? TREE_PURPOSE (uses) : NULL_TREE); + tree old_decls = (b == uses->binding_level) + ? uses->names_in_scope : NULL_TREE; while (new_decls != old_decls) { if (TREE_CODE (new_decls) == VAR_DECL @@ -3985,23 +4283,35 @@ define_label (filename, line, name) && DECL_INITIAL (new_decls) != error_mark_node) || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))) { - if (! identified) - cp_error ("jump to label `%D'", decl); - identified = 1; + if (! identified) + { + cp_error ("jump to label `%D'", decl); + error_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); } new_decls = TREE_CHAIN (new_decls); } - if ((tree)b == TREE_TYPE (uses)) + if (b == uses->binding_level) break; b = b->level_chain; } - if (prev) - TREE_CHAIN (prev) = TREE_CHAIN (uses); + if (prev != NULL) + prev->next = uses->next; else - named_label_uses = TREE_CHAIN (uses); + named_label_uses = uses->next; + + uses = uses->next; + } + else + { + prev = uses; + uses = uses->next; } current_function_return_value = NULL_TREE; return decl; @@ -4034,6 +4344,7 @@ pop_switch () /* Same, but for CASE labels. If DECL is NULL_TREE, it's the default. */ /* XXX Note decl is never actually used. (bpk) */ + void define_case_label (decl) tree decl; @@ -4139,8 +4450,8 @@ storetags (tags) static tree lookup_tag (form, name, binding_level, thislevel_only) enum tree_code form; - struct binding_level *binding_level; tree name; + struct binding_level *binding_level; int thislevel_only; { register struct binding_level *level; @@ -4156,6 +4467,27 @@ lookup_tag (form, name, binding_level, thislevel_only) if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name) return TREE_VALUE (tail); } + 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)); + /* If it has an original type, it is a typedef, and we + should not return it. */ + if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old))) + old = NULL_TREE; + if (old && TREE_CODE (old) != form + && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL)) + { + cp_error ("`%#D' redeclared as %C", old, form); + return NULL_TREE; + } + if (old) + return old; + if (thislevel_only || tail == global_namespace) + return NULL_TREE; + } else for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) { @@ -4165,21 +4497,30 @@ lookup_tag (form, name, binding_level, thislevel_only) /* Should tighten this up; it'll probably permit UNION_TYPE and a struct template, for example. */ if (code != form - && !(form != ENUMERAL_TYPE - && (code == TEMPLATE_DECL - || code == UNINSTANTIATED_P_TYPE))) - + && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL)) { /* Definition isn't the kind we were looking for. */ cp_error ("`%#D' redeclared as %C", TREE_VALUE (tail), form); + return NULL_TREE; } return TREE_VALUE (tail); } } if (thislevel_only && ! level->tag_transparent) - return NULL_TREE; - if (current_class_type && level->level_chain == global_binding_level) + { + 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); + } + return NULL_TREE; + } + if (current_class_type && level->level_chain->namespace_p) { /* Try looking in this class's tags before heading into global binding level. */ @@ -4208,6 +4549,7 @@ lookup_tag (form, name, binding_level, thislevel_only) { cp_error ("`%#D' redeclared as %C in class scope", TREE_VALUE (tail), form); + return NULL_TREE; } return TREE_VALUE (tail); } @@ -4218,7 +4560,7 @@ lookup_tag (form, name, binding_level, thislevel_only) if (TYPE_SIZE (context) == NULL_TREE) goto no_context; /* Go to next enclosing type, if any. */ - context = DECL_CONTEXT (TYPE_NAME (context)); + context = DECL_CONTEXT (TYPE_MAIN_DECL (context)); break; case 'd': context = DECL_CONTEXT (context); @@ -4235,12 +4577,14 @@ lookup_tag (form, name, binding_level, thislevel_only) return NULL_TREE; } +#if 0 void set_current_level_tags_transparency (tags_transparent) int tags_transparent; { current_binding_level->tag_transparent = tags_transparent; } +#endif /* Given a type, find the tag that was defined for it and return the tag name. Otherwise return 0. However, the value can never be 0 @@ -4271,36 +4615,10 @@ lookup_tag_reverse (type, name) } return NULL_TREE; } - -/* Given type TYPE which was not declared in C++ language context, - attempt to find a name by which it is referred. */ -tree -typedecl_for_tag (tag) - tree tag; -{ - struct binding_level *b = current_binding_level; - - if (TREE_CODE (TYPE_NAME (tag)) == TYPE_DECL) - return TYPE_NAME (tag); - - while (b) - { - tree decls = b->names; - while (decls) - { - if (TREE_CODE (decls) == TYPE_DECL && TREE_TYPE (decls) == tag) - break; - decls = TREE_CHAIN (decls); - } - if (decls) - return decls; - b = b->level_chain; - } - return NULL_TREE; -} /* Lookup TYPE in CONTEXT (a chain of nested types or a FUNCTION_DECL). Return the type value, or NULL_TREE if not found. */ + static tree lookup_nested_type (type, context) tree type; @@ -4341,157 +4659,453 @@ lookup_nested_type (type, context) } /* Look up NAME in the NAMESPACE. */ + tree lookup_namespace_name (namespace, name) tree namespace, name; { - struct binding_level *b = (struct binding_level *)NAMESPACE_LEVEL (namespace); - tree x; + struct tree_binding _b; + tree val; + + my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373); + + val = binding_init (&_b); + if (!qualified_lookup_using_namespace (name, namespace, val, 0)) + return error_mark_node; - for (x = NULL_TREE; b && !x; b = b->level_chain) + if (BINDING_VALUE (val)) { - for (x = b->names; x; x = TREE_CHAIN (x)) - if (DECL_NAME (x) == name || DECL_ASSEMBLER_NAME (x) == name) - break; - /* Must find directly in the namespace. */ - break; - } - return x; -} + val = BINDING_VALUE (val); -/* 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 - such declaration, or return a TREE_LIST with all the overloaded - definitions if there are many, or return 0 if it is undefined. + /* 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); + return val; + } - If PREFER_TYPE is > 0, we prefer TYPE_DECLs. - If PREFER_TYPE is -2, we're being called from yylex(). (UGLY) - Otherwise we prefer non-TYPE_DECLs. */ + cp_error ("`%D' undeclared in namespace `%D'", name, namespace); + return error_mark_node; +} tree -lookup_name_real (name, prefer_type, nonclass) - tree name; - int prefer_type, nonclass; +make_typename_type (context, name) + tree context, name; { - register tree val; - int yylex = 0; - tree from_obj = NULL_TREE; + tree t, d; + tree fullname; - if (prefer_type == -2) - { - extern int looking_for_typename; - tree type; + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + name = TYPE_IDENTIFIER (name); + else if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); - yylex = 1; - prefer_type = looking_for_typename; + fullname = name; - if (got_scope) - type = got_scope; - else if (got_object != error_mark_node) - type = got_object; - - if (type) + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + name = TREE_OPERAND (name, 0); + if (TREE_CODE (name) == TEMPLATE_DECL) + name = TREE_OPERAND (fullname, 0) = DECL_NAME (name); + } + if (TREE_CODE (name) != IDENTIFIER_NODE) + my_friendly_abort (2000); + + if (! uses_template_parms (context) + || currently_open_class (context)) + { + if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR) { - if (type == error_mark_node) - return error_mark_node; - else if (type == void_type_node) - val = IDENTIFIER_GLOBAL_VALUE (name); - else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM - /* TFIXME -- don't do this for UPTs in new model. */ - || TREE_CODE (type) == UNINSTANTIATED_P_TYPE) - { - if (prefer_type > 0) - val = create_nested_upt (type, name); - else - val = NULL_TREE; - } - else if (TREE_CODE (type) == NAMESPACE_DECL) - { - val = lookup_namespace_name (type, name); - } - else if (! IS_AGGR_TYPE (type)) - /* Someone else will give an error about this if needed. */ - val = NULL_TREE; - else if (TYPE_BEING_DEFINED (type)) + 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) { - 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 - && CLASSTYPE_LOCAL_TYPEDECLS (type)) - val = lookup_field (type, name, 0, 1); + cp_error ("no class template named `%#T' in `%#T'", + name, context); + return error_mark_node; } - else if (type == current_class_type) - val = IDENTIFIER_CLASS_VALUE (name); - else - val = lookup_field (type, name, 0, prefer_type); + + return lookup_template_class (t, TREE_OPERAND (fullname, 1), + NULL_TREE, context); } else - val = NULL_TREE; - + { + 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 (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; +} + +/* Select the right _DECL from multiple choices. */ + +static tree +select_decl (binding, flags) + tree binding; + int flags; +{ + tree val; + val = BINDING_VALUE (binding); + if (LOOKUP_NAMESPACES_ONLY (flags)) + { + /* We are not interested in types. */ + if (val && TREE_CODE (val) == NAMESPACE_DECL) + return val; + return NULL_TREE; + } + + /* If we could have a type and + we have nothing or we need a type and have none. */ + if (BINDING_TYPE (binding) + && (!val || ((flags & LOOKUP_PREFER_TYPES) + && TREE_CODE (val) != TYPE_DECL))) + 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)) + val = NULL_TREE; + + return val; +} + +/* Unscoped lookup of a global, iterate over namespaces, considering + using namespace statements. */ + +static tree +unqualified_namespace_lookup (name, flags) + tree name; + int flags; +{ + struct tree_binding _binding; + tree b = binding_init (&_binding); + tree initial = current_decl_namespace(); + tree scope = initial; + tree siter; + struct binding_level *level; + tree val = NULL_TREE; + + while (!val) + { + val = binding_for_name (name, scope); + + /* Initialize binding for this context. */ + BINDING_VALUE (b) = BINDING_VALUE (val); + BINDING_TYPE (b) = BINDING_TYPE (val); + + /* Add all _DECLs seen through local using-directives. */ + for (level = current_binding_level; + !level->namespace_p; + level = level->level_chain) + if (!lookup_using_namespace (name, b, level->using_directives, + scope, flags)) + /* Give up because of error. */ + return NULL_TREE; + + /* Add all _DECLs seen through global using-directives. */ + /* XXX local and global using lists should work equally. */ + siter = initial; + while (1) + { + if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), + scope, flags)) + /* Give up because of error. */ + return NULL_TREE; + if (siter == scope) break; + siter = CP_DECL_CONTEXT (siter); + } + + val = select_decl (b, flags); + if (scope == global_namespace) + break; + scope = CP_DECL_CONTEXT (scope); + } + return val; +} + +/* Combine prefer_type and namespaces_only into flags. */ + +static int +lookup_flags (prefer_type, namespaces_only) + int prefer_type, namespaces_only; +{ + if (namespaces_only) + return LOOKUP_PREFER_NAMESPACES; + if (prefer_type > 1) + return LOOKUP_PREFER_TYPES; + if (prefer_type > 0) + return LOOKUP_PREFER_BOTH; + return 0; +} + +/* Given a lookup that returned VAL, use FLAGS to decide if we want to + ignore it or not. Subroutine of lookup_name_real. */ + +static tree +qualify_lookup (val, flags) + tree val; + int flags; +{ + if (val == NULL_TREE) + return val; + if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL) + return val; + if ((flags & LOOKUP_PREFER_TYPES) + && (TREE_CODE (val) == TYPE_DECL + || ((flags & LOOKUP_TEMPLATES_EXPECTED) + && DECL_CLASS_TEMPLATE_P (val)))) + return val; + if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES)) + return NULL_TREE; + return val; +} + +/* 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 + such declaration, or return a TREE_LIST with all the overloaded + definitions if there are many, or return 0 if it is undefined. + + If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces. + If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces). + If PREFER_TYPE is -2, we're being called from yylex(). (UGLY) + Otherwise we prefer non-TYPE_DECLs. + + If NONCLASS is non-zero, we don't look for the NAME in class scope, + using IDENTIFIER_CLASS_VALUE. */ + +static tree +lookup_name_real (name, prefer_type, nonclass, namespaces_only) + tree name; + int prefer_type, nonclass, namespaces_only; +{ + register tree val; + int yylex = 0; + tree from_obj = NULL_TREE; + tree locval, classval; + int flags; + + /* Hack: copy flag set by parser, if set. */ + if (only_namespace_names) + namespaces_only = 1; + + if (prefer_type == -2) + { + extern int looking_for_typename; + tree type = NULL_TREE; + + yylex = 1; + 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; + + /* std:: becomes :: for now. */ + if (got_scope == std_node) + got_scope = void_type_node; + if (got_scope) - goto done; + type = got_scope; + else if (got_object != error_mark_node) + type = got_object; + + if (type) + { + if (type == error_mark_node) + return error_mark_node; + if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type)) + type = TREE_TYPE (type); + + if (TYPE_P (type)) + type = complete_type (type); + + if (TREE_CODE (type) == VOID_TYPE) + type = global_namespace; + if (TREE_CODE (type) == NAMESPACE_DECL) + { + struct tree_binding b; + val = binding_init (&b); + if (!qualified_lookup_using_namespace (name, type, val, flags)) + return NULL_TREE; + val = select_decl (val, flags); + } + else if (! IS_AGGR_TYPE (type) + || TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM + || 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 + val = lookup_member (type, name, 0, prefer_type); + } + else + val = NULL_TREE; - /* This special lookup only applies to types. */ - else if (got_object && val && TREE_CODE (val) == TYPE_DECL) + if (got_scope) + goto done; + else if (got_object && val) from_obj = val; } - - if (current_binding_level != global_binding_level - && IDENTIFIER_LOCAL_VALUE (name)) - val = IDENTIFIER_LOCAL_VALUE (name); + 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. */ - else if (current_class_type && ! nonclass) + if (current_class_type && ! nonclass) { - val = IDENTIFIER_CLASS_VALUE (name); - if (val == NULL_TREE - && TYPE_BEING_DEFINED (current_class_type) - && CLASSTYPE_LOCAL_TYPEDECLS (current_class_type)) + 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. */ - val = lookup_field (current_class_type, name, 0, 1); + 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); /* 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 (val == NULL_TREE) - val = lookup_nested_field (name, ! yylex); + if (classval == NULL_TREE) + classval = lookup_nested_field (name, ! yylex); - if (val == NULL_TREE) - val = IDENTIFIER_GLOBAL_VALUE (name); + classval = qualify_lookup (classval, flags); } + + if (locval && classval) + { + if (current_scope () == current_function_decl + && ! hack_decl_function_context (current_function_decl)) + /* Not in a nested function. */ + val = locval; + else + { + /* 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; + } + } + else if (locval) + val = locval; + else if (classval) + val = classval; else - val = IDENTIFIER_GLOBAL_VALUE (name); + val = unqualified_namespace_lookup (name, flags); done: if (val) { + /* This should only warn about types used in qualified-ids. */ if (from_obj && from_obj != val) - cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope", - got_object); + { + if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL + && TREE_CODE (val) == TYPE_DECL + && TREE_TYPE (from_obj) != TREE_TYPE (val)) + { + cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')", + name, got_object, TREE_TYPE (from_obj)); + cp_pedwarn (" does not match lookup in the current scope (`%#T')", + TREE_TYPE (val)); + } + + /* We don't change val to from_obj if got_object depends on + template parms because that breaks implicit typename for + destructor calls. */ + if (! uses_template_parms (got_object)) + 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_NAME (IDENTIFIER_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); } else if (from_obj) val = from_obj; @@ -4503,7 +5117,23 @@ tree lookup_name_nonclass (name) tree name; { - return lookup_name_real (name, 0, 1); + return lookup_name_real (name, 0, 1, 0); +} + +tree +lookup_function_nonclass (name, args) + tree name; + tree args; +{ + return lookup_arg_dependent (name, lookup_name_nonclass (name), args); +} + +tree +lookup_name_namespace_only (name) + tree name; +{ + /* type-or-namespace, nonclass, namespace_only */ + return lookup_name_real (name, 1, 1, 1); } tree @@ -4511,7 +5141,7 @@ lookup_name (name, prefer_type) tree name; int prefer_type; { - return lookup_name_real (name, prefer_type, 0); + return lookup_name_real (name, prefer_type, 0, 0); } /* Similar to `lookup_name' but look only at current binding level. */ @@ -4522,9 +5152,9 @@ lookup_name_current_level (name) { register tree t = NULL_TREE; - if (current_binding_level == global_binding_level) + if (current_binding_level->namespace_p) { - t = IDENTIFIER_GLOBAL_VALUE (name); + t = IDENTIFIER_NAMESPACE_VALUE (name); /* extern "C" function() */ if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST) @@ -4535,20 +5165,57 @@ lookup_name_current_level (name) struct binding_level *b = current_binding_level; while (1) { - for (t = b->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name) - goto out; + if (purpose_member (name, b->shadowed)) + return IDENTIFIER_LOCAL_VALUE (name); + if (b->keep == 2) + b = b->level_chain; + else + break; + } + } + + return t; +} + +/* Like lookup_name_current_level, but for types. */ + +tree +lookup_type_current_level (name) + tree name; +{ + register tree t = NULL_TREE; + + my_friendly_assert (! current_binding_level->namespace_p, 980716); + + if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE + && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node) + { + struct binding_level *b = current_binding_level; + while (1) + { + if (purpose_member (name, b->type_shadowed)) + return REAL_IDENTIFIER_TYPE_VALUE (name); if (b->keep == 2) b = b->level_chain; else break; } - out: - ; } return t; } + +void +begin_only_namespace_names () +{ + only_namespace_names = 1; +} + +void +end_only_namespace_names () +{ + only_namespace_names = 0; +} /* Arrange for the user to get a source line number, even when the compiler is going down in flames, so that she at least has a @@ -4559,7 +5226,7 @@ lookup_name_current_level (name) static void signal_catch (sig) - int sig; + int sig ATTRIBUTE_UNUSED; { signal (SIGSEGV, SIG_DFL); #ifdef SIGIOT @@ -4577,10 +5244,13 @@ signal_catch (sig) my_friendly_abort (0); } +#if 0 +/* Unused -- brendan 970107 */ /* Array for holding types considered "built-in". These types are output in the module in which `main' is defined. */ static tree *builtin_type_tdescs_arr; static int builtin_type_tdescs_len, builtin_type_tdescs_max; +#endif /* Push the declarations of builtin types into the namespace. RID_INDEX, if < RID_MAX is the index of the builtin type @@ -4594,7 +5264,7 @@ record_builtin_type (rid_index, name, type) tree type; { tree rname = NULL_TREE, tname = NULL_TREE; - tree tdecl; + tree tdecl = NULL_TREE; if ((int) rid_index < (int) RID_MAX) rname = ridpointers[(int) rid_index]; @@ -4605,84 +5275,77 @@ record_builtin_type (rid_index, name, type) if (tname) { -#if 0 /* not yet, should get fixed properly later */ - tdecl = pushdecl (make_type_decl (tname, type)); -#else tdecl = pushdecl (build_decl (TYPE_DECL, tname, type)); -#endif set_identifier_type_value (tname, NULL_TREE); if ((int) rid_index < (int) RID_MAX) - IDENTIFIER_GLOBAL_VALUE (tname) = tdecl; + /* Built-in types live in the global namespace. */ + SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl); } if (rname != NULL_TREE) { if (tname != NULL_TREE) { set_identifier_type_value (rname, NULL_TREE); - IDENTIFIER_GLOBAL_VALUE (rname) = tdecl; + SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl); } else { -#if 0 /* not yet, should get fixed properly later */ - tdecl = pushdecl (make_type_decl (rname, type)); -#else tdecl = pushdecl (build_decl (TYPE_DECL, rname, type)); -#endif set_identifier_type_value (rname, NULL_TREE); } } +} - if (flag_rtti) - { - if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max) - { - builtin_type_tdescs_max *= 2; - builtin_type_tdescs_arr - = (tree *)xrealloc (builtin_type_tdescs_arr, - builtin_type_tdescs_max * sizeof (tree)); - } - builtin_type_tdescs_arr[builtin_type_tdescs_len++] = type; - if (TREE_CODE (type) != POINTER_TYPE) - { - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_pointer_type (type); - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_pointer_type (build_type_variant (type, 1, 0)); - } - if (TREE_CODE (type) != VOID_TYPE) - { - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_reference_type (type); - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_reference_type (build_type_variant (type, 1, 0)); - } +/* Record one of the standard Java types. + * Declare it as having the given NAME. + * If SIZE > 0, it is the size of one of the integral types; + * otherwise it is the negative of the size of one of the other types. */ + +static tree +record_builtin_java_type (name, size) + char *name; + int size; +{ + tree type, decl; + if (size > 0) + type = make_signed_type (size); + else if (size > -32) + { /* "__java_char" or ""__java_boolean". */ + type = make_unsigned_type (-size); + /*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/ + } + else + { /* "__java_float" or ""__java_double". */ + type = make_node (REAL_TYPE); + TYPE_PRECISION (type) = - size; + layout_type (type); } + record_builtin_type (RID_MAX, name, type); + decl = TYPE_NAME (type); + DECL_IGNORED_P (decl) = 1; + TYPE_FOR_JAVA (type) = 1; + return type; } +/* Push a type into the namespace so that the back-ends ignore it. */ + static void -output_builtin_tdesc_entries () +record_unknown_type (type, name) + tree type; + char *name; { - extern struct obstack permanent_obstack; - - /* If there's more than one main in this file, don't crash. */ - if (builtin_type_tdescs_arr == 0) - return; - - push_obstacks (&permanent_obstack, &permanent_obstack); - while (builtin_type_tdescs_len > 0) - { - tree type = builtin_type_tdescs_arr[--builtin_type_tdescs_len]; - tree tdesc = build_t_desc (type, 0); - TREE_ASM_WRITTEN (tdesc) = 0; - build_t_desc (type, 2); - } - free (builtin_type_tdescs_arr); - builtin_type_tdescs_arr = 0; - pop_obstacks (); -} + tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type)); + /* Make sure the "unknown type" typedecl gets ignored for debug info. */ + DECL_IGNORED_P (decl) = 1; + TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; + TYPE_SIZE (type) = TYPE_SIZE (void_type_node); + TYPE_ALIGN (type) = 1; + TYPE_MODE (type) = TYPE_MODE (void_type_node); +} /* Push overloaded decl, in global scope, with one argument so it can be used as a callback from define_function. */ + static void push_overloaded_decl_1 (x) tree x; @@ -4690,18 +5353,16 @@ push_overloaded_decl_1 (x) push_overloaded_decl (x, 0); } -#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ - define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME) - #ifdef __GNUC__ __inline #endif -tree auto_function (name, type, code) +tree +auto_function (name, type, code) tree name, type; enum built_in_function code; { return define_function - (IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1, + (IDENTIFIER_POINTER (name), type, code, push_overloaded_decl_1, IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type), 0))); } @@ -4714,25 +5375,33 @@ tree auto_function (name, type, code) void init_decl_processing () { - tree decl; - register tree endlink, int_endlink, double_endlink, ptr_endlink; + register tree endlink, int_endlink, double_endlink, unsigned_endlink; tree fields[20]; - /* Either char* or void*. */ - tree traditional_ptr_type_node; /* Data type of memcpy. */ - tree memcpy_ftype; -#if 0 /* Not yet. */ - /* Data type of strncpy. */ - tree strncpy_ftype; -#endif + tree memcpy_ftype, strlen_ftype; 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; /* Have to make these distinct before we try using them. */ lang_name_cplusplus = get_identifier ("C++"); lang_name_c = get_identifier ("C"); + lang_name_java = get_identifier ("Java"); + + /* Enter the global namespace. */ + my_friendly_assert (global_namespace == NULL_TREE, 375); + my_friendly_assert (current_lang_name == NULL_TREE, 375); + current_lang_name = lang_name_cplusplus; + push_namespace (get_identifier ("::")); + global_namespace = current_namespace; + current_lang_name = NULL_TREE; if (flag_strict_prototype == 2) { @@ -4747,19 +5416,20 @@ init_decl_processing () current_function_decl = NULL_TREE; named_labels = NULL_TREE; - named_label_uses = NULL_TREE; + named_label_uses = NULL; 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. */ + around compiler bugs. */ signal (SIGSEGV, signal_catch); /* We will also catch aborts in the back-end through signal_catch and give the user a chance to see where the error might be, and to defeat aborts in the back-end when there have been errors previously in their - code. */ + code. */ #ifdef SIGIOT signal (SIGIOT, signal_catch); #endif @@ -4772,13 +5442,15 @@ 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); - if (flag_rtti) - { - builtin_type_tdescs_max = 100; - builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree)); - } /* Must lay these out before anything else gets laid out. */ error_mark_node = make_node (ERROR_MARK); @@ -4790,9 +5462,14 @@ init_decl_processing () /* Make the binding_level structure for global names. */ pushlevel (0); global_binding_level = current_binding_level; + /* The global level is the namespace level of ::. */ + NAMESPACE_LEVEL (global_namespace) = global_binding_level; + declare_namespace_level (); this_identifier = get_identifier (THIS_NAME); in_charge_identifier = get_identifier (IN_CHARGE_NAME); + ctor_identifier = get_identifier (CTOR_NAME); + dtor_identifier = get_identifier (DTOR_NAME); pfn_identifier = get_identifier (VTABLE_PFN_NAME); index_identifier = get_identifier (VTABLE_INDEX_NAME); delta_identifier = get_identifier (VTABLE_DELTA_NAME); @@ -4813,10 +5490,10 @@ init_decl_processing () /* Define `char', which is like either `signed char' or `unsigned char' but not the same as either. */ - char_type_node = - (flag_signed_char - ? make_signed_type (CHAR_TYPE_SIZE) - : make_unsigned_type (CHAR_TYPE_SIZE)); + char_type_node + = (flag_signed_char + ? make_signed_type (CHAR_TYPE_SIZE) + : make_unsigned_type (CHAR_TYPE_SIZE)); record_builtin_type (RID_CHAR, "char", char_type_node); long_integer_type_node = make_signed_type (LONG_TYPE_SIZE); @@ -4838,32 +5515,21 @@ init_decl_processing () record_builtin_type (RID_MAX, "long long unsigned", long_long_unsigned_type_node); - /* `unsigned long' is the standard type for sizeof. - Traditionally, use a signed type. - Note that stddef.h uses `unsigned long', - and this must agree, even of long and int are the same size. */ - sizetype - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))); - if (flag_traditional && TREE_UNSIGNED (sizetype)) - sizetype = signed_type (sizetype); - - ptrdiff_type_node - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE))); - - TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype; - short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); record_builtin_type (RID_SHORT, "short int", short_integer_type_node); short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node); record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node); + /* `unsigned long' is the standard type for sizeof. + Note that stddef.h uses `unsigned long', + and this must agree, even if long and int are the same size. */ + set_sizetype + (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)))); + + ptrdiff_type_node + = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE))); + /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); record_builtin_type (RID_MAX, "signed char", signed_char_type_node); @@ -4879,6 +5545,8 @@ 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)); + intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node)); 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)); @@ -4887,6 +5555,8 @@ 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)); + unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node)); float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; @@ -4906,6 +5576,39 @@ init_decl_processing () record_builtin_type (RID_MAX, "long double", long_double_type_node); layout_type (long_double_type_node); + complex_integer_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), + complex_integer_type_node)); + TREE_TYPE (complex_integer_type_node) = integer_type_node; + layout_type (complex_integer_type_node); + + complex_float_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"), + complex_float_type_node)); + TREE_TYPE (complex_float_type_node) = float_type_node; + layout_type (complex_float_type_node); + + complex_double_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"), + complex_double_type_node)); + TREE_TYPE (complex_double_type_node) = double_type_node; + layout_type (complex_double_type_node); + + complex_long_double_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"), + complex_long_double_type_node)); + TREE_TYPE (complex_long_double_type_node) = long_double_type_node; + layout_type (complex_long_double_type_node); + + java_byte_type_node = record_builtin_java_type ("__java_byte", 8); + java_short_type_node = record_builtin_java_type ("__java_short", 16); + java_int_type_node = record_builtin_java_type ("__java_int", 32); + java_long_type_node = record_builtin_java_type ("__java_long", 64); + java_float_type_node = record_builtin_java_type ("__java_float", -32); + java_double_type_node = record_builtin_java_type ("__java_double", -64); + java_char_type_node = record_builtin_java_type ("__java_char", -16); + java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1); + integer_zero_node = build_int_2 (0, 0); TREE_TYPE (integer_zero_node) = integer_type_node; integer_one_node = build_int_2 (1, 0); @@ -4917,6 +5620,9 @@ init_decl_processing () boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE); TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); + TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0); + TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node; + TYPE_PRECISION (boolean_type_node) = 1; record_builtin_type (RID_BOOL, "bool", boolean_type_node); boolean_false_node = build_int_2 (0, 0); TREE_TYPE (boolean_false_node) = boolean_type_node; @@ -4927,6 +5633,9 @@ init_decl_processing () size_zero_node = size_int (0); size_one_node = size_int (1); + signed_size_zero_node = build_int_2 (0, 0); + TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype)); + void_type_node = make_node (VOID_TYPE); record_builtin_type (RID_VOID, NULL_PTR, void_type_node); layout_type (void_type_node); /* Uses integer_zero_node. */ @@ -4936,15 +5645,17 @@ init_decl_processing () null_pointer_node = build_int_2 (0, 0); TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node); layout_type (TREE_TYPE (null_pointer_node)); - + /* Used for expressions that do nothing, but are not errors. */ void_zero_node = build_int_2 (0, 0); TREE_TYPE (void_zero_node) = void_type_node; string_type_node = build_pointer_type (char_type_node); - const_string_type_node = - build_pointer_type (build_type_variant (char_type_node, 1, 0)); + const_string_type_node + = build_pointer_type (build_type_variant (char_type_node, 1, 0)); +#if 0 record_builtin_type (RID_MAX, NULL_PTR, string_type_node); +#endif /* Make a type to be the domain of a few array types whose domains don't really matter. @@ -4953,7 +5664,7 @@ init_decl_processing () initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */ array_domain_type = build_index_type (build_int_2 (200, 0)); - /* make a type for arrays of characters. + /* Make a type for arrays of characters. With luck nothing will ever really depend on the length of this array type. */ char_array_type_node @@ -4968,20 +5679,45 @@ init_decl_processing () default_function_type = build_function_type (integer_type_node, NULL_TREE); - build_pointer_type (default_function_type); ptr_type_node = build_pointer_type (void_type_node); - const_ptr_type_node = - build_pointer_type (build_type_variant (void_type_node, 1, 0)); + const_ptr_type_node + = build_pointer_type (build_type_variant (void_type_node, 1, 0)); +#if 0 record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node); +#endif endlink = void_list_node; int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); double_endlink = tree_cons (NULL_TREE, double_type_node, endlink); - ptr_endlink = tree_cons (NULL_TREE, ptr_type_node, endlink); + unsigned_endlink = tree_cons (NULL_TREE, unsigned_type_node, endlink); + + ptr_ftype = build_function_type (ptr_type_node, NULL_TREE); + ptr_ftype_unsigned = build_function_type (ptr_type_node, unsigned_endlink); + sizetype_endlink = tree_cons (NULL_TREE, sizetype, endlink); + /* We realloc here because sizetype could be int or unsigned. S'ok. */ + ptr_ftype_sizetype = build_function_type (ptr_type_node, sizetype_endlink); + + void_ftype = build_function_type (void_type_node, endlink); + void_ftype_int = build_function_type (void_type_node, int_endlink); + void_ftype_ptr + = build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink)); + void_ftype_ptr + = build_exception_variant (void_ftype_ptr, + tree_cons (NULL_TREE, NULL_TREE, NULL_TREE)); + + float_ftype_float + = build_function_type (float_type_node, + tree_cons (NULL_TREE, float_type_node, endlink)); double_ftype_double = build_function_type (double_type_node, double_endlink); + ldouble_ftype_ldouble + = build_function_type (long_double_type_node, + tree_cons (NULL_TREE, long_double_type_node, + endlink)); + double_ftype_double_double = build_function_type (double_type_node, tree_cons (NULL_TREE, double_type_node, @@ -4995,12 +5731,6 @@ init_decl_processing () tree_cons (NULL_TREE, long_integer_type_node, endlink)); - void_ftype_ptr_ptr_int - = build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, ptr_type_node, - int_endlink))); - int_ftype_cptr_cptr_sizet = build_function_type (integer_type_node, tree_cons (NULL_TREE, const_ptr_type_node, @@ -5009,12 +5739,6 @@ init_decl_processing () sizetype, endlink)))); - void_ftype_ptr_int_int - = build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, integer_type_node, - int_endlink))); - string_ftype_ptr_ptr /* strcpy prototype */ = build_function_type (string_type_node, tree_cons (NULL_TREE, string_type_node, @@ -5022,17 +5746,6 @@ init_decl_processing () const_string_type_node, endlink))); -#if 0 - /* Not yet. */ - strncpy_ftype /* strncpy prototype */ - = build_function_type (string_type_node, - tree_cons (NULL_TREE, string_type_node, - tree_cons (NULL_TREE, const_string_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)))); -#endif - int_ftype_string_string /* strcmp prototype */ = build_function_type (integer_type_node, tree_cons (NULL_TREE, const_string_type_node, @@ -5040,69 +5753,51 @@ init_decl_processing () const_string_type_node, endlink))); - sizet_ftype_string /* strlen prototype */ + strlen_ftype /* strlen prototype */ = build_function_type (sizetype, tree_cons (NULL_TREE, const_string_type_node, endlink)); - traditional_ptr_type_node - = (flag_traditional ? string_type_node : ptr_type_node); - memcpy_ftype /* memcpy prototype */ - = build_function_type (traditional_ptr_type_node, + = build_function_type (ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, const_ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)))); + sizetype_endlink))); if (flag_huge_objects) delta_type_node = long_integer_type_node; else delta_type_node = short_integer_type_node; - builtin_function ("__builtin_constant_p", int_ftype_int, + builtin_function ("__builtin_constant_p", default_function_type, BUILT_IN_CONSTANT_P, NULL_PTR); - builtin_return_address_fndecl = - builtin_function ("__builtin_return_address", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - unsigned_type_node, - endlink)), - BUILT_IN_RETURN_ADDRESS, NULL_PTR); + builtin_return_address_fndecl + = builtin_function ("__builtin_return_address", ptr_ftype_unsigned, + BUILT_IN_RETURN_ADDRESS, NULL_PTR); - builtin_function ("__builtin_frame_address", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - unsigned_type_node, - endlink)), + 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", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)), + builtin_function ("__builtin_alloca", ptr_ftype_sizetype, BUILT_IN_ALLOCA, "alloca"); + builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); /* Define alloca, ffs as builtins. Declare _exit just to mark it as volatile. */ if (! flag_no_builtin && !flag_no_nonansi_builtin) { - temp = builtin_function ("alloca", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)), + temp = builtin_function ("alloca", ptr_ftype_sizetype, BUILT_IN_ALLOCA, NULL_PTR); /* Suppress error if redefined as a non-function. */ DECL_BUILT_IN_NONANSI (temp) = 1; temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); /* Suppress error if redefined as a non-function. */ DECL_BUILT_IN_NONANSI (temp) = 1; - temp = builtin_function ("_exit", build_function_type (void_type_node, - int_endlink), + temp = builtin_function ("_exit", void_ftype_int, NOT_BUILT_IN, NULL_PTR); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; @@ -5110,65 +5805,48 @@ init_decl_processing () DECL_BUILT_IN_NONANSI (temp) = 1; } - builtin_function ("__builtin_abs", int_ftype_int, - BUILT_IN_ABS, NULL_PTR); - builtin_function ("__builtin_fabs", double_ftype_double, - BUILT_IN_FABS, NULL_PTR); + builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); + builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS, + NULL_PTR); + builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS, + NULL_PTR); + builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS, + NULL_PTR); builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR); - builtin_function ("__builtin_ffs", int_ftype_int, - BUILT_IN_FFS, NULL_PTR); - builtin_function ("__builtin_fsqrt", double_ftype_double, - BUILT_IN_FSQRT, NULL_PTR); - builtin_function ("__builtin_sin", double_ftype_double, - BUILT_IN_SIN, "sin"); - builtin_function ("__builtin_cos", double_ftype_double, - BUILT_IN_COS, "cos"); - builtin_function ("__builtin_saveregs", - build_function_type (ptr_type_node, NULL_TREE), + builtin_function ("__builtin_saveregs", ptr_ftype, BUILT_IN_SAVEREGS, NULL_PTR); -/* EXPAND_BUILTIN_VARARGS is obsolete. */ -#if 0 - builtin_function ("__builtin_varargs", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)), - BUILT_IN_VARARGS, NULL_PTR); -#endif builtin_function ("__builtin_classify_type", default_function_type, BUILT_IN_CLASSIFY_TYPE, NULL_PTR); - builtin_function ("__builtin_next_arg", - build_function_type (ptr_type_node, NULL_TREE), + builtin_function ("__builtin_next_arg", ptr_ftype, BUILT_IN_NEXT_ARG, NULL_PTR); - builtin_function ("__builtin_args_info", + builtin_function ("__builtin_args_info", int_ftype_int, + BUILT_IN_ARGS_INFO, NULL_PTR); + builtin_function ("__builtin_setjmp", build_function_type (integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink)), - BUILT_IN_ARGS_INFO, NULL_PTR); + BUILT_IN_SETJMP, NULL_PTR); + builtin_function ("__builtin_longjmp", + build_function_type (integer_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, + integer_type_node, + endlink))), + BUILT_IN_LONGJMP, NULL_PTR); /* Untyped call and return. */ - builtin_function ("__builtin_apply_args", - build_function_type (ptr_type_node, NULL_TREE), + builtin_function ("__builtin_apply_args", ptr_ftype, BUILT_IN_APPLY_ARGS, NULL_PTR); temp = tree_cons (NULL_TREE, build_pointer_type (build_function_type (void_type_node, NULL_TREE)), - tree_cons (NULL_TREE, - ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink))); + tree_cons (NULL_TREE, ptr_ftype_sizetype, NULL_TREE)); builtin_function ("__builtin_apply", build_function_type (ptr_type_node, temp), BUILT_IN_APPLY, NULL_PTR); - builtin_function ("__builtin_return", - build_function_type (void_type_node, - tree_cons (NULL_TREE, - ptr_type_node, - endlink)), + builtin_function ("__builtin_return", void_ftype_ptr, BUILT_IN_RETURN, NULL_PTR); /* Currently under experimentation. */ @@ -5180,47 +5858,64 @@ init_decl_processing () BUILT_IN_STRCMP, "strcmp"); builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, "strcpy"); -#if 0 - /* Not yet. */ - builtin_function ("__builtin_strncpy", strncpy_ftype, - BUILT_IN_STRNCPY, "strncpy"); -#endif - builtin_function ("__builtin_strlen", sizet_ftype_string, + builtin_function ("__builtin_strlen", strlen_ftype, BUILT_IN_STRLEN, "strlen"); + builtin_function ("__builtin_sqrtf", float_ftype_float, + BUILT_IN_FSQRT, "sqrtf"); + builtin_function ("__builtin_fsqrt", double_ftype_double, + BUILT_IN_FSQRT, NULL_PTR); + builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble, + BUILT_IN_FSQRT, "sqrtl"); + builtin_function ("__builtin_sinf", float_ftype_float, + BUILT_IN_SIN, "sinf"); + builtin_function ("__builtin_sin", double_ftype_double, + BUILT_IN_SIN, "sin"); + builtin_function ("__builtin_sinl", ldouble_ftype_ldouble, + BUILT_IN_SIN, "sinl"); + builtin_function ("__builtin_cosf", float_ftype_float, + BUILT_IN_COS, "cosf"); + builtin_function ("__builtin_cos", double_ftype_double, + BUILT_IN_COS, "cos"); + builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, + BUILT_IN_COS, "cosl"); if (!flag_no_builtin) { -#if 0 /* These do not work well with libg++. */ builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR); builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR); -#endif + builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR); + builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS, + NULL_PTR); builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR); builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, NULL_PTR); - builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR); + builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, + NULL_PTR); builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, NULL_PTR); -#if 0 - /* Not yet. */ - builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR); -#endif - builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR); + builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR); + builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR); + builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR); + builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT, + NULL_PTR); + builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR); builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR); + builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR); + builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR); builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR); + builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR); /* Declare these functions volatile to avoid spurious "control drops through" warnings. */ - temp = builtin_function ("abort", - build_function_type (void_type_node, endlink), + temp = builtin_function ("abort", void_ftype, NOT_BUILT_IN, NULL_PTR); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; /* Well, these are actually ANSI, but we can't set DECL_BUILT_IN on them... */ DECL_BUILT_IN_NONANSI (temp) = 1; - temp = builtin_function ("exit", build_function_type (void_type_node, - int_endlink), + temp = builtin_function ("exit", void_ftype_int, NOT_BUILT_IN, NULL_PTR); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; @@ -5230,42 +5925,39 @@ init_decl_processing () #if 0 /* Support for these has not been written in either expand_builtin or build_function_call. */ - builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0); - builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0); + builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR); + builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR); builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, - 0); - builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0); + NULL_PTR); + builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, + NULL_PTR); builtin_function ("__builtin_fmod", double_ftype_double_double, - BUILT_IN_FMOD, 0); + BUILT_IN_FMOD, NULL_PTR); builtin_function ("__builtin_frem", double_ftype_double_double, - BUILT_IN_FREM, 0); - builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, - 0); + BUILT_IN_FREM, NULL_PTR); + builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, + BUILT_IN_MEMSET, NULL_PTR); builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, - 0); + NULL_PTR); builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, - 0); + NULL_PTR); #endif /* C++ extensions */ unknown_type_node = make_node (UNKNOWN_TYPE); -#if 0 /* not yet, should get fixed properly later */ - pushdecl (make_type_decl (get_identifier ("unknown type"), - unknown_type_node)); -#else - decl = pushdecl (build_decl (TYPE_DECL, get_identifier ("unknown type"), - unknown_type_node)); - /* Make sure the "unknown type" typedecl gets ignored for debug info. */ - DECL_IGNORED_P (decl) = 1; - TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; -#endif - TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node); - TYPE_ALIGN (unknown_type_node) = 1; - TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node); + record_unknown_type (unknown_type_node, "unknown type"); + /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */ TREE_TYPE (unknown_type_node) = unknown_type_node; - /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */ + + if (flag_ansi) + TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0); + else + TREE_TYPE (null_node) = build_pointer_type (unknown_type_node); + + /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same + result. */ TYPE_POINTER_TO (unknown_type_node) = unknown_type_node; TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; @@ -5274,7 +5966,7 @@ init_decl_processing () TYPE_MAIN_VARIANT (opaque_type_node) = opaque_type_node; record_builtin_type (RID_MAX, 0, opaque_type_node); - /* This is special for C++ so functions can be overloaded. */ + /* This is special for C++ so functions can be overloaded. */ wchar_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE))); wchar_type_size = TYPE_PRECISION (wchar_type_node); @@ -5295,14 +5987,6 @@ init_decl_processing () wchar_array_type_node = build_array_type (wchar_type_node, array_domain_type); - /* This is a hack that should go away when we deliver the - real gc code. */ - if (flag_gc) - { - builtin_function ("__gc_main", default_function_type, NOT_BUILT_IN, 0); - pushdecl (lookup_name (get_identifier ("__gc_main"), 0)); - } - if (flag_vtable_thunks) { /* Make sure we get a unique function type, so we can give @@ -5381,254 +6065,79 @@ init_decl_processing () record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type); } -#if 0 - if (flag_rtti) - { - /* Must build __t_desc type. Currently, type descriptors look like this: - - struct __t_desc - { - const char *name; - int size; - int bits; - struct __t_desc *points_to; - int ivars_count, meths_count; - struct __i_desc *ivars[]; - struct __m_desc *meths[]; - struct __t_desc *parents[]; - struct __t_desc *vbases[]; - int offsets[]; - }; - - ...as per Linton's paper. */ - - __t_desc_type_node = make_lang_type (RECORD_TYPE); - __i_desc_type_node = make_lang_type (RECORD_TYPE); - __m_desc_type_node = make_lang_type (RECORD_TYPE); - __t_desc_array_type = - build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE); - __i_desc_array_type = - build_array_type (build_pointer_type (__i_desc_type_node), NULL_TREE); - __m_desc_array_type = - build_array_type (build_pointer_type (__m_desc_type_node), NULL_TREE); - - fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"), - string_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("size"), - unsigned_type_node); - fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"), - unsigned_type_node); - fields[3] = build_lang_field_decl (FIELD_DECL, - get_identifier ("points_to"), - build_pointer_type (__t_desc_type_node)); - fields[4] = build_lang_field_decl (FIELD_DECL, - get_identifier ("ivars_count"), - integer_type_node); - fields[5] = build_lang_field_decl (FIELD_DECL, - get_identifier ("meths_count"), - integer_type_node); - fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("ivars"), - build_pointer_type (__i_desc_array_type)); - fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("meths"), - build_pointer_type (__m_desc_array_type)); - fields[8] = build_lang_field_decl (FIELD_DECL, get_identifier ("parents"), - build_pointer_type (__t_desc_array_type)); - fields[9] = build_lang_field_decl (FIELD_DECL, get_identifier ("vbases"), - build_pointer_type (__t_desc_array_type)); - fields[10] = build_lang_field_decl (FIELD_DECL, get_identifier ("offsets"), - build_pointer_type (integer_type_node)); - finish_builtin_type (__t_desc_type_node, "__t_desc", fields, 10, integer_type_node); - - /* ivar descriptors look like this: - - struct __i_desc - { - const char *name; - int offset; - struct __t_desc *type; - }; - */ - - fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"), - string_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("offset"), - integer_type_node); - fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), - build_pointer_type (__t_desc_type_node)); - finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, - integer_type_node); - - /* method descriptors look like this: - - struct __m_desc - { - const char *name; - int vindex; - struct __t_desc *vcontext; - struct __t_desc *return_type; - void (*address)(); - short parm_count; - short required_parms; - struct __t_desc *parm_types[]; - }; - */ - - fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"), - string_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("vindex"), - integer_type_node); - fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("vcontext"), - build_pointer_type (__t_desc_type_node)); - fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"), - build_pointer_type (__t_desc_type_node)); - fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("address"), - build_pointer_type (default_function_type)); - fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_count"), - short_integer_type_node); - fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("required_parms"), - short_integer_type_node); - fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"), - build_pointer_type (build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE))); - finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, - integer_type_node); - } + std_node = build_decl (NAMESPACE_DECL, + get_identifier (flag_honor_std ? "fake std":"std"), + void_type_node); + pushdecl (std_node); - if (flag_rtti) - { - int i = builtin_type_tdescs_len; - while (i > 0) - { - tree tdesc = build_t_desc (builtin_type_tdescs_arr[--i], 0); - TREE_ASM_WRITTEN (tdesc) = 1; - TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1; - } - } -#endif /*flag_rtti*/ + global_type_node = make_node (LANG_TYPE); + record_unknown_type (global_type_node, "global type"); /* Now, C++. */ current_lang_name = lang_name_cplusplus; - auto_function (ansi_opname[(int) NEW_EXPR], - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, sizetype, - void_list_node)), - NOT_BUILT_IN); - auto_function (ansi_opname[(int) VEC_NEW_EXPR], - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, sizetype, - void_list_node)), - NOT_BUILT_IN); - auto_function (ansi_opname[(int) DELETE_EXPR], - build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - void_list_node)), - NOT_BUILT_IN); - auto_function (ansi_opname[(int) VEC_DELETE_EXPR], - build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - void_list_node)), - NOT_BUILT_IN); + { + tree bad_alloc_type_node, newtype, deltype; + 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); + if (flag_honor_std) + pop_namespace (); + newtype = build_exception_variant + (ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node)); + deltype = build_exception_variant + (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); + auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN); + } abort_fndecl - = define_function ("__pure_virtual", - build_function_type (void_type_node, void_list_node), + = define_function ("__pure_virtual", void_ftype, NOT_BUILT_IN, 0, 0); /* Perform other language dependent initializations. */ init_class_processing (); init_init_processing (); init_search_processing (); + if (flag_rtti) + init_rtti_processing (); - if (flag_handle_exceptions) + if (flag_exceptions) init_exception_processing (); - if (flag_gc) - init_gc_processing (); if (flag_no_inline) { flag_inline_functions = 0; -#if 0 - /* This causes unnecessary emission of inline functions. */ - flag_default_inline = 0; -#endif } - if (flag_cadillac) - init_cadillac (); + + if (! supports_one_only ()) + flag_weak = 0; /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ declare_function_name (); /* Prepare to check format strings against argument lists. */ init_function_format_info (); -} - -/* initialize type descriptor type node of various rtti type. */ - -int -init_type_desc() -{ - tree tdecl; - - tdecl = lookup_name (get_identifier ("type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __t_desc_type_node = TREE_TYPE(tdecl); - __tp_desc_type_node = build_pointer_type (__t_desc_type_node); - -#if 0 - tdecl = lookup_name (get_identifier ("__baselist_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __baselist_desc_type_node = TREE_TYPE (tdecl); -#endif - - tdecl = lookup_name (get_identifier ("__builtin_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __bltn_desc_type_node = TREE_TYPE (tdecl); - - tdecl = lookup_name (get_identifier ("__user_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __user_desc_type_node = TREE_TYPE (tdecl); - - tdecl = lookup_name (get_identifier ("__class_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __class_desc_type_node = TREE_TYPE (tdecl); - - tdecl = lookup_field (__class_desc_type_node, - get_identifier ("access_mode"), 0, 0); - if (tdecl == NULL_TREE) - return 0; - __access_mode_type_node = TREE_TYPE (tdecl); - - tdecl = lookup_name (get_identifier ("__attr_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __attr_desc_type_node = TREE_TYPE (tdecl); - - tdecl = lookup_name (get_identifier ("__pointer_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __ptr_desc_type_node = TREE_TYPE (tdecl); - tdecl = lookup_name (get_identifier ("__func_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __func_desc_type_node = TREE_TYPE (tdecl); + /* Show we use EH for cleanups. */ + using_eh_for_cleanups (); - tdecl = lookup_name (get_identifier ("__ptmf_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __ptmf_desc_type_node = TREE_TYPE (tdecl); + print_error_function = lang_print_error_function; + lang_get_alias_set = &c_get_alias_set; +} - tdecl = lookup_name (get_identifier ("__ptmd_type_info"), 0); - if (tdecl == NULL_TREE) - return 0; - __ptmd_desc_type_node = TREE_TYPE (tdecl); +/* Function to print any language-specific context for an error message. */ - return 1; +static void +lang_print_error_function (file) + char *file; +{ + default_print_error_function (file); + maybe_print_template_context (); } + /* Make 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. @@ -5642,7 +6151,7 @@ define_function (name, type, function_code, pfn, library_name) char *name; tree type; enum built_in_function function_code; - void (*pfn)(); + void (*pfn) PROTO((tree)); char *library_name; { tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type); @@ -5650,6 +6159,9 @@ define_function (name, type, function_code, pfn, library_name) TREE_PUBLIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; + my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392); + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME, we cannot change DECL_ASSEMBLER_NAME until we have installed this function in the namespace. */ @@ -5693,10 +6205,20 @@ shadow_tag (declspecs) code = TREE_CODE (value); if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE) { - my_friendly_assert (TYPE_NAME (value) != NULL_TREE, 261); + my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261); - if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0) - cp_error ("forward declaration of `%#T'", value); + if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value)) + { + 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); + } t = value; ok_code = code; @@ -5724,16 +6246,38 @@ shadow_tag (declspecs) || (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 (TYPE_FIELDS (t)) { tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, - NULL_TREE, NULL_TREE); + NULL_TREE); finish_anon_union (decl); } - else - error ("anonymous union cannot have a function member"); } else { @@ -5754,7 +6298,7 @@ shadow_tag (declspecs) } if (found_tag == 0) - pedwarn ("abstract declarator used as declaration"); + cp_error ("abstract declarator used as declaration"); else if (found_tag > 1) pedwarn ("multiple types in one declaration"); } @@ -5770,7 +6314,7 @@ groktypename (typename) return typename; return grokdeclarator (TREE_VALUE (typename), TREE_PURPOSE (typename), - TYPENAME, 0, NULL_TREE, NULL_TREE); + TYPENAME, 0, NULL_TREE); } /* Decode a declarator in an ordinary declaration or data definition. @@ -5793,10 +6337,10 @@ groktypename (typename) int debug_temp_inits = 1; tree -start_decl (declarator, declspecs, initialized, raises) +start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) tree declarator, declspecs; int initialized; - tree raises; + tree attributes, prefix_attributes; { register tree decl; register tree type, tem; @@ -5804,9 +6348,12 @@ start_decl (declarator, declspecs, initialized, raises) extern int have_extern_spec; extern int used_extern_spec; +#if 0 + /* See code below that used this. */ int init_written = initialized; +#endif - /* This should only be done once on the top most decl. */ + /* This should only be done once on the top most decl. */ if (have_extern_spec && !used_extern_spec) { declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), @@ -5814,16 +6361,16 @@ start_decl (declarator, declspecs, initialized, raises) used_extern_spec = 1; } - decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises, + decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, NULL_TREE); - if (decl == NULL_TREE || decl == void_type_node) + if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE) return NULL_TREE; type = TREE_TYPE (decl); /* Don't lose if destructors must be executed at file-level. */ - if (TREE_STATIC (decl) - && TYPE_NEEDS_DESTRUCTOR (type) + if (! processing_template_decl && TREE_STATIC (decl) + && TYPE_NEEDS_DESTRUCTOR (complete_type (type)) && !TREE_PERMANENT (decl)) { push_obstacks (&permanent_obstack, &permanent_obstack); @@ -5841,60 +6388,22 @@ start_decl (declarator, declspecs, initialized, raises) pop_obstacks (); } - /* Corresponding pop_obstacks is done in `cp_finish_decl'. */ - push_obstacks_nochange (); - context = (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) ? DECL_CLASS_CONTEXT (decl) : DECL_CONTEXT (decl); - if (processing_template_decl) + if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL + && context != current_namespace && TREE_CODE (decl) == VAR_DECL) { - tree d; - if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* Declarator is a call_expr; extract arguments from it, since - grokdeclarator didn't do it. */ - tree args; - args = copy_to_permanent (last_function_parms); - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) - { - tree t = TREE_TYPE (decl); - - t = TYPE_METHOD_BASETYPE (t); /* type method belongs to */ - if (TREE_CODE (t) != UNINSTANTIATED_P_TYPE) - { - t = build_pointer_type (t); /* base type of `this' */ -#if 1 - /* I suspect this is wrong. */ - t = build_type_variant (t, flag_this_is_variable <= 0, - 0); /* type of `this' */ -#else - t = build_type_variant (t, 0, 0); /* type of `this' */ -#endif - t = build (PARM_DECL, t, this_identifier); - TREE_CHAIN (t) = args; - args = t; - } - } - DECL_ARGUMENTS (decl) = args; - } - d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl)); - TREE_PUBLIC (d) = TREE_PUBLIC (decl); - TREE_STATIC (d) = TREE_STATIC (decl); - DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) - && !(context && !DECL_THIS_EXTERN (decl))); - DECL_TEMPLATE_RESULT (d) = decl; - decl = d; + /* When parsing the initializer, lookup should use the object's + namespace. */ + push_decl_namespace (context); } - /* 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. */ - if (TYPE_NEEDS_DESTRUCTOR (type) - && current_binding_level->more_cleanups_ok == 0) - pushlevel_temporary (1); + /* We are only interested in class contexts, later. */ + if (context && TREE_CODE (context) == NAMESPACE_DECL) + context = NULL_TREE; if (initialized) /* Is it valid for this decl to have an initializer at all? @@ -5919,51 +6428,30 @@ start_decl (declarator, declspecs, initialized, raises) break; default: - /* 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 (type) != NULL_TREE) - ; /* A complete type is ok. */ - else if (TREE_CODE (type) != ARRAY_TYPE) - { - cp_error ("variable `%#D' has initializer but incomplete type", - decl); - initialized = 0; - } - else if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE) + if (! processing_template_decl) { - cp_error ("elements of array `%#D' have incomplete type", decl); - initialized = 0; + if (type != error_mark_node) + { + if (TYPE_SIZE (type) != NULL_TREE + && ! TREE_CONSTANT (TYPE_SIZE (type))) + { + cp_error + ("variable-sized object `%D' may not be initialized", + decl); + initialized = 0; + } + + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + { + cp_error + ("elements of array `%#D' have incomplete type", decl); + initialized = 0; + } + } } } - if (!initialized - && TREE_CODE (decl) != TYPE_DECL - && TREE_CODE (decl) != TEMPLATE_DECL - && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl)) - { - if (TYPE_SIZE (type) == NULL_TREE) - { - cp_error ("aggregate `%#D' has incomplete type and cannot be initialized", - decl); - /* Change the type so that assemble_variable will give - DECL an rtl we can live with: (mem (const_int 0)). */ - TREE_TYPE (decl) = error_mark_node; - type = error_mark_node; - } - else - { - /* If any base type in the hierarchy of TYPE needs a constructor, - then we set initialized to 1. This way any nodes which are - created for the purposes of initializing this aggregate - will live as long as it does. This is necessary for global - aggregates which do not have their initializers processed until - the end of the file. */ - initialized = TYPE_NEEDS_CONSTRUCTING (type); - } - } - if (initialized) { if (! toplevel_bindings_p () @@ -5971,7 +6459,7 @@ start_decl (declarator, declspecs, initialized, raises) cp_warning ("declaration of `%#D' has `extern' and is initialized", decl); DECL_EXTERNAL (decl) = 0; - if ( toplevel_bindings_p ()) + if (toplevel_bindings_p ()) TREE_STATIC (decl) = 1; /* Tell `pushdecl' this is an initialized decl @@ -5980,130 +6468,106 @@ start_decl (declarator, declspecs, initialized, raises) DECL_INITIAL (decl) = error_mark_node; } - if (context && TYPE_SIZE (context) != NULL_TREE) + if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE) { if (TREE_CODE (decl) == VAR_DECL) { tree field = lookup_field (context, DECL_NAME (decl), 0, 0); if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) cp_error ("`%#D' is not a static member of `%#T'", decl, context); - else if (duplicate_decls (decl, field)) - decl = field; + else + { + if (DECL_CONTEXT (field) != context) + { + cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'", + DECL_CONTEXT (field), DECL_NAME (decl), + context, DECL_NAME (decl)); + DECL_CONTEXT (decl) = DECL_CONTEXT (field); + } + /* Static data member are tricky; an in-class initialization + still doesn't provide a definition, so the in-class + declaration will have DECL_EXTERNAL set, but will have an + initialization. Thus, duplicate_decls won't warn + about this situation, and so we check here. */ + if (DECL_INITIAL (decl) && DECL_INITIAL (field)) + cp_error ("duplicate initialization of %D", decl); + if (duplicate_decls (decl, field)) + decl = field; + } } else { - tree field = check_classfn (context, NULL_TREE, decl); + tree field = check_classfn (context, decl); if (field && duplicate_decls (decl, field)) decl = field; } /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */ - if (DECL_LANG_SPECIFIC (decl)) - DECL_IN_AGGR_P (decl) = 0; - if (DECL_USE_TEMPLATE (decl) || CLASSTYPE_USE_TEMPLATE (context)) + DECL_IN_AGGR_P (decl) = 0; + if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) + || CLASSTYPE_USE_TEMPLATE (context)) SET_DECL_TEMPLATE_SPECIALIZATION (decl); - /* Stupid stupid stupid stupid (jason 7/21/95) */ - if (pedantic && DECL_EXTERNAL (decl) - && ! DECL_TEMPLATE_SPECIALIZATION (decl)) + 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. */ - if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE) - || (TREE_CODE (decl) == TEMPLATE_DECL && !global_bindings_p ()) - || TREE_CODE (type) == LANG_TYPE) + if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE + /* Definitions of namespace members outside their namespace are + possible. */ + && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL) + || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ()) + || TREE_CODE (type) == LANG_TYPE + /* The declaration of template specializations does not affect + the functions available for overload resolution, so we do not + call pushdecl. */ + || (TREE_CODE (decl) == FUNCTION_DECL + && DECL_TEMPLATE_SPECIALIZATION (decl))) tem = decl; else tem = pushdecl (decl); - - /* Tell the back-end to use or not use .common as appropriate. If we say - -fconserve-space, we want this to save space, at the expense of wrong - semantics. If we say -fno-conserve-space, we want this to produce - errors about redefs; to do this we force variables into the data - segment. Common storage is okay for non-public uninitialized data; - the linker can't match it with storage from other files, and we may - save some disk space. */ - DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem); -#if 0 - /* We don't do this yet for GNU C++. */ - /* For a local variable, define the RTL now. */ - if (! toplevel_bindings_p () - /* But not if this is a duplicate decl - and we preserved the rtl from the previous one - (which may or may not happen). */ - && DECL_RTL (tem) == NULL_RTX) + if (processing_template_decl) { - if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE) - expand_decl (tem); - else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE - && DECL_INITIAL (tem) != NULL_TREE) - expand_decl (tem); + if (! current_function_decl) + tem = push_template_decl (tem); + else if (minimal_parse_mode) + DECL_VINDEX (tem) + = build_min_nt (DECL_STMT, copy_to_permanent (declarator), + copy_to_permanent (declspecs), + NULL_TREE); } + + +#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) + /* Tell the back-end to use or not use .common as appropriate. If we say + -fconserve-space, we want this to save .data space, at the expense of + wrong semantics. If we say -fno-conserve-space, we want this to + produce errors about redefs; to do this we force variables into the + data segment. */ + DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem); #endif - if (TREE_CODE (decl) == TEMPLATE_DECL) - { - tree result = DECL_TEMPLATE_RESULT (decl); - if (DECL_CONTEXT (result) != NULL_TREE) - { - tree type; - type = DECL_CONTEXT (result); + if (! processing_template_decl) + start_decl_1 (tem); - if (TREE_CODE (type) != UNINSTANTIATED_P_TYPE) - { - cp_error ("declaration of `%D' in non-template type `%T'", - decl, type); - return NULL_TREE; - } + /* Corresponding pop_obstacks is done in `cp_finish_decl'. */ + push_obstacks_nochange (); - if (TREE_CODE (result) == FUNCTION_DECL) - return tem; - else if (TREE_CODE (result) == VAR_DECL) - { #if 0 - tree tmpl = UPT_TEMPLATE (type); - - fprintf (stderr, "%s:%d: adding ", __FILE__, __LINE__); - print_node_brief (stderr, "", DECL_NAME (tem), 0); - fprintf (stderr, " to class %s\n", - IDENTIFIER_POINTER (DECL_NAME (tmpl))); - DECL_TEMPLATE_MEMBERS (tmpl) - = perm_tree_cons (DECL_NAME (tem), tem, - DECL_TEMPLATE_MEMBERS (tmpl)); - return tem; -#else - sorry ("static data member templates"); - return NULL_TREE; -#endif - } - else - my_friendly_abort (13); - } - else if (TREE_CODE (result) == FUNCTION_DECL) - /*tem = push_overloaded_decl (tem, 0)*/; - else if (TREE_CODE (result) == VAR_DECL) - { - cp_error ("data template `%#D' must be member of a class template", - result); - return NULL_TREE; - } - else if (TREE_CODE (result) == TYPE_DECL) - { - cp_error ("invalid template `%#D'", result); - return NULL_TREE; - } - else - my_friendly_abort (14); - } - + /* We have no way of knowing whether the initializer will need to be + evaluated at run-time or not until we've parsed it, so let's just put + it in the permanent obstack. (jason) */ if (init_written && ! (TREE_CODE (tem) == PARM_DECL || (TREE_READONLY (tem) @@ -6114,7 +6578,8 @@ start_decl (declarator, declspecs, initialized, raises) use temporary storage. Do this even if we will ignore the value. */ if (toplevel_bindings_p () && debug_temp_inits) { - if (TYPE_NEEDS_CONSTRUCTING (type) + if (processing_template_decl + || TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE) /* In this case, the initializer must lay down in permanent storage, since it will be saved until `finish_file' is run. */ @@ -6123,81 +6588,108 @@ start_decl (declarator, declspecs, initialized, raises) temporary_allocation (); } } - - if (flag_cadillac) - cadillac_start_decl (tem); +#endif return tem; } -#if 0 /* unused */ -static void -make_temporary_for_reference (decl, ctor_call, init, cleanupp) - tree decl, ctor_call, init; - tree *cleanupp; +void +start_decl_1 (decl) + tree decl; { tree type = TREE_TYPE (decl); - tree target_type = TREE_TYPE (type); - tree tmp, tmp_addr; + int initialized = (DECL_INITIAL (decl) != NULL_TREE); - if (ctor_call) - { - tmp_addr = TREE_VALUE (TREE_OPERAND (ctor_call, 1)); - if (TREE_CODE (tmp_addr) == NOP_EXPR) - tmp_addr = TREE_OPERAND (tmp_addr, 0); - my_friendly_assert (TREE_CODE (tmp_addr) == ADDR_EXPR, 146); - tmp = TREE_OPERAND (tmp_addr, 0); - } - else + /* 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. */ + if (TYPE_NEEDS_DESTRUCTOR (type) + && current_binding_level->more_cleanups_ok == 0) + pushlevel_temporary (1); + + if (initialized) + /* Is it valid for this decl to have an initializer at all? + If not, set INITIALIZED to zero, which will indirectly + tell `cp_finish_decl' to ignore the initializer once it is parsed. */ { - tmp = get_temp_name (target_type, toplevel_bindings_p ()); - tmp_addr = build_unary_op (ADDR_EXPR, tmp, 0); + /* 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) + ; /* A complete type is ok. */ + else if (TREE_CODE (type) != ARRAY_TYPE) + { + cp_error ("variable `%#D' has initializer but incomplete type", + decl); + initialized = 0; + type = TREE_TYPE (decl) = error_mark_node; + } + else if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + { + if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) + cp_error ("elements of array `%#D' have incomplete type", decl); + /* else we already gave an error in start_decl. */ + initialized = 0; + } } - TREE_TYPE (tmp_addr) = build_pointer_type (target_type); - DECL_INITIAL (decl) = convert (build_pointer_type (target_type), tmp_addr); - TREE_TYPE (DECL_INITIAL (decl)) = type; - if (TYPE_NEEDS_CONSTRUCTING (target_type)) + if (!initialized + && TREE_CODE (decl) != TYPE_DECL + && TREE_CODE (decl) != TEMPLATE_DECL + && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl)) { - if (toplevel_bindings_p ()) + if ((! processing_template_decl || ! uses_template_parms (type)) + && TYPE_SIZE (complete_type (type)) == NULL_TREE) { - /* lay this variable out now. Otherwise `output_addressed_constants' - gets confused by its initializer. */ - make_decl_rtl (tmp, NULL_PTR, 1); - static_aggregates = perm_tree_cons (init, tmp, static_aggregates); + cp_error ("aggregate `%#D' has incomplete type and cannot be initialized", + decl); + /* Change the type so that assemble_variable will give + DECL an rtl we can live with: (mem (const_int 0)). */ + type = TREE_TYPE (decl) = error_mark_node; } else { - if (ctor_call != NULL_TREE) - init = ctor_call; - else - init = build_method_call (tmp, constructor_name_full (target_type), - build_tree_list (NULL_TREE, init), - NULL_TREE, LOOKUP_NORMAL); - DECL_INITIAL (decl) = build (COMPOUND_EXPR, type, init, - DECL_INITIAL (decl)); - *cleanupp = maybe_build_cleanup (tmp); + /* If any base type in the hierarchy of TYPE needs a constructor, + then we set initialized to 1. This way any nodes which are + created for the purposes of initializing this aggregate + will live as long as it does. This is necessary for global + aggregates which do not have their initializers processed until + the end of the file. */ + initialized = TYPE_NEEDS_CONSTRUCTING (type); } } - else + +#if 0 + /* We don't do this yet for GNU C++. */ + /* For a local variable, define the RTL now. */ + if (! toplevel_bindings_p () + /* But not if this is a duplicate decl + and we preserved the rtl from the previous one + (which may or may not happen). */ + && DECL_RTL (tem) == NULL_RTX) { - DECL_INITIAL (tmp) = init; - TREE_STATIC (tmp) = toplevel_bindings_p (); - cp_finish_decl (tmp, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); + if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE) + expand_decl (tem); + else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE + && DECL_INITIAL (tem) != NULL_TREE) + expand_decl (tem); } - if (TREE_STATIC (tmp)) - preserve_initializer (); -} #endif + if (! initialized) + DECL_INITIAL (decl) = NULL_TREE; +} + /* Handle initialization of references. - These three arguments from from `cp_finish_decl', and have the - same meaning here that they do there. */ -/* quotes on semantics can be found in ARM 8.4.3. */ + These three arguments are from `cp_finish_decl', and have the + same meaning here that they do there. + + Quotes on semantics can be found in ARM 8.4.3. */ + static void -grok_reference_init (decl, type, init, cleanupp) +grok_reference_init (decl, type, init) tree decl, type, init; - tree *cleanupp; { tree tmp; @@ -6224,6 +6716,10 @@ grok_reference_init (decl, type, init, cleanupp) 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); @@ -6238,39 +6734,14 @@ grok_reference_init (decl, type, init, cleanupp) } tmp = convert_to_reference - (type, init, CONV_IMPLICIT, LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl); + (type, init, CONV_IMPLICIT, + LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl); if (tmp == error_mark_node) goto fail; else if (tmp != NULL_TREE) { - tree subtype = TREE_TYPE (type); init = tmp; - - /* Associate the cleanup with the reference so that we - don't get burned by "aggressive" cleanup policy. */ - if (TYPE_NEEDS_DESTRUCTOR (subtype)) - { - if (TREE_CODE (init) == WITH_CLEANUP_EXPR) - { - *cleanupp = TREE_OPERAND (init, 2); - TREE_OPERAND (init, 2) = error_mark_node; - } - else - { - if (TREE_CODE (tmp) == ADDR_EXPR) - tmp = TREE_OPERAND (tmp, 0); - if (TREE_CODE (tmp) == TARGET_EXPR) - { - *cleanupp = build_delete - (build_pointer_type (subtype), - build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0), - integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); - TREE_OPERAND (tmp, 2) = error_mark_node; - } - } - } - DECL_INITIAL (decl) = save_expr (init); } else @@ -6318,10 +6789,12 @@ obscure_complex_init (decl, init) return NULL_TREE; } +#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) if (toplevel_bindings_p () && ! DECL_COMMON (decl)) DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, NULL_TREE); else +#endif DECL_INITIAL (decl) = error_mark_node; return init; @@ -6357,11 +6830,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) int flags; { register tree type; - tree cleanup = NULL_TREE, ttype; + tree cleanup = NULL_TREE, ttype = NULL_TREE; int was_incomplete; int temporary = allocation_temporary_p (); char *asmspec = NULL; int was_readonly = 0; + int already_used = 0; /* If this is 0, then we did not change obstacks. */ if (! decl) @@ -6375,6 +6849,23 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); + if (init && TREE_CODE (init) == NAMESPACE_DECL) + { + cp_error ("Cannot initialize `%D' to namespace `%D'", + decl, init); + init = NULL_TREE; + } + + if (TREE_CODE (decl) == VAR_DECL + && DECL_CONTEXT (decl) + && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL + && DECL_CONTEXT (decl) != current_namespace + && init) + { + /* Leave the namespace of the object. */ + pop_decl_namespace (); + } + /* If the type of the thing we are declaring either has a constructor, or has a virtual function table pointer, AND its initialization was accepted by `start_decl', @@ -6391,8 +6882,27 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) return; } - was_incomplete = (DECL_SIZE (decl) == NULL_TREE); + if (processing_template_decl) + { + if (init && DECL_INITIAL (decl)) + DECL_INITIAL (decl) = init; + if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl)) + { + tree stmt = DECL_VINDEX (decl); + /* If the decl is declaring a member of a local class (in a + template function), the DECL_VINDEX will either be NULL, + or it will be an actual virtual function index, not a + DECL_STMT. */ + if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT) + { + DECL_VINDEX (decl) = NULL_TREE; + TREE_OPERAND (stmt, 2) = copy_to_permanent (init); + add_tree (stmt); + } + } + goto finish_end0; + } /* Take care of TYPE_DECLs up front. */ if (TREE_CODE (decl) == TYPE_DECL) { @@ -6411,35 +6921,21 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) CLASSTYPE_GOT_SEMICOLON (type) = 1; } GNU_xref_decl (current_function_decl, decl); + + /* If we have installed this as the canonical typedef for this + type, and that type has not been defined yet, delay emitting + the debug information for it, as we will emit it later. */ + if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl + && TYPE_SIZE (TREE_TYPE (decl)) == NULL_TREE) + TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; + rest_of_decl_compilation (decl, NULL_PTR, - DECL_CONTEXT (decl) == NULL_TREE, 0); + DECL_CONTEXT (decl) == NULL_TREE, at_eof); goto finish_end; } if (TREE_CODE (decl) != FUNCTION_DECL) { ttype = target_type (type); -#if 0 /* WTF? -KR - Leave this out until we can figure out why it was - needed/desirable in the first place. Then put a comment - here explaining why. Or just delete the code if no ill - effects arise. */ - if (TYPE_NAME (ttype) - && TREE_CODE (TYPE_NAME (ttype)) == TYPE_DECL - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (ttype))) - { - tree old_id = TYPE_IDENTIFIER (ttype); - char *newname = (char *)alloca (IDENTIFIER_LENGTH (old_id) + 2); - /* Need to preserve template data for UPT nodes. */ - tree old_template = IDENTIFIER_TEMPLATE (old_id); - newname[0] = '_'; - bcopy (IDENTIFIER_POINTER (old_id), newname + 1, - IDENTIFIER_LENGTH (old_id) + 1); - old_id = get_identifier (newname); - lookup_tag_reverse (ttype, old_id); - TYPE_IDENTIFIER (ttype) = old_id; - IDENTIFIER_TEMPLATE (old_id) = old_template; - } -#endif } if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl) @@ -6480,7 +6976,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p () || pseudo_global_level_p ()); - grok_reference_init (decl, type, init, &cleanup); + grok_reference_init (decl, type, init); init = NULL_TREE; } @@ -6620,7 +7116,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) if (TREE_CODE (decl) == VAR_DECL) { if (DECL_SIZE (decl) == NULL_TREE - && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE) + && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE) layout_decl (decl, 0); if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE) @@ -6645,8 +7141,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) /* Let debugger know it should output info for this type. */ note_debug_info_needed (ttype); - if (TREE_STATIC (decl) && DECL_CONTEXT (decl) - && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') + if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl)) note_debug_info_needed (DECL_CONTEXT (decl)); if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) @@ -6659,21 +7154,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) cp_error ("storage size of `%D' isn't constant", decl); } - if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)) + if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type) + /* Cleanups for static variables are handled by `finish_file'. */ + && ! TREE_STATIC (decl)) { int yes = suspend_momentary (); - - /* If INIT comes from a functional cast, use the cleanup - we built for that. Otherwise, make our own cleanup. */ - if (init && TREE_CODE (init) == WITH_CLEANUP_EXPR - && comptypes (TREE_TYPE (decl), TREE_TYPE (init), 1)) - { - cleanup = TREE_OPERAND (init, 2); - init = TREE_OPERAND (init, 0); - current_binding_level->have_cleanups = 1; - } - else - cleanup = maybe_build_cleanup (decl); + cleanup = maybe_build_cleanup (decl); resume_momentary (yes); } } @@ -6691,24 +7177,96 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) unless the type is an undefined structure or union. If not, it will get done when the type is completed. */ + was_incomplete = (DECL_SIZE (decl) == NULL_TREE); + if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == RESULT_DECL) { /* ??? FIXME: What about nested classes? */ int toplev = toplevel_bindings_p () || pseudo_global_level_p (); int was_temp - = ((flag_traditional - || (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type))) + = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type) && allocation_temporary_p ()); if (was_temp) end_temporary_allocation (); + /* Static data in a function with comdat linkage also has comdat + linkage. */ if (TREE_CODE (decl) == VAR_DECL - && ! toplevel_bindings_p () - && ! TREE_STATIC (decl) - && type_needs_gc_entry (type)) - DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index); + && TREE_STATIC (decl) + /* Don't mess with __FUNCTION__. */ + && ! TREE_ASM_WRITTEN (decl) + && current_function_decl + && DECL_CONTEXT (decl) == current_function_decl + && (DECL_THIS_INLINE (current_function_decl) + || DECL_TEMPLATE_INSTANTIATION (current_function_decl)) + && TREE_PUBLIC (current_function_decl)) + { + /* Rather than try to get this right with inlining, we suppress + inlining of such functions. */ + current_function_cannot_inline + = "function with static variable cannot be inline"; + + /* If flag_weak, we don't need to mess with this, as we can just + make the function weak, and let it refer to its unique local + copy. This works because we don't allow the function to be + inlined. */ + if (! flag_weak) + { + if (DECL_INTERFACE_KNOWN (current_function_decl)) + { + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl); + } + else if (DECL_INITIAL (decl) == NULL_TREE + || DECL_INITIAL (decl) == error_mark_node) + { + TREE_PUBLIC (decl) = 1; + DECL_COMMON (decl) = 1; + } + /* else we lose. We can only do this if we can use common, + which we can't if it has been initialized. */ + + if (TREE_PUBLIC (decl)) + DECL_ASSEMBLER_NAME (decl) + = build_static_name (current_function_decl, DECL_NAME (decl)); + 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; + } + } + } + + 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; + } + } + } if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl)) make_decl_rtl (decl, NULL_PTR, toplev); @@ -6751,7 +7309,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) make_decl_rtl (decl, asmspec, toplev); } else - rest_of_decl_compilation (decl, asmspec, toplev, 0); + rest_of_decl_compilation (decl, asmspec, toplev, at_eof); } else if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl) @@ -6772,14 +7330,14 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) make_decl_rtl (decl, asmspec, 1); } else - rest_of_decl_compilation (decl, asmspec, toplev, 0); + rest_of_decl_compilation (decl, asmspec, toplev, at_eof); } else /* Just a constant field. Should not need any rtl. */ goto finish_end0; } else - rest_of_decl_compilation (decl, asmspec, toplev, 0); + rest_of_decl_compilation (decl, asmspec, toplev, at_eof); if (was_temp) resume_temporary_allocation (); @@ -6804,22 +7362,22 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) if (TREE_CODE (decl) == FUNCTION_DECL) ; - else if (DECL_EXTERNAL (decl)) - ; + else if (DECL_EXTERNAL (decl) + && ! (DECL_LANG_SPECIFIC (decl) + && DECL_NOT_REALLY_EXTERN (decl))) + { + if (init) + DECL_INITIAL (decl) = init; + } else if (TREE_STATIC (decl) && type != error_mark_node) { /* Cleanups for static variables are handled by `finish_file'. */ if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE || TYPE_NEEDS_DESTRUCTOR (type)) expand_static_init (decl, init); - - /* Make entry in appropriate vector. */ - if (flag_gc && type_needs_gc_entry (type)) - build_static_gc_entry (decl, type); } else if (! toplev) { - tree old_cleanups = cleanups_this_call; /* This is a declared decl which must live until the end of the binding contour. It may need a cleanup. */ @@ -6846,7 +7404,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) { /* XXX: Why don't we use decl here? */ /* Ans: Because it was already expanded? */ - if (! cp_expand_decl_cleanup (NULL_TREE, cleanup)) + if (! expand_decl_cleanup (NULL_TREE, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); /* Cleanup used up here. */ @@ -6854,10 +7412,59 @@ 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; + + /* Check to see if the same name is already bound at + the outer level, either because it was directly declared, + or because a dead for-decl got preserved. In either case, + the code would not have been valid under the ARM + scope rules, so clear is_for_scope for the + current_binding_level. + + 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)) + { + 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; + } + } + } + + expand_start_target_temps (); + if (DECL_SIZE (decl) && type != error_mark_node) { /* Compute and store the initial value. */ expand_decl_init (decl); + already_used = TREE_USED (decl) || TREE_USED (type); if (init || TYPE_NEEDS_CONSTRUCTING (type)) { @@ -6870,19 +7477,34 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) was initialized was ever used. Don't do this if it has a destructor, so we don't complain about the 'resource allocation is initialization' idiom. */ - if (TYPE_NEEDS_CONSTRUCTING (type) && cleanup == NULL_TREE) + /* Now set attribute((unused)) on types so decls of + that type will be marked used. (see TREE_USED, above.) + This avoids the warning problems this particular code + tried to work around. */ + + if (TYPE_NEEDS_CONSTRUCTING (type) + && ! already_used + && cleanup == NULL_TREE + && DECL_NAME (decl)) TREE_USED (decl) = 0; + if (already_used) + TREE_USED (decl) = 1; + } + + /* Cleanup any temporaries needed for the initial value. */ + expand_end_target_temps (); + + if (DECL_SIZE (decl) && type != error_mark_node) + { /* Store the cleanup, if there was one. */ if (cleanup) { - if (! cp_expand_decl_cleanup (decl, cleanup)) + if (! expand_decl_cleanup (decl, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); } } - /* Cleanup any temporaries needed for the initial value. */ - expand_cleanups_to (old_cleanups); } finish_end0: @@ -6896,18 +7518,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) && (TREE_CODE (decl) == VAR_DECL /* We also have a pushclass done that we need to undo here if we're at top level and declare a method. */ - || (TREE_CODE (decl) == FUNCTION_DECL - /* If size hasn't been set, we're still defining it, - and therefore inside the class body; don't pop - the binding level.. */ - && TYPE_SIZE (context) != NULL_TREE - /* The binding level gets popped elsewhere for a - friend declaration inside another class. */ - /* - && TYPE_IDENTIFIER (context) == current_class_name - */ - && context == current_class_type - ))) + || TREE_CODE (decl) == FUNCTION_DECL) + /* If size hasn't been set, we're still defining it, + and therefore inside the class body; don't pop + the binding level.. */ + && TYPE_SIZE (context) != NULL_TREE + && context == current_class_type) popclass (1); } } @@ -6917,6 +7533,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) /* If requested, warn about definitions of large data objects. */ if (warn_larger_than + && ! processing_template_decl && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) && !DECL_EXTERNAL (decl)) { @@ -6941,12 +7558,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) if (was_readonly) TREE_READONLY (decl) = 1; - - if (flag_cadillac) - cadillac_finish_decl (decl); } /* This is here for a midend callback from c-common.c */ + void finish_decl (decl, init, asmspec_tree) tree decl, init; @@ -6961,7 +7576,6 @@ expand_static_init (decl, init) tree init; { tree oldstatic = value_member (decl, static_aggregates); - tree old_cleanups; if (oldstatic) { @@ -6973,7 +7587,7 @@ expand_static_init (decl, init) /* Emit code to perform this initialization but once. */ tree temp; - /* Remember this information until end of file. */ + /* Remember this information until end of file. */ push_obstacks (&permanent_obstack, &permanent_obstack); /* Emit code to perform this initialization but once. */ @@ -6981,7 +7595,8 @@ expand_static_init (decl, init) rest_of_decl_compilation (temp, NULL_PTR, 0, 0); expand_start_cond (build_binary_op (EQ_EXPR, temp, integer_zero_node, 1), 0); - old_cleanups = cleanups_this_call; + expand_start_target_temps (); + expand_assignment (temp, integer_one_node, 0, 0); if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) || (init && TREE_CODE (init) == TREE_LIST)) @@ -6993,7 +7608,43 @@ expand_static_init (decl, init) expand_assignment (decl, init, 0, 0); /* Cleanup any temporaries needed for the initial value. */ - expand_cleanups_to (old_cleanups); + expand_end_target_temps (); + + if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl))) + { + tree cleanup, fcall; + static tree Atexit = 0; + if (Atexit == 0) + { + tree atexit_fndecl, PFV, pfvlist; + /* Remember this information until end of file. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + PFV = build_pointer_type (build_function_type + (void_type_node, void_list_node)); + + pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); + + push_lang_context (lang_name_c); + atexit_fndecl + = builtin_function ("atexit", + build_function_type (void_type_node, + pfvlist), + NOT_BUILT_IN, NULL_PTR); + assemble_external (atexit_fndecl); + Atexit = default_conversion (atexit_fndecl); + pop_lang_context (); + pop_obstacks (); + } + + cleanup = start_anon_func (); + expand_expr_stmt (build_cleanup (decl)); + end_anon_func (); + mark_addressable (cleanup); + cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); + 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))) { @@ -7001,7 +7652,7 @@ expand_static_init (decl, init) TREE_STATIC (static_aggregates) = 1; } - /* Resume old (possibly temporary) allocation. */ + /* Resume old (possibly temporary) allocation. */ pop_obstacks (); } else @@ -7100,6 +7751,7 @@ complete_array_type (type, initial_value, do_default) /* Return zero if something is declared to be a member of type CTYPE when in the context of CUR_TYPE. STRING is the error message to print in that case. Otherwise, quietly return 1. */ + static int member_function_or_else (ctype, cur_type, string) tree ctype, cur_type; @@ -7117,6 +7769,7 @@ member_function_or_else (ctype, cur_type, string) /* Generate errors possibly applicable for a given set of specifiers. This is for ARM $7.1.2. */ + static void bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) tree object; @@ -7147,18 +7800,23 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) 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. */ + static tree -grokfndecl (ctype, type, declarator, virtualp, flags, quals, - raises, attrlist, check, publicp, inlinep) +grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, + raises, attrlist, 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; - int check, publicp, inlinep; + int check, friendp, publicp, inlinep, funcdef_flag, template_count; + tree in_namespace; { tree cname, decl; int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; + tree t; if (ctype) cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL @@ -7169,26 +7827,28 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, if (raises) { type = build_exception_variant (type, raises); - raises = TYPE_RAISES_EXCEPTIONS (type); } + decl = build_lang_decl (FUNCTION_DECL, declarator, type); - /* propagate volatile out from type to decl */ + /* Propagate volatile out from type to decl. */ if (TYPE_VOLATILE (type)) - TREE_THIS_VOLATILE (decl) = 1; + TREE_THIS_VOLATILE (decl) = 1; + + /* This decl is not from the current namespace. */ + if (in_namespace) + set_decl_namespace (decl, in_namespace); /* Should probably propagate const out from type to decl I bet (mrs). */ if (staticp) { DECL_STATIC_FUNCTION_P (decl) = 1; DECL_CONTEXT (decl) = ctype; - DECL_CLASS_CONTEXT (decl) = ctype; } - /* All function decls start out public; we'll fix their linkage later (at - definition or EOF) if appropriate. */ - TREE_PUBLIC (decl) = 1; + if (ctype) + DECL_CLASS_CONTEXT (decl) = ctype; - if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) + if (ctype == NULL_TREE && MAIN_NAME_P (declarator)) { if (inlinep) error ("cannot declare `main' to be inline"); @@ -7198,8 +7858,12 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, publicp = 1; } + TREE_PUBLIC (decl) = publicp; if (! publicp) - DECL_C_STATIC (decl) = 1; + { + DECL_INTERFACE_KNOWN (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 1; + } if (inlinep) DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1; @@ -7215,10 +7879,43 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) grok_op_properties (decl, virtualp, check < 0); + if (ctype && hack_decl_function_context (decl)) + DECL_NO_STATIC_CHAIN (decl) = 1; + + for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG) + { + add_defarg_fn (decl); + break; + } + + if (friendp + && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR) + { + if (funcdef_flag) + cp_error + ("defining explicit specialization `%D' in friend declaration", + orig_declarator); + else + { + /* A friend declaration of the form friend void f<>(). Record + the information in the TEMPLATE_ID_EXPR. */ + SET_DECL_IMPLICIT_INSTANTIATION (decl); + DECL_TEMPLATE_INFO (decl) + = perm_tree_cons (TREE_OPERAND (orig_declarator, 0), + TREE_OPERAND (orig_declarator, 1), + NULL_TREE); + } + } + /* Caller will do the rest of this. */ if (check < 0) return decl; + if (check && funcdef_flag) + DECL_INITIAL (decl) = error_mark_node; + if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator) { tree tmp; @@ -7230,26 +7927,40 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, DECL_CONSTRUCTOR_P (decl) = 1; grokclassfn (ctype, declarator, decl, flags, quals); - if (check) - check_classfn (ctype, declarator, decl); + + decl = check_explicit_specialization (orig_declarator, decl, + template_count, + 2 * (funcdef_flag != 0) + + 4 * (friendp != 0)); + + if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl)) + && check) + { + tmp = check_classfn (ctype, decl); + + if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL) + tmp = DECL_TEMPLATE_RESULT(tmp); + + if (tmp && DECL_ARTIFICIAL (tmp)) + cp_error ("definition of implicitly-declared `%D'", tmp); + if (tmp && duplicate_decls (decl, tmp)) + return tmp; + } if (! grok_ctor_properties (ctype, decl)) return NULL_TREE; if (check == 0 && ! current_function_decl) { - /* FIXME: this should only need to look at - IDENTIFIER_GLOBAL_VALUE. */ - tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0); + /* Assembler names live in the global namespace. */ + tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)); if (tmp == NULL_TREE) - IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl; + 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; - /* avoid creating circularities. */ - DECL_CHAIN (decl) = NULL_TREE; } make_decl_rtl (decl, NULL_PTR, 1); } @@ -7264,8 +7975,36 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, if (ctype != NULL_TREE) grokclassfn (ctype, cname, decl, flags, quals); - if (ctype != NULL_TREE && check) - check_classfn (ctype, cname, decl); + decl = check_explicit_specialization (orig_declarator, decl, + template_count, + 2 * (funcdef_flag != 0) + + 4 * (friendp != 0)); + if (ctype != NULL_TREE + && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl)) + && check) + { + tmp = check_classfn (ctype, decl); + + if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL) + tmp = DECL_TEMPLATE_RESULT (tmp); + + if (tmp && DECL_STATIC_FUNCTION_P (tmp) + && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) + { + /* Remove the `this' parm added by grokclassfn. + XXX Isn't this done in start_function, too? */ + revert_static_member_fn (&decl, NULL, NULL); + last_function_parms = TREE_CHAIN (last_function_parms); + } + if (tmp && DECL_ARTIFICIAL (tmp)) + cp_error ("definition of implicitly-declared `%D'", tmp); + if (tmp) + { + if (!duplicate_decls (decl, tmp)) + my_friendly_abort (892); + return tmp; + } + } if (ctype == NULL_TREE || check) return decl; @@ -7275,19 +8014,25 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, methods, though. */ if (! current_function_decl) { - /* FIXME: this should only need to look at - IDENTIFIER_GLOBAL_VALUE. */ - tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0); - if (tmp == NULL_TREE) - IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl; - else if (TREE_CODE (tmp) != TREE_CODE (decl)) - cp_error ("inconsistent declarations for `%D'", decl); - else + if (!DECL_TEMPLATE_SPECIALIZATION (decl)) { - duplicate_decls (decl, tmp); - decl = tmp; - /* avoid creating circularities. */ - DECL_CHAIN (decl) = NULL_TREE; + /* 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) @@ -7295,95 +8040,30 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, TREE_VALUE (attrlist)); make_decl_rtl (decl, NULL_PTR, 1); } - - /* If this declaration supersedes the declaration of - a method declared virtual in the base class, then - mark this field as being virtual as well. */ - { - tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype)); - int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 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) - { - tmp = get_matching_virtual (base_binfo, decl, - flags == DTOR_FLAG); - if (tmp) - { - /* If this function overrides some virtual in some base - class, then the function itself is also necessarily - virtual, even if the user didn't explicitly say so. */ - DECL_VIRTUAL_P (decl) = 1; - - /* The TMP we really want is the one from the deepest - baseclass on this path, taking care not to - duplicate if we have already found it (via another - path to its virtual baseclass. */ - if (staticp) - { - cp_error ("method `%D' may not be declared static", - decl); - cp_error_at ("(since `%D' declared virtual in base class.)", - tmp); - break; - } - virtualp = 1; - - { - /* The argument types may have changed... */ - tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); - tree base_variant = TREE_TYPE (TREE_VALUE (argtypes)); - - 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); - raises = TYPE_RAISES_EXCEPTIONS (type); - } - TREE_TYPE (decl) = type; - DECL_VINDEX (decl) - = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); - } - break; - } - } - } - } if (virtualp) { + DECL_VIRTUAL_P (decl) = 1; if (DECL_VINDEX (decl) == NULL_TREE) DECL_VINDEX (decl) = error_mark_node; IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; - if (ctype && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) - /* If this function is derived from a template, don't - make it public. This shouldn't be here, but there's - no good way to override the interface pragmas for one - function or class only. Bletch. */ - && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (ctype)) == NULL_TREE - && (write_virtuals == 2 - || (write_virtuals == 3 - && CLASSTYPE_INTERFACE_KNOWN (ctype)))) - TREE_PUBLIC (decl) = 1; } } return decl; } static tree -grokvardecl (type, declarator, specbits, initialized, constp) +grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) tree type; tree declarator; - RID_BIT_TYPE specbits; + RID_BIT_TYPE *specbits_in; int initialized; int constp; + tree in_namespace; { tree decl; + RID_BIT_TYPE specbits; + + specbits = *specbits_in; if (TREE_CODE (type) == OFFSET_TYPE) { @@ -7397,9 +8077,17 @@ grokvardecl (type, declarator, specbits, initialized, constp) DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator); } else - decl = build_decl (VAR_DECL, declarator, type); + { + tree context = in_namespace ? in_namespace : current_namespace; + 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); + } - DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl)); + if (in_namespace) + set_decl_namespace (decl, in_namespace); if (RIDBIT_SETP (RID_EXTERN, specbits)) { @@ -7409,8 +8097,7 @@ grokvardecl (type, declarator, specbits, initialized, constp) /* In class context, static means one per class, public access, and static storage. */ - if (DECL_FIELD_CONTEXT (decl) != NULL_TREE - && IS_AGGR_TYPE (DECL_FIELD_CONTEXT (decl))) + if (DECL_CLASS_SCOPE_P (decl)) { TREE_PUBLIC (decl) = 1; TREE_STATIC (decl) = 1; @@ -7433,7 +8120,7 @@ grokvardecl (type, declarator, specbits, initialized, constp) return decl; } -/* Create a canonical pointer to member function type. */ +/* Create a canonical pointer to member function type. */ tree build_ptrmemfunc_type (type) @@ -7462,9 +8149,9 @@ build_ptrmemfunc_type (type) t = make_lang_type (RECORD_TYPE); - /* Let the front-end know this is a pointer to member function. */ + /* Let the front-end know this is a pointer to member function... */ TYPE_PTRMEMFUNC_FLAG (t) = 1; - /* and not really an aggregate. */ + /* ... and not really an aggregate. */ IS_AGGR_TYPE (t) = 0; fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, @@ -7482,7 +8169,7 @@ build_ptrmemfunc_type (type) TYPE_SET_PTRMEMFUNC_TYPE (type, t); - /* Seems to be wanted. */ + /* Seems to be wanted. */ CLASSTYPE_GOT_SEMICOLON (t) = 1; return t; } @@ -7546,12 +8233,12 @@ build_ptrmemfunc_type (type) enum return_types { return_normal, return_ctor, return_dtor, return_conversion }; tree -grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrlist) +grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) tree declspecs; tree declarator; enum decl_context decl_context; int initialized; - tree raises, attrlist; + tree attrlist; { RID_BIT_TYPE specbits; int nclasses = 0; @@ -7563,6 +8250,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli int virtualp, explicitp, friendp, inlinep, staticp; int explicit_int = 0; int explicit_char = 0; + int defaulted_int = 0; int opaque_typedef = 0; tree typedef_decl = NULL_TREE; char *name; @@ -7570,8 +8258,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli int funcdef_flag = 0; enum tree_code innermost_code = ERROR_MARK; int bitfield = 0; - int size_varies = 0; +#if 0 + /* See the code below that used this. */ tree decl_machine_attr = NULL_TREE; +#endif /* Set this to error_mark_node for FIELD_DECLs we could not handle properly. All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */ tree init = NULL_TREE; @@ -7586,6 +8276,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli tree ctor_return_type = NULL_TREE; enum overload_flags flags = NO_SPECIAL; tree quals = NULL_TREE; + tree raises = NULL_TREE; + int template_count = 0; + tree in_namespace = NULL_TREE; RIDBIT_RESET_ALL (specbits); if (decl_context == FUNCDEF) @@ -7595,228 +8288,263 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli else if (decl_context == BITFIELD) bitfield = 1, decl_context = FIELD; - if (flag_traditional && allocation_temporary_p ()) - end_temporary_allocation (); - /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ { - tree last = NULL_TREE; - register tree decl = declarator; - name = NULL; - - while (decl) - switch (TREE_CODE (decl)) - { - case COND_EXPR: - ctype = NULL_TREE; - decl = TREE_OPERAND (decl, 0); - break; - - case BIT_NOT_EXPR: /* for C++ destructors! */ - { - tree name = TREE_OPERAND (decl, 0); - tree rename = NULL_TREE; - - my_friendly_assert (flags == NO_SPECIAL, 152); - flags = DTOR_FLAG; - return_type = return_dtor; - my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); - if (ctype == NULL_TREE) - { - if (current_class_type == NULL_TREE) - { - error ("destructors must be member functions"); - flags = NO_SPECIAL; - } - else - { - tree t = constructor_name (current_class_name); - if (t != name) - rename = t; - } - } - else - { - tree t = constructor_name (ctype); - if (t != name) - rename = t; - } - - if (rename) - { - error ("destructor `%s' must match class name `%s'", - IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (rename)); - TREE_OPERAND (decl, 0) = rename; - } - decl = name; - } - break; - - case ADDR_EXPR: /* C++ reference declaration */ - /* fall through */ - case ARRAY_REF: - case INDIRECT_REF: - ctype = NULL_TREE; - innermost_code = TREE_CODE (decl); - last = decl; - decl = TREE_OPERAND (decl, 0); - break; - - 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... */ - - if (last) - /* We need to insinuate ourselves into the declarator in place - of the CALL_EXPR. */ - TREE_OPERAND (last, 0) = TREE_OPERAND (decl, 0); - else - declarator = TREE_OPERAND (decl, 0); + tree *next = &declarator; + register tree decl; + name = NULL; - init = TREE_OPERAND (decl, 1); + while (next && *next) + { + decl = *next; + switch (TREE_CODE (decl)) + { + case COND_EXPR: + ctype = NULL_TREE; + next = &TREE_OPERAND (decl, 0); + break; - decl = start_decl (declarator, declspecs, 1, NULL_TREE); - finish_decl (decl, init, NULL_TREE); - return 0; - } - innermost_code = TREE_CODE (decl); - if (decl_context == FIELD && ctype == NULL_TREE) - ctype = current_class_type; - if (ctype - && TREE_OPERAND (decl, 0) == constructor_name_full (ctype)) - TREE_OPERAND (decl, 0) = constructor_name (ctype); - decl = TREE_OPERAND (decl, 0); - if (ctype != NULL_TREE - && decl != NULL_TREE && flags != DTOR_FLAG - && decl == constructor_name (ctype)) + case BIT_NOT_EXPR: /* For C++ destructors! */ { - return_type = return_ctor; - ctor_return_type = ctype; - } - ctype = NULL_TREE; - break; - - case IDENTIFIER_NODE: - dname = decl; - decl = NULL_TREE; + tree name = TREE_OPERAND (decl, 0); + tree rename = NULL_TREE; + + my_friendly_assert (flags == NO_SPECIAL, 152); + flags = DTOR_FLAG; + return_type = return_dtor; + if (TREE_CODE (name) == TYPE_DECL) + TREE_OPERAND (decl, 0) = name = constructor_name (name); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); + if (ctype == NULL_TREE) + { + if (current_class_type == NULL_TREE) + { + error ("destructors must be member functions"); + flags = NO_SPECIAL; + } + else + { + tree t = constructor_name (current_class_name); + if (t != name) + rename = t; + } + } + else + { + tree t = constructor_name (ctype); + if (t != name) + rename = t; + } - if (! IDENTIFIER_OPNAME_P (dname) - /* Linux headers use '__op'. Arrgh. */ - || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)) - name = IDENTIFIER_POINTER (dname); - else - { - if (IDENTIFIER_TYPENAME_P (dname)) + if (rename) { - my_friendly_assert (flags == NO_SPECIAL, 154); - flags = TYPENAME_FLAG; - ctor_return_type = TREE_TYPE (dname); - return_type = return_conversion; + cp_error ("destructor `%T' must match class name `%T'", + name, rename); + TREE_OPERAND (decl, 0) = rename; } - name = operator_name_string (dname); + next = &name; } - break; + break; - case RECORD_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: - /* Parse error puts this typespec where - a declarator should go. */ - error ("declarator name missing"); - dname = TYPE_NAME (decl); - if (dname && TREE_CODE (dname) == TYPE_DECL) - dname = DECL_NAME (dname); - name = dname ? IDENTIFIER_POINTER (dname) : ""; - declspecs = temp_tree_cons (NULL_TREE, decl, declspecs); - decl = NULL_TREE; - break; + case ADDR_EXPR: /* C++ reference declaration */ + /* Fall through. */ + case ARRAY_REF: + case INDIRECT_REF: + ctype = NULL_TREE; + innermost_code = TREE_CODE (decl); + next = &TREE_OPERAND (decl, 0); + break; - /* C++ extension */ - case SCOPE_REF: - { - /* Perform error checking, and convert class names to types. - We may call grokdeclarator multiple times for the same - tree structure, so only do the conversion once. In this - case, we have exactly what we want for `ctype'. */ - tree cname = TREE_OPERAND (decl, 0); - if (cname == NULL_TREE) - ctype = NULL_TREE; - /* Can't use IS_AGGR_TYPE because CNAME might not be a type. */ - else if (IS_AGGR_TYPE_CODE (TREE_CODE (cname)) - || TREE_CODE (cname) == UNINSTANTIATED_P_TYPE) - ctype = cname; - else if (! is_aggr_typedef (cname, 1)) - { - TREE_OPERAND (decl, 0) = NULL_TREE; - } - /* Must test TREE_OPERAND (decl, 1), in case user gives - us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */ - else if (TREE_OPERAND (decl, 1) - && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF) + case CALL_EXPR: + if (parmlist_is_exprlist (TREE_OPERAND (decl, 1))) { - TREE_OPERAND (decl, 0) = IDENTIFIER_TYPE_VALUE (cname); + /* 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... */ + + *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); + return 0; } - else if (ctype == NULL_TREE) + innermost_code = TREE_CODE (decl); + if (decl_context == FIELD && ctype == NULL_TREE) + ctype = current_class_type; + if (ctype + && TREE_OPERAND (decl, 0) + && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL + && ((DECL_NAME (TREE_OPERAND (decl, 0)) + == constructor_name_full (ctype)) + || (DECL_NAME (TREE_OPERAND (decl, 0)) + == constructor_name (ctype))))) + TREE_OPERAND (decl, 0) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 0); + decl = *next; + if (ctype != NULL_TREE + && decl != NULL_TREE && flags != DTOR_FLAG + && decl == constructor_name (ctype)) { - ctype = IDENTIFIER_TYPE_VALUE (cname); - TREE_OPERAND (decl, 0) = ctype; + return_type = return_ctor; + ctor_return_type = ctype; } - else if (TREE_COMPLEXITY (decl) == current_class_depth) - TREE_OPERAND (decl, 0) = ctype; - else + ctype = NULL_TREE; + break; + + case TEMPLATE_ID_EXPR: { - if (! UNIQUELY_DERIVED_FROM_P (IDENTIFIER_TYPE_VALUE (cname), - ctype)) - { - cp_error ("type `%T' is not derived from type `%T'", - IDENTIFIER_TYPE_VALUE (cname), ctype); - TREE_OPERAND (decl, 0) = NULL_TREE; - } + tree fns = TREE_OPERAND (decl, 0); + + 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 - { - ctype = IDENTIFIER_TYPE_VALUE (cname); - TREE_OPERAND (decl, 0) = ctype; - } + my_friendly_abort (0); } + /* Fall through. */ - if (ctype - && TREE_OPERAND (decl, 1) == constructor_name_full (ctype)) - TREE_OPERAND (decl, 1) = constructor_name (ctype); - decl = TREE_OPERAND (decl, 1); - if (ctype) + case IDENTIFIER_NODE: + if (TREE_CODE (decl) == IDENTIFIER_NODE) + dname = decl; + + next = 0; + + if (is_rid (dname)) { - if (TREE_CODE (decl) == IDENTIFIER_NODE - && constructor_name (ctype) == decl) - { - return_type = return_ctor; - ctor_return_type = ctype; - } - else if (TREE_CODE (decl) == BIT_NOT_EXPR - && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE - && (constructor_name (ctype) == TREE_OPERAND (decl, 0) - || constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) + cp_error ("declarator-id missing; using reserved word `%D'", + dname); + name = IDENTIFIER_POINTER (dname); + } + if (! IDENTIFIER_OPNAME_P (dname) + /* GNU/Linux headers use '__op'. Arrgh. */ + || (IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))) + name = IDENTIFIER_POINTER (dname); + else + { + if (IDENTIFIER_TYPENAME_P (dname)) { - return_type = return_dtor; - ctor_return_type = ctype; - flags = DTOR_FLAG; - decl = TREE_OPERAND (decl, 0) = constructor_name (ctype); + my_friendly_assert (flags == NO_SPECIAL, 154); + flags = TYPENAME_FLAG; + ctor_return_type = TREE_TYPE (dname); + return_type = return_conversion; } + name = operator_name_string (dname); } - } - break; + break; - case ERROR_MARK: - decl = NULL_TREE; - break; + /* C++ extension */ + case SCOPE_REF: + { + /* Perform error checking, and decide on a ctype. */ + tree cname = TREE_OPERAND (decl, 0); + if (cname == NULL_TREE) + ctype = NULL_TREE; + else if (TREE_CODE (cname) == NAMESPACE_DECL) + { + ctype = NULL_TREE; + in_namespace = TREE_OPERAND (decl, 0); + TREE_OPERAND (decl, 0) = NULL_TREE; + } + else if (! is_aggr_type (cname, 1)) + TREE_OPERAND (decl, 0) = NULL_TREE; + /* Must test TREE_OPERAND (decl, 1), in case user gives + us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */ + else if (TREE_OPERAND (decl, 1) + && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF) + ctype = cname; + else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM + || TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM) + { + cp_error ("`%T::%D' is not a valid declarator", cname, + TREE_OPERAND (decl, 1)); + cp_error (" perhaps you want `typename %T::%D' to make it a type", + cname, TREE_OPERAND (decl, 1)); + return void_type_node; + } + else if (ctype == NULL_TREE) + ctype = cname; + else if (TREE_COMPLEXITY (decl) == current_class_depth) + TREE_OPERAND (decl, 0) = ctype; + else + { + if (! UNIQUELY_DERIVED_FROM_P (cname, ctype)) + { + cp_error ("type `%T' is not derived from type `%T'", + cname, ctype); + TREE_OPERAND (decl, 0) = NULL_TREE; + } + else + ctype = cname; + } - default: - return 0; /* We used to do a 155 abort here. */ - } + if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL + && ((DECL_NAME (TREE_OPERAND (decl, 1)) + == constructor_name_full (ctype)) + || (DECL_NAME (TREE_OPERAND (decl, 1)) + == constructor_name (ctype)))) + TREE_OPERAND (decl, 1) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 1); + decl = *next; + if (ctype) + { + if (TREE_CODE (decl) == IDENTIFIER_NODE + && constructor_name (ctype) == decl) + { + return_type = return_ctor; + ctor_return_type = ctype; + } + else if (TREE_CODE (decl) == BIT_NOT_EXPR + && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE + && (constructor_name (ctype) == TREE_OPERAND (decl, 0) + || constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) + { + return_type = return_dtor; + ctor_return_type = ctype; + flags = DTOR_FLAG; + TREE_OPERAND (decl, 0) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 0); + } + } + } + break; + + case ERROR_MARK: + next = 0; + break; + + case TYPE_DECL: + /* Parse error puts this typespec where + a declarator should go. */ + cp_error ("`%T' specified as declarator-id", DECL_NAME (decl)); + if (TREE_TYPE (decl) == current_class_type) + cp_error (" perhaps you want `%T' for a constructor", + current_class_name); + dname = DECL_NAME (decl); + name = IDENTIFIER_POINTER (dname); + + /* Avoid giving two errors for this. */ + IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE; + + declspecs = temp_tree_cons (NULL_TREE, integer_type_node, + declspecs); + *next = dname; + next = 0; + break; + + default: + cp_compiler_error ("`%D' as declarator", decl); + return 0; /* We used to do a 155 abort here. */ + } + } if (name == NULL) name = "type name"; } @@ -7849,7 +8577,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli We also want to avoid calling this a PARM if it is in a namespace. */ - if (decl_context == NORMAL && ! namespace_bindings_p ()) + if (decl_context == NORMAL && ! namespace_bindings_p () + && ! pseudo_global_level_p ()) { struct binding_level *b = current_binding_level; current_binding_level = b->level_chain; @@ -7911,7 +8640,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } goto found; } - /* C++ aggregate types. */ + /* C++ aggregate types. */ if (IDENTIFIER_HAS_TYPE_VALUE (id)) { if (type) @@ -7927,9 +8656,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli { if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits)) { - if (pedantic && ! in_system_header) + if (pedantic && ! in_system_header && warn_long_long) pedwarn ("ANSI C++ does not support `long long'"); - else if (longlong) + if (longlong) error ("`long long long' is too long for GCC"); else longlong = 1; @@ -7941,6 +8670,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } } } + /* C++ aggregate types. */ + else if (TREE_CODE (id) == TYPE_DECL || TREE_CODE (id) == TEMPLATE_DECL) + { + if (type) + cp_error ("multiple declarations `%T' and `%T'", type, + TREE_TYPE (id)); + else + { + type = TREE_TYPE (id); + TREE_VALUE (spec) = type; + } + goto found; + } if (type) error ("two or more data types in declaration of `%s'", name); else if (TREE_CODE (id) == IDENTIFIER_NODE) @@ -7952,11 +8694,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli else { type = TREE_TYPE (t); +#if 0 + /* See the code below that used this. */ decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id); +#endif typedef_decl = t; } } - else if (TREE_CODE (id) != ERROR_MARK) + else if (id != error_mark_node) /* Can't change CLASS nodes into RECORD nodes here! */ type = id; @@ -7965,7 +8710,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli typedef_type = type; - /* No type at all: default to `int', and set EXPLICIT_INT + /* No type at all: default to `int', and set DEFAULTED_INT because it was not a user-defined typedef. Except when we have a `typedef' inside a signature, in which case the type defaults to `unknown type' and is @@ -7979,7 +8724,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli { /* These imply 'int'. */ type = integer_type_node; - explicit_int = 1; + defaulted_int = 1; } if (type == NULL_TREE) @@ -7993,18 +8738,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli type = ctor_return_type; else if (current_class_type && IS_SIGNATURE (current_class_type) - && (RIDBIT_SETP (RID_TYPEDEF, specbits) - || SIGNATURE_GROKKING_TYPEDEF (current_class_type)) + && RIDBIT_SETP (RID_TYPEDEF, specbits) && (decl_context == FIELD || decl_context == NORMAL)) { explicit_int = 0; opaque_typedef = 1; type = copy_node (opaque_type_node); } - /* access declaration */ - else if (decl_context == FIELD && declarator - && TREE_CODE (declarator) == SCOPE_REF) - type = void_type_node; else { if (funcdef_flag) @@ -8016,10 +8756,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } else if (RIDBIT_SETP (RID_TYPEDEF, specbits)) pedwarn ("ANSI C++ forbids typedef which does not specify a type"); - else if (declspecs == NULL_TREE && - (innermost_code != CALL_EXPR || pedantic)) - cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class", - dname); + 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); + } type = integer_type_node; } } @@ -8044,13 +8789,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli type = ctor_return_type; } - /* Catch typedefs that only specify a type, like 'typedef int;'. */ - else if (RIDBIT_SETP (RID_TYPEDEF, specbits) && declarator == NULL_TREE) - { - /* Template "this is a type" syntax; just ignore for now. */ - if (processing_template_defn) - return void_type_node; - } ctype = NULL_TREE; @@ -8097,7 +8835,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli else { ok = 1; - if (!explicit_int && !explicit_char && pedantic) + if (!explicit_int && !defaulted_int && !explicit_char && pedantic) { pedwarn ("long, short, signed or unsigned used invalidly for `%s'", name); @@ -8117,13 +8855,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } } + if (RIDBIT_SETP (RID_COMPLEX, specbits) + && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) + { + error ("complex invalid for `%s'", name); + RIDBIT_RESET (RID_COMPLEX, specbits); + } + /* Decide whether an integer type is signed or not. Optionally treat bitfields as signed by default. */ if (RIDBIT_SETP (RID_UNSIGNED, specbits) - /* Traditionally, all bitfields are unsigned. */ - || (bitfield && flag_traditional) || (bitfield && ! flag_signed_bitfields - && (explicit_int || explicit_char + && (explicit_int || defaulted_int || explicit_char /* A typedef for plain `int' without `signed' can be controlled just like plain `int'. */ || ! (typedef_decl != NULL_TREE @@ -8154,21 +8897,46 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli else if (RIDBIT_SETP (RID_SHORT, specbits)) type = short_integer_type_node; + if (RIDBIT_SETP (RID_COMPLEX, specbits)) + { + /* If we just have "complex", it is equivalent to + "complex double", but if any modifiers at all are specified it is + the complex form of TYPE. E.g, "complex short" is + "complex short int". */ + + if (defaulted_int && ! longlong + && ! (RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits) + || RIDBIT_SETP (RID_SIGNED, specbits) + || RIDBIT_SETP (RID_UNSIGNED, specbits))) + type = complex_double_type_node; + else if (type == integer_type_node) + type = complex_integer_type_node; + else if (type == float_type_node) + type = complex_float_type_node; + else if (type == double_type_node) + type = complex_double_type_node; + else if (type == long_double_type_node) + type = complex_long_double_type_node; + else + type = build_complex_type (type); + } + + if (return_type == return_conversion + && (RIDBIT_SETP (RID_CONST, specbits) + || RIDBIT_SETP (RID_VOLATILE, specbits))) + cp_error ("`operator %T' cannot be cv-qualified", + 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); staticp = 0; inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); -#if 0 - /* This sort of redundancy is blessed in a footnote to the Sep 94 WP. */ - if (constp > 1) - warning ("duplicate `const'"); - if (volatilep > 1) - warning ("duplicate `volatile'"); -#endif virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); RIDBIT_RESET (RID_VIRTUAL, specbits); explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0; @@ -8198,20 +8966,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli error ("non-object member `%s' cannot be declared `mutable'", name); RIDBIT_RESET (RID_MUTABLE, specbits); } -#if 0 - if (RIDBIT_SETP (RID_TYPEDEF, specbits)) - { - error ("non-object member `%s' cannot be declared `mutable'", name); - RIDBIT_RESET (RID_MUTABLE, specbits); - } - /* Because local typedefs are parsed twice, we don't want this - message here. */ - else if (decl_context != FIELD) - { - error ("non-member `%s' cannot be declared `mutable'", name); - RIDBIT_RESET (RID_MUTABLE, specbits); - } -#endif } /* Warn if two storage classes are given. Default to `auto'. */ @@ -8248,16 +9002,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli /* Static anonymous unions are dealt with here. */ if (staticp && decl_context == TYPENAME && TREE_CODE (declspecs) == TREE_LIST - && TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs)))) + && ANON_UNION_TYPE_P (TREE_VALUE (declspecs))) decl_context = FIELD; /* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual' is used in a signature member function declaration. */ if (decl_context == FIELD && IS_SIGNATURE (current_class_type) - && RIDBIT_NOTSETP(RID_TYPEDEF, specbits) - && !SIGNATURE_GROKKING_TYPEDEF (current_class_type)) + && RIDBIT_NOTSETP (RID_TYPEDEF, specbits)) { if (constp) { @@ -8301,82 +9053,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli && (RIDBIT_SETP (RID_REGISTER, specbits) || RIDBIT_SETP (RID_AUTO, specbits))) ; + else if (RIDBIT_SETP (RID_TYPEDEF, specbits)) + ; else if (decl_context == FIELD - && RIDBIT_SETP (RID_TYPEDEF, specbits)) - { - /* Processing a typedef declaration nested within a class type - definition. */ - register tree scanner; - register tree previous_declspec; - tree loc_typedecl; - - if (initialized) - error ("typedef declaration includes an initializer"); - - /* To process a class-local typedef declaration, we descend down - the chain of declspecs looking for the `typedef' spec. When - we find it, we replace it with `static', and then recursively - call `grokdeclarator' with the original declarator and with - the newly adjusted declspecs. This call should return a - FIELD_DECL node with the TREE_TYPE (and other parts) set - appropriately. We can then just change the TREE_CODE on that - from FIELD_DECL to TYPE_DECL and we're done. */ - - for (previous_declspec = NULL_TREE, scanner = declspecs; - scanner; - previous_declspec = scanner, scanner = TREE_CHAIN (scanner)) - { - if (TREE_VALUE (scanner) == ridpointers[(int) RID_TYPEDEF]) - break; - } - - if (previous_declspec) - TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner); - else - declspecs = TREE_CHAIN (scanner); - - declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], - declspecs); - - /* In the recursive call to grokdeclarator we need to know - whether we are working on a signature-local typedef. */ - if (IS_SIGNATURE (current_class_type)) - SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 1; - - loc_typedecl = - grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE, NULL_TREE); - - if (previous_declspec) - TREE_CHAIN (previous_declspec) = scanner; - - if (loc_typedecl != error_mark_node) - { - register int i = sizeof (struct lang_decl_flags) / sizeof (int); - register int *pi; - - TREE_SET_CODE (loc_typedecl, TYPE_DECL); - /* This is the same field as DECL_ARGUMENTS, which is set for - function typedefs by the above grokdeclarator. */ - DECL_NESTED_TYPENAME (loc_typedecl) = 0; - - pi = (int *) permalloc (sizeof (struct lang_decl_flags)); - while (i > 0) - pi[--i] = 0; - DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi; - } - - if (IS_SIGNATURE (current_class_type)) - { - SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 0; - if (loc_typedecl != error_mark_node && opaque_typedef) - SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1; - } - - return loc_typedecl; - } - else if (decl_context == FIELD - && (! IS_SIGNATURE (current_class_type) - || SIGNATURE_GROKKING_TYPEDEF (current_class_type)) + && ! IS_SIGNATURE (current_class_type) /* C++ allows static class elements */ && RIDBIT_SETP (RID_STATIC, specbits)) /* C++ also allows inlines and signed and unsigned elements, @@ -8391,7 +9071,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli if (declarator) { - tmp = TREE_OPERAND (declarator, 0); + /* Avoid trying to get an operand off an identifier node. */ + if (TREE_CODE (declarator) == IDENTIFIER_NODE) + tmp = declarator; + else + tmp = TREE_OPERAND (declarator, 0); op = IDENTIFIER_OPNAME_P (tmp); } error ("storage class specified for %s `%s'", @@ -8436,28 +9120,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli { if (RIDBIT_SETP (RID_AUTO, specbits)) error ("top-level declaration of `%s' specifies `auto'", name); -#if 0 - if (RIDBIT_SETP (RID_REGISTER, specbits)) - error ("top-level declaration of `%s' specifies `register'", name); -#endif -#if 0 - /* I'm not sure under what circumstances we should turn - on the extern bit, and under what circumstances we should - warn if other bits are turned on. */ - if (decl_context == NORMAL - && RIDBIT_NOSETP (RID_EXTERN, specbits) - && ! root_lang_context_p ()) - { - RIDBIT_SET (RID_EXTERN, specbits); - } -#endif } + if (nclasses > 0 && friendp) + error ("storage class specifiers invalid in friend function declarations"); + /* Now figure out the structure of the declarator proper. Descend through it, creating more complex types, until we reach the declared identifier (or NULL_TREE, in an absolute declarator). */ - while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE) + while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE + && TREE_CODE (declarator) != TEMPLATE_ID_EXPR) { /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]), an INDIRECT_REF (for *...), @@ -8480,7 +9153,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli array or function or pointer, and DECLARATOR has had its outermost layer removed. */ - if (TREE_CODE (type) == ERROR_MARK) + if (type == error_mark_node) { if (TREE_CODE (declarator) == SCOPE_REF) declarator = TREE_OPERAND (declarator, 1); @@ -8496,11 +9169,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ctype = TYPE_METHOD_BASETYPE (type); if (ctype != NULL_TREE) { -#if 0 /* not yet, should get fixed properly later */ - tree dummy = make_type_decl (NULL_TREE, type); -#else tree dummy = build_decl (TYPE_DECL, NULL_TREE, type); -#endif ctype = grok_method_quals (ctype, dummy, quals); type = TREE_TYPE (dummy); quals = NULL_TREE; @@ -8519,7 +9188,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli /* Check for some types that there cannot be arrays of. */ - if (TYPE_MAIN_VARIANT (type) == void_type_node) + if (TREE_CODE (type) == VOID_TYPE) { cp_error ("declaration of `%D' as array of voids", dname); type = error_mark_node; @@ -8574,15 +9243,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli the function; then build_vec_delete will need this value. */ int yes = suspend_momentary (); - /* might be a cast */ + /* Might be a cast. */ if (TREE_CODE (size) == NOP_EXPR && TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0))) size = TREE_OPERAND (size, 0); - /* If this is a template parameter, it'll be constant, but - we don't know what the value is yet. */ - if (TREE_CODE (size) == TEMPLATE_CONST_PARM) - goto dont_grok_size; + /* If this involves a template parameter, it'll be + constant, but we don't know what the value is yet. */ + 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); + goto dont_grok_size; + } if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE) @@ -8620,20 +9295,36 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli else cp_pedwarn ("ANSI C++ forbids variable-size array"); } - /* Make sure the array size remains visibly nonconstant - even if it is (eg) a const variable with known value. */ - size_varies = 1; } - dont_grok_size: - itype = - fold (build_binary_op (MINUS_EXPR, - convert (index_type, size), - convert (index_type, - integer_one_node), 1)); + itype + = fold (build_binary_op (MINUS_EXPR, + cp_convert (index_type, size), + cp_convert (index_type, + integer_one_node), 1)); if (! TREE_CONSTANT (itype)) itype = variable_size (itype); - itype = build_index_type (itype); + else if (TREE_OVERFLOW (itype)) + { + error ("overflow in array dimension"); + TREE_OVERFLOW (itype) = 0; + } + + /* If we're a parm, we need to have a permanent type so + mangling checks for re-use will work right. If both the + element and index types are permanent, the array type + will be, too. */ + if (decl_context == PARM + && allocation_temporary_p () && TREE_PERMANENT (type)) + { + push_obstacks (&permanent_obstack, &permanent_obstack); + itype = build_index_type (itype); + pop_obstacks (); + } + else + itype = build_index_type (itype); + + dont_grok_size: resume_momentary (yes); } @@ -8693,15 +9384,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) inner_decl = TREE_OPERAND (inner_decl, 1); + if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR) + inner_decl = dname; + /* Pick up type qualifiers which should be applied to `this'. */ quals = TREE_OPERAND (declarator, 2); + /* Pick up the exception specifications. */ + raises = TREE_TYPE (declarator); + /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ - funcdecl_p = - inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE - || TREE_CODE (inner_decl) == BIT_NOT_EXPR); - + funcdecl_p + = inner_decl + && (TREE_CODE (inner_decl) == IDENTIFIER_NODE + || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR + || TREE_CODE (inner_decl) == BIT_NOT_EXPR); + if (ctype == NULL_TREE && decl_context == FIELD && funcdecl_p @@ -8726,8 +9425,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli error ("destructor cannot be static member function"); if (quals) { - error ("destructors cannot be declared `const' or `volatile'"); - return void_type_node; + cp_error ("destructors may not be `%s'", + IDENTIFIER_POINTER (TREE_VALUE (quals))); + quals = NULL_TREE; } if (decl_context == FIELD) { @@ -8736,7 +9436,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli return void_type_node; } } - else /* it's a constructor. */ + else /* It's a constructor. */ { if (explicitp == 1) explicitp = 2; @@ -8752,20 +9452,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } if (quals) { - error ("constructors cannot be declared `const' or `volatile'"); - return void_type_node; + cp_error ("constructors may not be `%s'", + IDENTIFIER_POINTER (TREE_VALUE (quals))); + quals = NULL_TREE; } { RID_BIT_TYPE tmp_bits; - bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE)); + bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof (RID_BIT_TYPE)); RIDBIT_RESET (RID_INLINE, tmp_bits); RIDBIT_RESET (RID_STATIC, tmp_bits); if (RIDBIT_ANY_SET (tmp_bits)) error ("return value type specifier for constructor ignored"); } type = build_pointer_type (ctype); - if (decl_context == FIELD && - IS_SIGNATURE (current_class_type)) + if (decl_context == FIELD + && IS_SIGNATURE (current_class_type)) { error ("constructor not allowed in signature"); return void_type_node; @@ -8801,16 +9502,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli name); } - /* Traditionally, declaring return type float means double. */ - - if (flag_traditional - && TYPE_MAIN_VARIANT (type) == float_type_node) - { - type = build_type_variant (double_type_node, - TYPE_READONLY (type), - TYPE_VOLATILE (type)); - } - /* Construct the function type and go to the next inner layer of declarator. */ @@ -8821,31 +9512,39 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0); - if (declarator) + if (declarator && flags == DTOR_FLAG) { - /* Get past destructors, etc. - We know we have one because FLAGS will be non-zero. - - Complain about improper parameter lists here. */ + /* A destructor declared in the body of a class will + be represented as a BIT_NOT_EXPR. But, we just + want the underlying IDENTIFIER. */ if (TREE_CODE (declarator) == BIT_NOT_EXPR) + declarator = TREE_OPERAND (declarator, 0); + + if (strict_prototype == 0 && arg_types == NULL_TREE) + arg_types = void_list_node; + else if (arg_types == NULL_TREE + || arg_types != void_list_node) { - declarator = TREE_OPERAND (declarator, 0); - - if (strict_prototype == 0 && arg_types == NULL_TREE) - arg_types = void_list_node; - else if (arg_types == NULL_TREE - || arg_types != void_list_node) - { - error ("destructors cannot be specified with parameters"); - arg_types = void_list_node; - } + cp_error ("destructors may not have parameters"); + arg_types = void_list_node; + last_function_parms = NULL_TREE; } } - /* ANSI seems to say that `const int foo ();' + /* ANSI says that `const int foo ();' does not make the function foo const. */ - type = build_function_type (type, - flag_traditional ? 0 : arg_types); + type = build_function_type (type, arg_types); + + { + tree t; + for (t = arg_types; t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG) + { + add_defarg_fn (type); + break; + } + } } break; @@ -8928,7 +9627,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } else { - if (TYPE_MAIN_VARIANT (type) == void_type_node) + if (TREE_CODE (type) == VOID_TYPE) error ("invalid type: `void &'"); else type = build_reference_type (type); @@ -8990,6 +9689,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli resolve to. The code here just needs to build up appropriate member types. */ tree sname = TREE_OPERAND (declarator, 1); + tree t; + /* Destructors can have their visibilities changed as well. */ if (TREE_CODE (sname) == BIT_NOT_EXPR) sname = TREE_OPERAND (sname, 0); @@ -8997,10 +9698,29 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli if (TREE_COMPLEXITY (declarator) == 0) /* This needs to be here, in case we are called multiple times. */ ; + else if (TREE_COMPLEXITY (declarator) == -1) + /* Namespace member. */ + pop_decl_namespace (); else if (friendp && (TREE_COMPLEXITY (declarator) < 2)) - /* don't fall out into global scope. Hides real bug? --eichin */ ; + /* Don't fall out into global scope. Hides real bug? --eichin */ ; + else if (! IS_AGGR_TYPE_CODE + (TREE_CODE (TREE_OPERAND (declarator, 0)))) + ; else if (TREE_COMPLEXITY (declarator) == current_class_depth) { + /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq + that refer to ctype. They couldn't be resolved earlier + because we hadn't pushed into the class yet. + Example: resolve 'B::type' in + 'B::type> B::f () { }'. */ + if (current_template_parms + && uses_template_parms (type) + && uses_template_parms (current_class_type)) + { + tree args = current_template_args (); + type = tsubst (type, args, 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 @@ -9022,6 +9742,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } ctype = TREE_OPERAND (declarator, 0); + t = ctype; + while (t != NULL_TREE) + { + if (CLASSTYPE_TEMPLATE_INFO (t) && + !CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) + template_count += 1; + t = TYPE_MAIN_DECL (t); + if (DECL_LANG_SPECIFIC (t)) + t = DECL_CLASS_CONTEXT (t); + else + t = NULL_TREE; + } + if (sname == NULL_TREE) goto done_scoping; @@ -9055,53 +9788,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli return void_type_node; } } - else if (TYPE_SIZE (ctype) != NULL_TREE - || (RIDBIT_SETP (RID_TYPEDEF, specbits))) + else if (RIDBIT_SETP (RID_TYPEDEF, specbits) + || TYPE_SIZE (complete_type (ctype)) != NULL_TREE) { - tree t; - /* have to move this code elsewhere in this function. + /* Have to move this code elsewhere in this function. this code is used for i.e., typedef int A::M; M *pm; It is? How? jason 10/2/94 */ - if (explicit_int == -1 && decl_context == FIELD - && funcdef_flag == 0) - { - /* The code in here should only be used to build - stuff that will be grokked as access decls. */ - t = lookup_field (ctype, sname, 0, 0); - if (t) - { - t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type); - DECL_INITIAL (t) = init; - return t; - } - /* No such field, try member functions. */ - t = lookup_fnfields (TYPE_BINFO (ctype), sname, 0); - if (t) - { - if (flags == DTOR_FLAG) - t = TREE_VALUE (t); - else if (CLASSTYPE_METHOD_VEC (ctype) - && TREE_VALUE (t) == TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), 0)) - { - /* Don't include destructor with constructors. */ - t = DECL_CHAIN (TREE_VALUE (t)); - if (t == NULL_TREE) - cp_error ("`%T' does not have any constructors", - ctype); - t = build_tree_list (NULL_TREE, t); - } - t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type); - DECL_INITIAL (t) = init; - return t; - } - - cp_error - ("field `%D' is not a member of structure `%T'", - sname, ctype); - } - if (current_class_type) { cp_error ("cannot declare member `%T::%s' within `%T'", @@ -9112,14 +9806,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } else if (uses_template_parms (ctype)) { - enum tree_code c; if (TREE_CODE (type) == FUNCTION_TYPE) - { - type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), - TREE_TYPE (type), - TYPE_ARG_TYPES (type)); - c = FUNCTION_DECL; - } + type + = build_cplus_method_type (build_type_variant (ctype, + constp, + volatilep), + TREE_TYPE (type), + TYPE_ARG_TYPES (type)); } else { @@ -9192,7 +9885,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } } - if (RIDBIT_SETP (RID_TYPEDEF, specbits)) + if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME) { tree decl; @@ -9200,45 +9893,61 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli 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) + cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class", + declarator); + decl = build_lang_decl (TYPE_DECL, declarator, type); + if (IS_SIGNATURE (current_class_type) && opaque_typedef) + SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1; + } + else + { + /* Make sure this typedef lives as long as its type, + since it might be used as a template parameter. */ + if (type != error_mark_node) + push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); + decl = build_decl (TYPE_DECL, declarator, type); + if (type != error_mark_node) + pop_obstacks (); + } /* If the user declares "struct {...} foo" then `foo' will have an anonymous name. Fill that name in now. Nothing can 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))) { - /* replace the anonymous name with the real name everywhere. */ + /* Replace the anonymous name with the real name everywhere. */ lookup_tag_reverse (type, declarator); - TYPE_IDENTIFIER (type) = declarator; + TYPE_NAME (type) = decl; if (TYPE_LANG_SPECIFIC (type)) TYPE_WAS_ANONYMOUS (type) = 1; - { - tree d = TYPE_NAME (type), c = DECL_CONTEXT (d); - - if (!c) - set_nested_typename (d, 0, declarator, type); - else if (TREE_CODE (c) == FUNCTION_DECL) - set_nested_typename (d, DECL_ASSEMBLER_NAME (c), - declarator, type); - else - set_nested_typename (d, TYPE_NESTED_NAME (c), declarator, type); + /* XXX Temporarily set the scope. + When returning, start_decl expects it as NULL_TREE, + and will then then set it using pushdecl. */ + my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404); + if (current_class_type) + DECL_CONTEXT (decl) = current_class_type; + else + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); - DECL_ASSEMBLER_NAME (d) = DECL_NAME (d); - DECL_ASSEMBLER_NAME (d) - = get_identifier (build_overload_name (type, 1, 1)); - } + DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl); + DECL_ASSEMBLER_NAME (decl) + = get_identifier (build_overload_name (type, 1, 1)); + DECL_CONTEXT (decl) = NULL_TREE; } -#if 0 /* not yet, should get fixed properly later */ - decl = make_type_decl (declarator, type); -#else - decl = build_decl (TYPE_DECL, declarator, type); -#endif if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE) { cp_error_at ("typedef name may not be class-qualified", decl); @@ -9266,6 +9975,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli error ("non-object member `%s' cannot be declared mutable", name); } + bad_specifiers (decl, "type", virtualp, quals != NULL_TREE, + inlinep, friendp, raises != NULL_TREE); + + if (initialized) + error ("typedef declaration includes an initializer"); + return decl; } @@ -9289,10 +10004,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli /* Note that the grammar rejects storage classes in typenames, fields or parameters. */ if (constp || volatilep) - if (IS_SIGNATURE (type)) - error ("`const' or `volatile' specified with signature type"); - else - type = cp_build_type_variant (type, constp, volatilep); + { + if (IS_SIGNATURE (type)) + error ("`const' or `volatile' specified with signature type"); + else + type = cp_build_type_variant (type, constp, volatilep); + } /* Special case: "friend class foo" looks like a TYPENAME context. */ if (friendp) @@ -9322,11 +10039,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } else if (quals) { -#if 0 /* not yet, should get fixed properly later */ - tree dummy = make_type_decl (declarator, type); -#else tree dummy = build_decl (TYPE_DECL, declarator, type); -#endif if (ctype == NULL_TREE) { my_friendly_assert (TREE_CODE (type) == METHOD_TYPE, 159); @@ -9352,19 +10065,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli We don't complain about parms either, but that is because a better error message can be made later. */ - if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM) + if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM) { if (! declarator) error ("unnamed variable or field declared void"); else if (TREE_CODE (declarator) == IDENTIFIER_NODE) { if (IDENTIFIER_OPNAME_P (declarator)) -#if 0 /* How could this happen? */ - error ("operator `%s' declared void", - operator_name_string (declarator)); -#else my_friendly_abort (356); -#endif else error ("variable or field `%s' declared void", name); } @@ -9390,7 +10098,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli if (TREE_CODE (type) == ARRAY_TYPE) { - /* Transfer const-ness of array into that of type pointed to. */ + /* Transfer const-ness of array into that of type pointed to. */ type = build_pointer_type (cp_build_type_variant (TREE_TYPE (type), constp, volatilep)); volatilep = constp = 0; @@ -9399,13 +10107,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli type = build_pointer_type (type); else if (TREE_CODE (type) == OFFSET_TYPE) type = build_pointer_type (type); - else if (type == void_type_node && declarator) + else if (TREE_CODE (type) == VOID_TYPE && declarator) { error ("declaration of `%s' as void", name); return NULL_TREE; } - decl = build_decl (PARM_DECL, declarator, type); + decl = build_decl (PARM_DECL, declarator, complete_type (type)); bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); @@ -9438,6 +10146,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli else if (TREE_CODE (type) == FUNCTION_TYPE) { int publicp = 0; + tree function_context; + + /* We catch the others as conflicts with the builtin + typedefs. */ + if (friendp && declarator == ridpointers[(int) RID_SIGNED]) + { + cp_error ("function `%D' cannot be declared friend", + declarator); + friendp = 0; + } if (friendp == 0) { @@ -9478,15 +10196,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ - publicp = (! friendp - || RIDBIT_SETP (RID_EXTERN, specbits) - || ! (funcdef_flag < 0 || inlinep)); - decl = grokfndecl (ctype, type, declarator, + function_context = (ctype != NULL_TREE) ? + hack_decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE; + publicp = (! friendp || ! staticp) + && function_context == NULL_TREE; + decl = grokfndecl (ctype, type, + TREE_CODE (declarator) != TEMPLATE_ID_EXPR + ? declarator : dname, + declarator, virtualp, flags, quals, raises, attrlist, - friendp ? -1 : 0, publicp, inlinep); + friendp ? -1 : 0, friendp, publicp, inlinep, + funcdef_flag, template_count, in_namespace); if (decl == NULL_TREE) return NULL_TREE; +#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 if (explicitp == 2) DECL_NONCONVERTING_P (decl) = 1; @@ -9497,13 +10224,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli members of other classes. */ /* All method decls are public, so tell grokfndecl to set TREE_PUBLIC, also. */ - decl = grokfndecl (ctype, type, declarator, + decl = grokfndecl (ctype, type, declarator, declarator, virtualp, flags, quals, raises, attrlist, - friendp ? -1 : 0, 1, 0); + friendp ? -1 : 0, friendp, 1, 0, funcdef_flag, + template_count, in_namespace); if (decl == NULL_TREE) return NULL_TREE; } - else if (TYPE_SIZE (type) == NULL_TREE && !staticp + else if (!staticp && ! processing_template_decl + && TYPE_SIZE (complete_type (type)) == NULL_TREE && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { if (declarator) @@ -9515,7 +10244,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli instantiation made the field's type be incomplete. */ if (current_class_type && TYPE_NAME (current_class_type) - && IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (current_class_type))) + && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)) && declspecs && TREE_VALUE (declspecs) && TREE_TYPE (TREE_VALUE (declspecs)) == type) cp_error (" in instantiation of template `%T'", @@ -9545,7 +10274,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli tree t = NULL_TREE; if (decl && DECL_NAME (decl)) t = do_friend (ctype, declarator, decl, - last_function_parms, flags, quals); + last_function_parms, flags, quals, + funcdef_flag); if (t && funcdef_flag) return t; @@ -9559,6 +10289,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli { if (initialized) { + if (!staticp) + { + /* An attempt is being made to initialize a non-static + member. But, from [class.mem]: + + 4 A member-declarator can contain a + constant-initializer only if it declares a static + member (_class.static_) of integral or enumeration + type, see _class.static.data_. + + This used to be relatively common practice, but + 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", + 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 @@ -9566,34 +10317,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli but not both. If it appears in the class, the member is a member constant. The file-scope definition is always required. */ - if (staticp) - { - if (pedantic) - { - if (! constp) - cp_pedwarn ("ANSI C++ forbids in-class initialization of non-const static member `%D'", - declarator); - - else if (! INTEGRAL_TYPE_P (type)) - cp_pedwarn ("ANSI C++ forbids member constant `%D' of non-integral type `%T'", declarator, type); - } - } - - /* Note that initialization of const members is prohibited - by the draft ANSI standard, though it appears to be in - common practice. 12.6.2: The argument list is used to - initialize the named nonstatic member.... This (or an - initializer list) is the only way to initialize - nonstatic const and reference members. */ - else if (pedantic || ! constp) - cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'", - constp ? "const member" : "member", declarator); + 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 (staticp || (constp && initialized)) + if (staticp) { /* ANSI C++ Apr '95 wp 9.2 */ - if (staticp && declarator == current_class_name) + if (declarator == current_class_name) cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class", declarator); @@ -9604,7 +10343,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli decl = build_lang_field_decl (VAR_DECL, declarator, type); TREE_STATIC (decl) = 1; /* In class context, 'static' means public access. */ - TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = !!staticp; + TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1; } else { @@ -9622,12 +10361,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) { - tree original_name = declarator; + tree original_name; int publicp = 0; if (! declarator) return NULL_TREE; + if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + original_name = dname; + else + original_name = declarator; + if (RIDBIT_SETP (RID_AUTO, specbits)) error ("storage class `auto' invalid for function `%s'", name); else if (RIDBIT_SETP (RID_REGISTER, specbits)) @@ -9637,7 +10381,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli Storage classes other than `extern' are not allowed and `extern' makes no difference. */ if (! toplevel_bindings_p () - && ! processing_template_decl && (RIDBIT_SETP (RID_STATIC, specbits) || RIDBIT_SETP (RID_INLINE, specbits)) && pedantic) @@ -9657,36 +10400,44 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } if (current_lang_name == lang_name_cplusplus - && ! (IDENTIFIER_LENGTH (original_name) == 4 - && IDENTIFIER_POINTER (original_name)[0] == 'm' - && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0) + && ! 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. */ - declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0); + 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)); - /* Record presence of `static'. In C++, `inline' implies `static'. */ + /* Record presence of `static'. */ publicp = (ctype != NULL_TREE || RIDBIT_SETP (RID_EXTERN, specbits) - || (!RIDBIT_SETP (RID_STATIC, specbits) - && !RIDBIT_SETP (RID_INLINE, specbits))); + || !RIDBIT_SETP (RID_STATIC, specbits)); - decl = grokfndecl (ctype, type, original_name, + decl = grokfndecl (ctype, type, original_name, declarator, virtualp, flags, quals, raises, attrlist, - processing_template_decl ? 0 : friendp ? 2 : 1, - publicp, inlinep); + 1, friendp, + publicp, inlinep, funcdef_flag, + template_count, in_namespace); if (decl == NULL_TREE) return NULL_TREE; - if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c) - DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator); + /* 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; @@ -9730,7 +10481,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli if (TREE_CODE (type) == ARRAY_TYPE) { - /* Transfer const-ness of array into that of type pointed to. */ + /* Transfer const-ness of array into that of type + pointed to. */ type = build_pointer_type (cp_build_type_variant (TREE_TYPE (type), constp, volatilep)); volatilep = constp = 0; @@ -9742,7 +10494,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli } /* An uninitialized decl with `extern' is a reference. */ - decl = grokvardecl (type, declarator, specbits, initialized, constp); + decl = grokvardecl (type, declarator, &specbits, + initialized, constp, in_namespace); bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); @@ -9804,6 +10557,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli An empty exprlist is a parmlist. An exprlist which contains only identifiers at the global level is a parmlist. Otherwise, it is an exprlist. */ + int parmlist_is_exprlist (exprs) tree exprs; @@ -9830,14 +10584,18 @@ parmlist_is_exprlist (exprs) be complete. C++: also subroutine of `start_function'. */ + static void require_complete_types_for_parms (parms) tree parms; { + if (processing_template_decl) + return; + while (parms) { tree type = TREE_TYPE (parms); - if (TYPE_SIZE (type) == NULL_TREE) + if (TYPE_SIZE (complete_type (type)) == NULL_TREE) { if (DECL_NAME (parms)) error ("parameter `%s' has incomplete type", @@ -9928,14 +10686,14 @@ grokparms (first_parm, funcdef_flag) } else if (first_parm != NULL_TREE && TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST - && TREE_VALUE (first_parm) != void_type_node) + && TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE) my_friendly_abort (145); else { /* Types were specified. This is a list of declarators each represented as a TREE_LIST node. */ register tree parm, chain; - int any_init = 0, any_error = 0, saw_void = 0; + int any_init = 0, any_error = 0; if (first_parm != NULL_TREE) { @@ -9944,42 +10702,41 @@ grokparms (first_parm, funcdef_flag) for (parm = first_parm; parm != NULL_TREE; parm = chain) { - tree type, list_node = parm; + tree type = NULL_TREE, list_node = parm; register tree decl = TREE_VALUE (parm); tree init = TREE_PURPOSE (parm); chain = TREE_CHAIN (parm); /* @@ weak defense against parse errors. */ - if (decl != void_type_node && TREE_CODE (decl) != TREE_LIST) + if (TREE_CODE (decl) != VOID_TYPE + && TREE_CODE (decl) != TREE_LIST) { /* Give various messages as the need arises. */ if (TREE_CODE (decl) == STRING_CST) - error ("invalid string constant `%s'", - TREE_STRING_POINTER (decl)); + cp_error ("invalid string constant `%E'", decl); else if (TREE_CODE (decl) == INTEGER_CST) error ("invalid integer constant in parameter list, did you forget to give parameter name?"); continue; } - if (decl != void_type_node) + if (TREE_CODE (decl) != VOID_TYPE) { - /* @@ May need to fetch out a `raises' here. */ decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl), PARM, init != NULL_TREE, - NULL_TREE, NULL_TREE); + NULL_TREE); if (! decl) continue; type = TREE_TYPE (decl); - if (TYPE_MAIN_VARIANT (type) == void_type_node) + if (TREE_CODE (type) == VOID_TYPE) decl = void_type_node; else if (TREE_CODE (type) == METHOD_TYPE) { if (DECL_NAME (decl)) - /* Cannot use `error_with_decl' here because + /* Cannot use the decl here because we don't have DECL_CONTEXT set up yet. */ - error ("parameter `%s' invalidly declared method type", - IDENTIFIER_POINTER (DECL_NAME (decl))); + cp_error ("parameter `%D' invalidly declared method type", + DECL_NAME (decl)); else error ("parameter invalidly declared method type"); type = build_pointer_type (type); @@ -9988,8 +10745,8 @@ grokparms (first_parm, funcdef_flag) else if (TREE_CODE (type) == OFFSET_TYPE) { if (DECL_NAME (decl)) - error ("parameter `%s' invalidly declared offset type", - IDENTIFIER_POINTER (DECL_NAME (decl))); + cp_error ("parameter `%D' invalidly declared offset type", + DECL_NAME (decl)); else error ("parameter invalidly declared offset type"); type = build_pointer_type (type); @@ -10000,18 +10757,18 @@ grokparms (first_parm, funcdef_flag) && CLASSTYPE_ABSTRACT_VIRTUALS (type)) { abstract_virtuals_error (decl, type); - any_error = 1; /* seems like a good idea */ + any_error = 1; /* Seems like a good idea. */ } else if (TREE_CODE (type) == RECORD_TYPE && TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type)) { signature_error (decl, type); - any_error = 1; /* seems like a good idea */ + any_error = 1; /* Seems like a good idea. */ } } - if (decl == void_type_node) + if (TREE_CODE (decl) == VOID_TYPE) { if (result == NULL_TREE) { @@ -10023,7 +10780,6 @@ grokparms (first_parm, funcdef_flag) TREE_CHAIN (last_result) = void_list_node; last_result = void_list_node; } - saw_void = 1; if (chain && (chain != void_list_node || TREE_CHAIN (chain))) error ("`void' in parameter list must be entire list"); @@ -10045,6 +10801,11 @@ grokparms (first_parm, funcdef_flag) 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) { @@ -10054,7 +10815,7 @@ grokparms (first_parm, funcdef_flag) 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. */ + wrong. */ cp_error ("local variable `%D' may not be used as a default argument", init); any_error = 1; } @@ -10063,15 +10824,13 @@ grokparms (first_parm, funcdef_flag) } else init = require_instantiated_type (type, init, integer_zero_node); - } -#if 0 /* This is too early to check; trailing parms might be merged in by - duplicate_decls. */ - else if (any_init) - { - error ("all trailing parameters must have default arguments"); - any_error = 1; + 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); } -#endif } else init = NULL_TREE; @@ -10086,7 +10845,7 @@ grokparms (first_parm, funcdef_flag) TREE_CHAIN (last_decl) = decl; last_decl = decl; } - if (TREE_PERMANENT (list_node)) + if (! current_function_decl && TREE_PERMANENT (list_node)) { TREE_PURPOSE (list_node) = init; TREE_VALUE (list_node) = type; @@ -10122,7 +10881,40 @@ grokparms (first_parm, funcdef_flag) return result; } + +/* Called from the parser to update an element of TYPE_ARG_TYPES for some + FUNCTION_TYPE with the newly parsed version of its default argument, which + was previously digested as text. See snarf_defarg et al in lex.c. */ + +void +replace_defarg (arg, init) + tree arg, init; +{ + if (! processing_template_decl + && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init)) + cp_pedwarn ("invalid type `%T' for default argument to `%T'", + TREE_TYPE (init), TREE_VALUE (arg)); + TREE_PURPOSE (arg) = init; +} +int +copy_args_p (d) + tree d; +{ + tree t = FUNCTION_ARG_CHAIN (d); + if (DECL_CONSTRUCTOR_P (d) + && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d))) + t = TREE_CHAIN (t); + if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE + && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t))) + == DECL_CLASS_CONTEXT (d)) + && (TREE_CHAIN (t) == NULL_TREE + || TREE_CHAIN (t) == void_list_node + || TREE_PURPOSE (TREE_CHAIN (t)))) + return 1; + return 0; +} + /* These memoizing functions keep track of special properties which a class may have. `grok_ctor_properties' notices whether a class has a constructor of the form X(X&), and also complains @@ -10130,6 +10922,7 @@ grokparms (first_parm, funcdef_flag) `grok_op_properties' takes notice of the various forms of operator= which are defined, as well as what sorts of type conversion may apply. Both functions take a FUNCTION_DECL as an argument. */ + int grok_ctor_properties (ctype, decl) tree ctype, decl; @@ -10141,41 +10934,33 @@ grok_ctor_properties (ctype, decl) added to any ctor so we can tell if the class has been initialized yet. This could screw things up in this function, so we deliberately ignore the leading int if we're in that situation. */ - if (parmtypes - && TREE_VALUE (parmtypes) == integer_type_node - && TYPE_USES_VIRTUAL_BASECLASSES (ctype)) + if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) { + my_friendly_assert (parmtypes + && TREE_VALUE (parmtypes) == integer_type_node, + 980529); parmtypes = TREE_CHAIN (parmtypes); parmtype = TREE_VALUE (parmtypes); } if (TREE_CODE (parmtype) == REFERENCE_TYPE - && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype) - { - if (TREE_CHAIN (parmtypes) == NULL_TREE + && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype + && (TREE_CHAIN (parmtypes) == NULL_TREE || TREE_CHAIN (parmtypes) == void_list_node - || TREE_PURPOSE (TREE_CHAIN (parmtypes))) - { - TYPE_HAS_INIT_REF (ctype) = 1; - if (TYPE_READONLY (TREE_TYPE (parmtype))) - TYPE_HAS_CONST_INIT_REF (ctype) = 1; - } - else - TYPE_GETS_INIT_AGGR (ctype) = 1; + || TREE_PURPOSE (TREE_CHAIN (parmtypes)))) + { + TYPE_HAS_INIT_REF (ctype) = 1; + if (TYPE_READONLY (TREE_TYPE (parmtype))) + TYPE_HAS_CONST_INIT_REF (ctype) = 1; } - else if (TYPE_MAIN_VARIANT (parmtype) == ctype) + else if (TYPE_MAIN_VARIANT (parmtype) == ctype + && TREE_CHAIN (parmtypes) != NULL_TREE + && TREE_CHAIN (parmtypes) == void_list_node) { - if (TREE_CHAIN (parmtypes) != NULL_TREE - && TREE_CHAIN (parmtypes) == void_list_node) - { - cp_error ("invalid constructor; you probably meant `%T (%T&)'", - ctype, ctype); - SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype); - - return 0; - } - else - TYPE_GETS_INIT_AGGR (ctype) = 1; + cp_error ("invalid constructor; you probably meant `%T (const %T&)'", + ctype, ctype); + SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype); + return 0; } else if (TREE_CODE (parmtype) == VOID_TYPE || TREE_PURPOSE (parmtypes) != NULL_TREE) @@ -10185,6 +10970,7 @@ grok_ctor_properties (ctype, decl) } /* An operator with this name can be either unary or binary. */ + static int ambi_op_p (name) tree name; @@ -10198,6 +10984,7 @@ ambi_op_p (name) } /* An operator with this name can only be unary. */ + static int unary_op_p (name) tree name; @@ -10209,7 +10996,8 @@ unary_op_p (name) } /* Do a little sanity-checking on how they declared their operator. */ -static void + +void grok_op_properties (decl, virtualp, friendp) tree decl; int virtualp, friendp; @@ -10252,10 +11040,10 @@ grok_op_properties (decl, virtualp, friendp) /* Take care of function decl if we had syntax errors. */ if (argtypes == NULL_TREE) - TREE_TYPE (decl) = - build_function_type (ptr_type_node, - hash_tree_chain (integer_type_node, - void_list_node)); + TREE_TYPE (decl) + = build_function_type (ptr_type_node, + hash_tree_chain (integer_type_node, + void_list_node)); else TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); } @@ -10266,10 +11054,10 @@ grok_op_properties (decl, virtualp, friendp) revert_static_member_fn (&decl, NULL, NULL); if (argtypes == NULL_TREE) - TREE_TYPE (decl) = - build_function_type (void_type_node, - hash_tree_chain (ptr_type_node, - void_list_node)); + TREE_TYPE (decl) + = build_function_type (void_type_node, + hash_tree_chain (ptr_type_node, + void_list_node)); else { TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl)); @@ -10301,7 +11089,7 @@ grok_op_properties (decl, virtualp, friendp) cp_error ("`%D' must be either a non-static member function or a non-member function", decl); if (p) - for (; TREE_VALUE (p) != void_type_node ; p = TREE_CHAIN (p)) + for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p)) { tree arg = TREE_VALUE (p); if (TREE_CODE (arg) == REFERENCE_TYPE) @@ -10310,7 +11098,8 @@ grok_op_properties (decl, virtualp, friendp) /* This lets bad template code slip through. */ if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE - || TREE_CODE (arg) == TEMPLATE_TYPE_PARM) + || TREE_CODE (arg) == TEMPLATE_TYPE_PARM + || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) goto foundaggr; } cp_error @@ -10321,11 +11110,10 @@ grok_op_properties (decl, virtualp, friendp) } } - if (name == ansi_opname[(int) CALL_EXPR] - || name == ansi_opname[(int) METHOD_CALL_EXPR]) - return; /* no restrictions on args */ + if (name == ansi_opname[(int) CALL_EXPR]) + return; /* No restrictions on args. */ - if (IDENTIFIER_TYPENAME_P (name)) + if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl)) { tree t = TREE_TYPE (name); if (TREE_CODE (t) == VOID_TYPE) @@ -10339,7 +11127,9 @@ grok_op_properties (decl, virtualp, friendp) if (t == current_class_type) what = "the same type"; + /* Don't force t to be complete here. */ else if (IS_AGGR_TYPE (t) + && TYPE_SIZE (t) && DERIVED_FROM_P (t, current_class_type)) what = "a base class"; @@ -10367,10 +11157,6 @@ grok_op_properties (decl, virtualp, friendp) if (TREE_CODE (parmtype) != REFERENCE_TYPE || TYPE_READONLY (TREE_TYPE (parmtype))) TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1; -#if 0 /* Too soon; done in grok_function_init */ - if (DECL_ABSTRACT_VIRTUAL_P (decl)) - TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1; -#endif } } else if (name == ansi_opname[(int) COND_EXPR]) @@ -10388,6 +11174,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) { if (methodp) @@ -10406,6 +11193,31 @@ grok_op_properties (decl, virtualp, friendp) else cp_error ("`%D' must take either one or two arguments", decl); } + + /* More Effective C++ rule 6. */ + if (warn_ecpp + && (name == ansi_opname[(int) POSTINCREMENT_EXPR] + || name == ansi_opname[(int) POSTDECREMENT_EXPR])) + { + tree arg = TREE_VALUE (argtypes); + tree ret = TREE_TYPE (TREE_TYPE (decl)); + if (methodp || TREE_CODE (arg) == REFERENCE_TYPE) + arg = TREE_TYPE (arg); + arg = TYPE_MAIN_VARIANT (arg); + if (list_length (argtypes) == 2) + { + if (TREE_CODE (ret) != REFERENCE_TYPE + || !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ret)), + arg, 1)) + cp_warning ("prefix `%D' should return `%T'", decl, + build_reference_type (arg)); + } + else + { + if (!comptypes (TYPE_MAIN_VARIANT (ret), arg, 1)) + cp_warning ("postfix `%D' should return `%T'", decl, arg); + } + } } else if (unary_op_p (name)) { @@ -10426,7 +11238,25 @@ grok_op_properties (decl, virtualp, friendp) else cp_error ("`%D' must take exactly two arguments", decl); } - } + + /* More Effective C++ rule 7. */ + if (warn_ecpp + && (name == ansi_opname [TRUTH_ANDIF_EXPR] + || name == ansi_opname [TRUTH_ORIF_EXPR] + || name == ansi_opname [COMPOUND_EXPR])) + cp_warning ("user-defined `%D' always evaluates both arguments", + decl); + } + + /* Effective C++ rule 23. */ + if (warn_ecpp + && list_length (argtypes) == 3 + && (name == ansi_opname [PLUS_EXPR] + || name == ansi_opname [MINUS_EXPR] + || name == ansi_opname [TRUNC_DIV_EXPR] + || name == ansi_opname [MULT_EXPR]) + && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE) + cp_warning ("`%D' should return by value", decl); /* 13.4.0.8 */ if (argtypes) @@ -10465,9 +11295,20 @@ xref_tag (code_type_node, name, binfo, globalize) enum tag_types tag_code; enum tree_code code; int temp = 0; - int i; register tree ref, t; struct binding_level *b = inner_binding_level; + int got_type = 0; + tree attributes = NULL_TREE; + + /* If we are called from the parser, code_type_node will sometimes be a + TREE_LIST. This indicates that the user wrote + "class __attribute__ ((foo)) bar". Extract the attributes so we can + use them later. */ + if (TREE_CODE (code_type_node) == TREE_LIST) + { + attributes = TREE_PURPOSE (code_type_node); + code_type_node = TREE_VALUE (code_type_node); + } tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node); switch (tag_code) @@ -10489,18 +11330,34 @@ xref_tag (code_type_node, name, binfo, globalize) /* If a cross reference is requested, look up the type already defined for this tag and return it. */ - t = IDENTIFIER_TYPE_VALUE (name); - if (t && TREE_CODE (t) != code) + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + { + t = name; + name = TYPE_IDENTIFIER (t); + got_type = 1; + } + 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 we know we are defining this tag, only look it up in this scope - * and don't try to find it as a type. */ - if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name)) + 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 - 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 { @@ -10513,6 +11370,15 @@ xref_tag (code_type_node, name, binfo, globalize) { /* Try finding it as a type declaration. If that wins, use it. */ ref = lookup_name (name, 1); + + if (ref != NULL_TREE + && processing_template_decl + && DECL_CLASS_TEMPLATE_P (ref) + && template_class_depth (current_class_type) == 0) + /* Since GLOBALIZE is true, we're declaring a global + template, so we want this type. */ + ref = DECL_RESULT (ref); + if (ref && TREE_CODE (ref) == TYPE_DECL && TREE_CODE (TREE_TYPE (ref)) == code) ref = TREE_TYPE (ref); @@ -10539,6 +11405,8 @@ xref_tag (code_type_node, name, binfo, globalize) if (code == ENUMERAL_TYPE) { + cp_error ("use of enum `%#D' without previous declaration", name); + ref = make_node (ENUMERAL_TYPE); /* Give the type a default layout like unsigned int @@ -10556,8 +11424,6 @@ xref_tag (code_type_node, name, binfo, globalize) done in `start_enum'. */ pushtag (name, ref, globalize); - if (flag_cadillac) - cadillac_start_enum (ref); } else { @@ -10582,50 +11448,27 @@ xref_tag (code_type_node, name, binfo, globalize) #endif pushtag (name, ref, globalize); class_binding_level = old_b; - - if (flag_cadillac) - cadillac_start_struct (ref); } } else { /* If it no longer looks like a nested type, make sure it's - in global scope. */ - if (b == global_binding_level && !class_binding_level - && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE) - IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref); - -#if 0 - if (binfo) + in global scope. + If it is not an IDENTIFIER, this is not a declaration */ + if (b->namespace_p && !class_binding_level + && TREE_CODE (name) == IDENTIFIER_NODE) { - tree tt1 = binfo; - tree tt2 = TYPE_BINFO_BASETYPES (ref); - - if (TYPE_BINFO_BASETYPES (ref)) - for (i = 0; tt1; i++, tt1 = TREE_CHAIN (tt1)) - if (TREE_VALUE (tt1) != TYPE_IDENTIFIER (BINFO_TYPE (TREE_VEC_ELT (tt2, i)))) - { - cp_error ("redeclaration of derivation chain of type `%#T'", - ref); - break; - } - - if (tt1 == NULL_TREE) - /* The user told us something we already knew. */ - goto just_return; - - /* In C++, since these migrate into the global scope, we must - build them on the permanent obstack. */ - end_temporary_allocation (); + if (IDENTIFIER_NAMESPACE_VALUE (name) == NULL_TREE) + SET_IDENTIFIER_NAMESPACE_VALUE (name, TYPE_NAME (ref)); } -#endif + + if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref)) + redeclare_class_template (ref, current_template_parms); } if (binfo) xref_basetypes (code_type_node, name, ref, binfo); - just_return: - /* Until the type is defined, tentatively accept whatever structure tag the user hands us. */ if (TYPE_SIZE (ref) == NULL_TREE @@ -10641,9 +11484,30 @@ xref_tag (code_type_node, name, binfo, globalize) pop_obstacks (); + TREE_TYPE (ref) = attributes; + return ref; } +tree +xref_tag_from_type (old, id, globalize) + tree old, id; + int globalize; +{ + tree code_type_node; + + if (TREE_CODE (old) == RECORD_TYPE) + code_type_node = (CLASSTYPE_DECLARED_CLASS (old) + ? class_type_node : record_type_node); + else + code_type_node = union_type_node; + + if (id == NULL_TREE) + id = TYPE_IDENTIFIER (old); + + return xref_tag (code_type_node, id, NULL_TREE, globalize); +} + void xref_basetypes (code_type_node, name, ref, binfo) tree code_type_node; @@ -10672,34 +11536,42 @@ xref_basetypes (code_type_node, name, ref, binfo) { /* The base of a derived struct is public by default. */ int via_public - = (TREE_PURPOSE (binfo) == (tree)access_public - || TREE_PURPOSE (binfo) == (tree)access_public_virtual + = (TREE_PURPOSE (binfo) == access_public_node + || TREE_PURPOSE (binfo) == access_public_virtual_node || (tag_code != class_type - && (TREE_PURPOSE (binfo) == (tree)access_default - || TREE_PURPOSE (binfo) == (tree)access_default_virtual))); - int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected; + && (TREE_PURPOSE (binfo) == access_default_node + || TREE_PURPOSE (binfo) == access_default_virtual_node))); + int via_protected + = (TREE_PURPOSE (binfo) == access_protected_node + || TREE_PURPOSE (binfo) == access_protected_virtual_node); int via_virtual - = (TREE_PURPOSE (binfo) == (tree)access_private_virtual - || TREE_PURPOSE (binfo) == (tree)access_public_virtual - || TREE_PURPOSE (binfo) == (tree)access_default_virtual); - tree basetype = TREE_TYPE (TREE_VALUE (binfo)); + = (TREE_PURPOSE (binfo) == access_private_virtual_node + || TREE_PURPOSE (binfo) == access_protected_virtual_node + || TREE_PURPOSE (binfo) == access_public_virtual_node + || TREE_PURPOSE (binfo) == access_default_virtual_node); + tree basetype = TREE_VALUE (binfo); tree base_binfo; - GNU_xref_hier (IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (TREE_VALUE (binfo)), - via_public, via_virtual, 0); - if (basetype && TREE_CODE (basetype) == TYPE_DECL) basetype = TREE_TYPE (basetype); - if (!basetype || TREE_CODE (basetype) != RECORD_TYPE) + if (!basetype + || (TREE_CODE (basetype) != RECORD_TYPE + && TREE_CODE (basetype) != TYPENAME_TYPE + && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM + && TREE_CODE (basetype) != TEMPLATE_TEMPLATE_PARM)) { cp_error ("base type `%T' fails to be a struct or class type", TREE_VALUE (binfo)); continue; } + + GNU_xref_hier (name, basetype, via_public, via_virtual, 0); + #if 1 - /* This code replaces similar code in layout_basetypes. */ - else if (TYPE_INCOMPLETE (basetype)) + /* 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 + && ! (current_template_parms && uses_template_parms (basetype))) { cp_error ("base class `%T' has incomplete type", basetype); continue; @@ -10716,6 +11588,10 @@ xref_basetypes (code_type_node, name, ref, binfo) continue; } + if (TYPE_FOR_JAVA (basetype) + && current_lang_stack == current_lang_base) + TYPE_FOR_JAVA (ref) = 1; + /* Note that the BINFO records which describe individual inheritances are *not* shared in the lattice! They cannot be shared because a given baseclass may be @@ -10735,17 +11611,7 @@ xref_basetypes (code_type_node, name, ref, binfo) BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); SET_CLASSTYPE_MARKED (basetype); -#if 0 - /* XYZZY TEST VIRTUAL BASECLASSES */ - if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE - && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype) - && via_virtual == 0) - { - warning ("making type `%s' a virtual baseclass", - TYPE_NAME_STRING (basetype)); - via_virtual = 1; - } -#endif + /* We are free to modify these bits because they are meaningless at top level, and BASETYPE is a top-level type. */ if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) @@ -10754,7 +11620,6 @@ xref_basetypes (code_type_node, name, ref, binfo) TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; } - TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); @@ -10783,7 +11648,7 @@ xref_basetypes (code_type_node, name, ref, binfo) } -static tree current_local_enum = NULL_TREE; +tree current_local_enum = NULL_TREE; /* Begin compiling the definition of an enumeration type. NAME is its name (or null if anonymous). @@ -10798,6 +11663,14 @@ start_enum (name) register tree enumtype = NULL_TREE; struct binding_level *b = inner_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 (); + /* If this is the real definition for a previous forward reference, fill in the contents in the same object that used to be the forward reference. */ @@ -10806,36 +11679,23 @@ start_enum (name) enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1); if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE) - cp_error ("multiple definition of enum `%T'", enumtype); + cp_error ("multiple definition of `%#T'", enumtype); else { enumtype = make_node (ENUMERAL_TYPE); 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; -#if 0 /* This stuff gets cleared in finish_enum anyway. */ - if (TYPE_VALUES (enumtype) != NULL_TREE) - /* Completely replace its old definition. - The old enumerators remain defined, however. */ - TYPE_VALUES (enumtype) = NULL_TREE; - - /* Initially, set up this enum as like `int' - so that we can create the enumerators' declarations and values. - Later on, the precision of the type may be changed and - it may be laid out again. */ - - TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); - TYPE_SIZE (enumtype) = NULL_TREE; - fixup_signed_type (enumtype); -#endif + current_local_enum = NULL_TREE; - /* We copy this value because enumerated type constants - are really of the type of the enumerator, not integer_type_node. */ - enum_next_value = copy_node (integer_zero_node); + /* We don't copy this value because build_enumerator needs to do it. */ + enum_next_value = integer_zero_node; enum_overflow = 0; GNU_xref_decl (current_function_decl, enumtype); @@ -10851,36 +11711,52 @@ tree finish_enum (enumtype, values) register tree enumtype, values; { - register tree minnode, maxnode; + register tree minnode = NULL_TREE, maxnode = NULL_TREE; /* Calculate the maximum value of any enumerator in this type. */ if (values) { register tree pair; register tree value = DECL_INITIAL (TREE_VALUE (values)); - - /* Speed up the main loop by performing some precalculations */ - TREE_TYPE (TREE_VALUE (values)) = enumtype; - TREE_TYPE (value) = enumtype; + + 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; - minnode = maxnode = value; for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair)) { value = DECL_INITIAL (TREE_VALUE (pair)); - TREE_TYPE (TREE_VALUE (pair)) = enumtype; - TREE_TYPE (value) = enumtype; + if (! processing_template_decl) + { + TREE_TYPE (TREE_VALUE (pair)) = enumtype; + TREE_TYPE (value) = enumtype; + if (tree_int_cst_lt (maxnode, value)) + maxnode = value; + else if (tree_int_cst_lt (value, minnode)) + minnode = value; + } TREE_VALUE (pair) = value; - if (tree_int_cst_lt (maxnode, value)) - maxnode = value; - else if (tree_int_cst_lt (value, minnode)) - minnode = value; } } else maxnode = minnode = integer_zero_node; - TYPE_VALUES (enumtype) = values; + TYPE_VALUES (enumtype) = nreverse (values); + + if (processing_template_decl) + { + if (current_function_decl) + { + add_tree (build_min (TAG_DEFN, enumtype)); + resume_temporary_allocation (); + } + return enumtype; + } { int unsignedp = tree_int_cst_sgn (minnode) >= 0; @@ -10898,7 +11774,7 @@ finish_enum (enumtype, values) else fixup_signed_type (enumtype); - if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node)) + 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)); @@ -10909,9 +11785,6 @@ finish_enum (enumtype, values) layout_type (enumtype); } - if (flag_cadillac) - cadillac_finish_enum (enumtype); - { register tree tem; @@ -10923,6 +11796,7 @@ finish_enum (enumtype, values) 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); @@ -10931,12 +11805,7 @@ finish_enum (enumtype, values) } /* Finish debugging output for this type. */ -#if 0 - /* @@ Do we ever generate generate ENUMERAL_TYPE nodes for which debugging - information should *not* be generated? I think not. */ - if (! DECL_IGNORED_P (TYPE_NAME (enumtype))) -#endif - rest_of_type_compilation (enumtype, global_bindings_p ()); + rest_of_type_compilation (enumtype, namespace_bindings_p ()); return enumtype; } @@ -10951,61 +11820,51 @@ build_enumerator (name, value) tree name, value; { tree decl, result; - /* Change this to zero if we find VALUE is not shareable. */ - int shareable = 1; - - /* Remove no-op casts from the value. */ - if (value) - STRIP_TYPE_NOPS (value); - - /* Validate and default VALUE. */ - if (value != NULL_TREE) - { - if (TREE_READONLY_DECL_P (value)) - { - value = decl_constant_value (value); - shareable = 0; - } - - if (TREE_CODE (value) == INTEGER_CST) - { - value = default_conversion (value); - constant_expression_warning (value); - } - else - { - cp_error ("enumerator value for `%D' not integer constant", name); - value = NULL_TREE; - } - } - - /* The order of things is reversed here so that we - can check for possible sharing of enum values, - to keep that from happening. */ - /* Default based on previous value. */ - if (value == NULL_TREE) - { - value = enum_next_value; - if (enum_overflow) - cp_error ("overflow in enumeration values at `%D'", name); - } /* Remove no-op casts from the value. */ if (value) STRIP_TYPE_NOPS (value); - /* Make up for hacks in lex.c. */ - if (value == integer_zero_node) - value = build_int_2 (0, 0); - else if (value == integer_one_node) - value = build_int_2 (1, 0); - else if (TREE_CODE (value) == INTEGER_CST - && (shareable == 0 - || TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE)) - { - value = copy_node (value); - TREE_TYPE (value) = integer_type_node; - } + if (! processing_template_decl) + { + /* Validate and default VALUE. */ + if (value != NULL_TREE) + { + if (TREE_READONLY_DECL_P (value)) + value = decl_constant_value (value); + + if (TREE_CODE (value) == INTEGER_CST) + { + value = default_conversion (value); + constant_expression_warning (value); + } + else + { + cp_error ("enumerator value for `%D' not integer constant", name); + value = NULL_TREE; + } + } + + /* Default based on previous value. */ + if (value == NULL_TREE && ! processing_template_decl) + { + value = enum_next_value; + if (enum_overflow) + cp_error ("overflow in enumeration values at `%D'", name); + } + + /* 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. */ @@ -11027,26 +11886,27 @@ build_enumerator (name, value) 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; pushdecl (decl); GNU_xref_decl (current_function_decl, decl); } - /* Set basis for default for next value. */ - enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value, - integer_one_node, PLUS_EXPR); - enum_overflow = tree_int_cst_lt (enum_next_value, value); - - if (enum_next_value == integer_one_node) - enum_next_value = copy_node (enum_next_value); + if (! processing_template_decl) + { + /* Set basis for default for next value. */ + enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value, + integer_one_node, PLUS_EXPR); + enum_overflow = tree_int_cst_lt (enum_next_value, value); + } result = saveable_tree_cons (name, decl, NULL_TREE); return result; } tree -grok_enum_decls (type, decl) - tree type, decl; +grok_enum_decls (decl) + tree decl; { tree d = current_local_enum; @@ -11055,7 +11915,6 @@ grok_enum_decls (type, decl) while (1) { - TREE_TYPE (d) = type; if (TREE_CHAIN (d) == NULL_TREE) { TREE_CHAIN (d) = decl; @@ -11070,6 +11929,8 @@ grok_enum_decls (type, decl) return decl; } +static int function_depth; + /* Create the FUNCTION_DECL for a function definition. DECLSPECS and DECLARATOR are the parts of the declaration; they describe the function's name and the type it returns, @@ -11092,11 +11953,11 @@ grok_enum_decls (type, decl) @@ something we had previously. */ int -start_function (declspecs, declarator, raises, attrs, pre_parsed_p) - tree declspecs, declarator, raises, attrs; +start_function (declspecs, declarator, attrs, pre_parsed_p) + tree declspecs, declarator, attrs; int pre_parsed_p; { - tree decl1, olddecl; + tree decl1; tree ctype = NULL_TREE; tree fntype; tree restype; @@ -11105,10 +11966,10 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) int doing_friend = 0; /* Sanity check. */ - my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 160); + my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160); my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161); - /* Assume, until we see it does. */ + /* Assume, until we see it does. */ current_function_returns_value = 0; current_function_returns_null = 0; warn_about_return_type = 0; @@ -11118,17 +11979,15 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) current_function_just_assigned_this = 0; current_function_parms_stored = 0; original_result_rtx = NULL_RTX; - current_function_obstack_index = 0; - current_function_obstack_usage = 0; base_init_expr = NULL_TREE; - protect_list = NULL_TREE; current_base_init_list = NULL_TREE; current_member_init_list = NULL_TREE; ctor_label = dtor_label = NULL_TREE; + static_labelno = 0; clear_temp_name (); - /* This should only be done once on the top most decl. */ + /* This should only be done once on the top most decl. */ if (have_extern_spec && !used_extern_spec) { declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs); @@ -11139,31 +11998,25 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) { decl1 = declarator; +#if 0 + /* What was this testing for, exactly? */ if (! DECL_ARGUMENTS (decl1) && !DECL_STATIC_FUNCTION_P (decl1) - && DECL_CONTEXT (decl1) - && DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl1))) - && IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl1))))) + && !DECL_ARTIFICIAL (decl1) + && DECL_CLASS_SCOPE_P (decl1) + && TYPE_IDENTIFIER (DECL_CONTEXT (decl1)) + && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1)))) { + tree binding = binding_for_name (DECL_NAME (decl1), + current_namespace); cp_error ("redeclaration of `%#D'", decl1); if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1))) cp_error_at ("previous declaration here", IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1))); - else if (IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1))) - cp_error_at ("previous declaration here", IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1))); - } - - /* This can happen if a template class is instantiated as part of the - specialization of a member function which is defined in the class - template. We should just use the specialization, but for now give an - error. */ - if (DECL_INITIAL (decl1) != NULL_TREE) - { - cp_error_at ("specialization of `%#D' not supported", decl1); - cp_error ("when defined in the class template body", decl1); + else if (BINDING_VALUE (binding)) + cp_error_at ("previous declaration here", BINDING_VALUE (binding)); } +#endif - last_function_parms = DECL_ARGUMENTS (decl1); - last_function_parm_tags = NULL_TREE; fntype = TREE_TYPE (decl1); if (TREE_CODE (fntype) == METHOD_TYPE) ctype = TYPE_METHOD_BASETYPE (fntype); @@ -11184,23 +12037,23 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) doing_friend = 1; } - raises = TYPE_RAISES_EXCEPTIONS (fntype); - /* In a fcn definition, arg types must be complete. */ - require_complete_types_for_parms (last_function_parms); + 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 = last_function_parms; + 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; } else { - decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises, - NULL_TREE); + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE); /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0; @@ -11212,7 +12065,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) && ! CLASSTYPE_GOT_SEMICOLON (restype)) { cp_error ("semicolon missing after declaration of `%#T'", restype); - shadow_tag (build_tree_list (NULL_TREE, restype)); + shadow_tag (build_expr_list (NULL_TREE, restype)); CLASSTYPE_GOT_SEMICOLON (restype) = 1; if (TREE_CODE (fntype) == FUNCTION_TYPE) fntype = build_function_type (integer_type_node, @@ -11226,15 +12079,13 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) if (TREE_CODE (fntype) == METHOD_TYPE) ctype = TYPE_METHOD_BASETYPE (fntype); - else if (IDENTIFIER_LENGTH (DECL_NAME (decl1)) == 4 - && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (decl1)), "main") - && DECL_CONTEXT (decl1) == NULL_TREE) + else if (DECL_MAIN_P (decl1)) { /* If this doesn't return integer_type, complain. */ if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) { if (pedantic || warn_return_type) - pedwarn ("return type for `main' changed to integer type"); + pedwarn ("return type for `main' changed to `int'"); TREE_TYPE (decl1) = fntype = default_function_type; } warn_about_return_type = 0; @@ -11248,53 +12099,57 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))); 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; - if (flag_cadillac) - cadillac_start_function (decl1); - else - announce_function (decl1); + announce_function (decl1); - if (TYPE_SIZE (TREE_TYPE (fntype)) == NULL_TREE) + if (! processing_template_decl) { - if (IS_AGGR_TYPE (TREE_TYPE (fntype))) - error_with_aggr_type (TREE_TYPE (fntype), - "return-type `%s' is an incomplete type"); - else - error ("return-type is an incomplete type"); - - /* Make it return void instead, but don't change the - type of the DECL_RESULT, in case we have a named return value. */ - if (ctype) - TREE_TYPE (decl1) - = build_cplus_method_type (build_type_variant (ctype, - TREE_READONLY (decl1), - TREE_SIDE_EFFECTS (decl1)), - void_type_node, - FUNCTION_ARG_CHAIN (decl1)); - else - TREE_TYPE (decl1) - = build_function_type (void_type_node, - 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)); - } + if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE) + { + cp_error ("return-type `%#T' is an incomplete type", + TREE_TYPE (fntype)); + + /* Make it return void instead, but don't change the + type of the DECL_RESULT, in case we have a named return value. */ + if (ctype) + TREE_TYPE (decl1) + = build_cplus_method_type (build_type_variant (ctype, + TREE_READONLY (decl1), + TREE_SIDE_EFFECTS (decl1)), + void_type_node, + FUNCTION_ARG_CHAIN (decl1)); + else + TREE_TYPE (decl1) + = build_function_type (void_type_node, + 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)); + } - if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype)) - && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype))) - abstract_virtuals_error (decl1, TREE_TYPE (fntype)); + if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype)) + && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype))) + abstract_virtuals_error (decl1, TREE_TYPE (fntype)); + } if (warn_about_return_type) - warning ("return-type defaults to `int'"); + 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] + && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE) + cp_warning ("`operator=' should return a reference to `*this'"); /* Make the init_value nonzero so pushdecl knows this is not tentative. error_mark_node is replaced below (in poplevel) with the BLOCK. */ DECL_INITIAL (decl1) = error_mark_node; - /* Didn't get anything from C. */ - olddecl = NULL_TREE; - /* This function exists in static storage. (This does not mean `static' in the C sense!) */ TREE_STATIC (decl1) = 1; @@ -11303,26 +12158,51 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) If we already have a decl for this name, and it is a FUNCTION_DECL, use the old decl. */ - if (pre_parsed_p == 0) - { - current_function_decl = decl1 = pushdecl (decl1); + if (processing_template_decl) + decl1 = push_template_decl (decl1); + else if (pre_parsed_p == 0) + { + /* A specialization is not used to guide overload resolution. */ + if ((flag_guiding_decls + || !DECL_TEMPLATE_SPECIALIZATION (decl1)) + && ! DECL_FUNCTION_MEMBER_P (decl1)) + decl1 = pushdecl (decl1); + else + { + /* We need to set the DECL_CONTEXT. */ + if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1)) + DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1)); + /* And make sure we have enough default args. */ + check_default_args (decl1); + } DECL_MAIN_VARIANT (decl1) = decl1; fntype = TREE_TYPE (decl1); } - else - current_function_decl = decl1; + + current_function_decl = decl1; if (DECL_INTERFACE_KNOWN (decl1)) { + tree ctx = hack_decl_function_context (decl1); + if (DECL_NOT_REALLY_EXTERN (decl1)) DECL_EXTERNAL (decl1) = 0; + + if (ctx != NULL_TREE && DECL_THIS_INLINE (ctx) + && TREE_PUBLIC (ctx)) + /* This is a function in a local class in an extern inline + function. */ + comdat_linkage (decl1); } /* 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. */ - else if (interface_unknown == 0) + else if (interface_unknown == 0 + && (! DECL_TEMPLATE_INSTANTIATION (decl1) + || flag_alt_external_templates)) { - if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) + if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1) + || processing_template_decl) DECL_EXTERNAL (decl1) = (interface_only || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines)); @@ -11337,14 +12217,13 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) So clear DECL_EXTERNAL. */ DECL_EXTERNAL (decl1) = 0; - if (DECL_THIS_INLINE (decl1) && ! DECL_INTERFACE_KNOWN (decl1)) + if ((DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) + && ! DECL_INTERFACE_KNOWN (decl1) + /* Don't try to defer nested functions for now. */ + && ! hack_decl_function_context (decl1)) DECL_DEFER_OUTPUT (decl1) = 1; else - { - DECL_INTERFACE_KNOWN (decl1) = 1; - if (DECL_C_STATIC (decl1)) - TREE_PUBLIC (decl1) = 0; - } + DECL_INTERFACE_KNOWN (decl1) = 1; } if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)) @@ -11353,8 +12232,8 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) TREE_TYPE (decl1) = fntype = build_function_type (TREE_TYPE (fntype), TREE_CHAIN (TYPE_ARG_TYPES (fntype))); - last_function_parms = TREE_CHAIN (last_function_parms); - DECL_ARGUMENTS (decl1) = last_function_parms; + current_function_parms = TREE_CHAIN (current_function_parms); + DECL_ARGUMENTS (decl1) = current_function_parms; ctype = NULL_TREE; } restype = TREE_TYPE (fntype); @@ -11364,15 +12243,15 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) push_nested_class (ctype, 1); /* If we're compiling a friend function, neither of the variables - current_class_decl nor current_class_type will have values. */ + current_class_ptr nor current_class_type will have values. */ if (! doing_friend) { /* We know that this was set up by `grokclassfn'. We do not wait until `store_parm_decls', since evil parse errors may never get us to that point. Here we keep the consistency between `current_class_type' - and `current_class_decl'. */ - tree t = last_function_parms; + and `current_class_ptr'. */ + tree t = current_function_parms; my_friendly_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL, 162); @@ -11382,14 +12261,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) int i = suspend_momentary (); /* Fool build_indirect_ref. */ - current_class_decl = NULL_TREE; - C_C_D = build_indirect_ref (t, NULL_PTR); - current_class_decl = t; + current_class_ptr = NULL_TREE; + current_class_ref = build_indirect_ref (t, NULL_PTR); + current_class_ptr = t; resume_momentary (i); } else /* We're having a signature pointer here. */ - C_C_D = current_class_decl = t; + current_class_ref = current_class_ptr = t; } } @@ -11399,40 +12278,27 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) push_nested_class (DECL_CONTEXT (decl1), 2); else push_memoized_context (0, 1); - current_class_decl = C_C_D = NULL_TREE; + current_class_ptr = current_class_ref = NULL_TREE; } pushlevel (0); current_binding_level->parm_flag = 1; - /* 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; - GNU_xref_function (decl1, current_function_parms); if (attrs) cplus_decl_attributes (decl1, NULL_TREE, attrs); make_function_rtl (decl1); - /* Allocate further tree nodes temporarily during compilation - of this function only. Tiemann moved up here from bottom of fn. */ - temporary_allocation (); - /* Promote the value to int before returning it. */ if (C_PROMOTING_INTEGER_TYPE_P (restype)) - { - /* It retains unsignedness if traditional or if it isn't - really getting wider. */ - if (TREE_UNSIGNED (restype) - && (flag_traditional - || TYPE_PRECISION (restype) - == TYPE_PRECISION (integer_type_node))) - restype = unsigned_type_node; - else - restype = integer_type_node; - } + restype = type_promotes_to (restype); + + /* If this fcn was already referenced via a block-scope `extern' decl + (or an implicit decl), propagate certain information about the usage. */ + if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1))) + TREE_ADDRESSABLE (decl1) = 1; + if (DECL_RESULT (decl1) == NULL_TREE) { DECL_RESULT (decl1) @@ -11441,6 +12307,22 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype); } + /* Allocate further tree nodes temporarily during compilation + of this function only. Tiemann moved up here from bottom of fn. */ + /* If this is a nested function, then we must continue to allocate RTL + on the permanent obstack in case we need to inline it later. */ + if (! hack_decl_function_context (decl1)) + temporary_allocation (); + + if (processing_template_decl) + { + ++minimal_parse_mode; + last_tree = DECL_SAVED_TREE (decl1) + = build_nt (EXPR_STMT, void_zero_node); + } + + ++function_depth; + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1)) && DECL_LANGUAGE (decl1) == lang_cplusplus) { @@ -11454,36 +12336,18 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p) ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); } - /* If this fcn was already referenced via a block-scope `extern' decl - (or an implicit decl), propagate certain information about the usage. */ - if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1))) - TREE_ADDRESSABLE (decl1) = 1; - return 1; } +/* Called after store_parm_decls for a function-try-block. We need to update + last_parm_cleanup_insn so that the base initializers for a constructor + are run within this block, not before it. */ + void expand_start_early_try_stmts () { - rtx insns; - start_sequence (); expand_start_try_stmts (); - insns = get_insns (); - end_sequence (); - store_in_parms (insns); -} - -void -store_in_parms (insns) - rtx insns; -{ - rtx last_parm_insn; - - last_parm_insn = get_first_nonparm_insn (); - if (last_parm_insn == NULL_RTX) - emit_insns (insns); - else - emit_insns_before (insns, previous_insn (last_parm_insn)); + last_parm_cleanup_insn = get_last_insn (); } /* Store the parameter declarations into the current function declaration. @@ -11498,6 +12362,7 @@ store_parm_decls () register tree fndecl = current_function_decl; register tree parm; int parms_have_cleanups = 0; + tree cleanups = NULL_TREE; /* This is either a chain of PARM_DECLs (when a prototype is used). */ tree specparms = current_function_parms; @@ -11534,22 +12399,18 @@ store_parm_decls () /* Must clear this because it might contain TYPE_DECLs declared at class level. */ storedecls (NULL_TREE); + for (parm = nreverse (specparms); parm; parm = next) { next = TREE_CHAIN (parm); if (TREE_CODE (parm) == PARM_DECL) { - tree cleanup = maybe_build_cleanup (parm); + tree cleanup; if (DECL_NAME (parm) == NULL_TREE) { -#if 0 - cp_error_at ("parameter name omitted", parm); -#else - /* for C++, this is not an error. */ pushdecl (parm); -#endif } - else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node) + else if (TREE_CODE (TREE_TYPE (parm)) == VOID_TYPE) cp_error ("parameter `%D' declared void", parm); else { @@ -11572,13 +12433,14 @@ store_parm_decls () pushdecl (parm); } - if (cleanup) + if (! processing_template_decl + && (cleanup = maybe_build_cleanup (parm), cleanup)) { expand_decl (parm); - if (! cp_expand_decl_cleanup (parm, cleanup)) - cp_error ("parser lost in parsing declaration of `%D'", - parm); parms_have_cleanups = 1; + + /* Keep track of the cleanups. */ + cleanups = tree_cons (parm, cleanup, cleanups); } } else @@ -11609,7 +12471,29 @@ store_parm_decls () /* Initialize the RTL code for the function. */ DECL_SAVED_INSNS (fndecl) = NULL_RTX; - expand_function_start (fndecl, parms_have_cleanups); + if (! processing_template_decl) + expand_function_start (fndecl, parms_have_cleanups); + + current_function_parms_stored = 1; + + /* If this function is `main', emit a call to `__main' + to run global initializers, etc. */ + if (DECL_MAIN_P (fndecl)) + expand_main_function (); + + /* Now that we have initialized the parms, we can start their + cleanups. We cannot do this before, since expand_decl_cleanup + should not be called before the parm can be used. */ + if (cleanups + && ! processing_template_decl) + { + for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups)) + { + if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), TREE_VALUE (cleanups))) + cp_error ("parser lost in parsing declaration of `%D'", + TREE_PURPOSE (cleanups)); + } + } /* Create a binding contour which can be used to catch cleanup-generated temporaries. Also, if the return value needs or @@ -11620,57 +12504,20 @@ store_parm_decls () expand_start_bindings (0); } - current_function_parms_stored = 1; - - if (flag_gc) - { - maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node); - if (! cp_expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup)) - cp_error ("parser lost in parsing declaration of `%D'", fndecl); - } - - /* If this function is `main', emit a call to `__main' - to run global initializers, etc. */ - if (DECL_NAME (fndecl) - && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4 - && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0 - && DECL_CONTEXT (fndecl) == NULL_TREE) - { - expand_main_function (); - - if (flag_gc) - expand_expr (build_function_call (lookup_name (get_identifier ("__gc_main"), 0), NULL_TREE), - 0, VOIDmode, 0); -#if 0 - /* done at a different time */ - if (flag_rtti) - output_builtin_tdesc_entries (); -#endif - } - - /* Take care of exception handling things. */ - if (flag_handle_exceptions) + if (! processing_template_decl && flag_exceptions) { - rtx insns; - start_sequence (); - - /* Mark the start of a stack unwinder if we need one. */ - start_eh_unwinder (); - /* Do the starting of the exception specifications, if we have any. */ if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) expand_start_eh_spec (); - - insns = get_insns (); - end_sequence (); - - if (insns) - store_in_parms (insns); } + + last_parm_cleanup_insn = get_last_insn (); + last_dtor_insn = get_last_insn (); } /* Bind a name and initialization to the return value of the current function. */ + void store_return_init (return_id, init) tree return_id, init; @@ -11691,8 +12538,7 @@ store_return_init (return_id, init) DECL_ASSEMBLER_NAME (decl) = return_id; } else - error ("return identifier `%s' already in place", - IDENTIFIER_POINTER (DECL_NAME (decl))); + cp_error ("return identifier `%D' already in place", decl); } /* Can't let this happen for constructors. */ @@ -11716,7 +12562,12 @@ store_return_init (return_id, init) /* Let `cp_finish_decl' know that this initializer is ok. */ DECL_INITIAL (decl) = init; pushdecl (decl); - cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); + + if (minimal_parse_mode) + add_tree (build_min_nt (RETURN_INIT, return_id, + copy_to_permanent (init))); + else + cp_finish_decl (decl, init, NULL_TREE, 0, 0); } } @@ -11731,7 +12582,10 @@ store_return_init (return_id, init) 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. */ + constructors. + + 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) @@ -11751,6 +12605,9 @@ finish_function (lineno, call_poplevel, nested) if (fndecl == NULL_TREE) return; + if (! nested && function_depth > 1) + nested = 1; + fntype = TREE_TYPE (fndecl); /* TREE_READONLY (fndecl) = 1; @@ -11764,382 +12621,391 @@ finish_function (lineno, call_poplevel, nested) store_parm_decls (); } - if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/) + if (processing_template_decl) { - tree ttype = target_type (fntype); - tree parmdecl; - - if (IS_AGGR_TYPE (ttype)) - /* Let debugger know it should output info for this type. */ - note_debug_info_needed (ttype); - - for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl)) + if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 0, 0); + } + } + else + { + if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/) { - ttype = target_type (TREE_TYPE (parmdecl)); + tree ttype = target_type (fntype); + tree parmdecl; + if (IS_AGGR_TYPE (ttype)) /* Let debugger know it should output info for this type. */ note_debug_info_needed (ttype); - } - } - /* Clean house because we will need to reorder insns here. */ - do_pending_stack_adjust (); + for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl)) + { + ttype = target_type (TREE_TYPE (parmdecl)); + if (IS_AGGR_TYPE (ttype)) + /* Let debugger know it should output info for this type. */ + note_debug_info_needed (ttype); + } + } - if (dtor_label) - { - tree binfo = TYPE_BINFO (current_class_type); - tree cond = integer_one_node; - tree exprstmt, vfields; - tree in_charge_node = lookup_name (in_charge_identifier, 0); - tree virtual_size; - int ok_to_optimize_dtor = 0; + /* Clean house because we will need to reorder insns here. */ + do_pending_stack_adjust (); - if (current_function_assigns_this) - cond = build (NE_EXPR, boolean_type_node, - current_class_decl, integer_zero_node); - else + if (dtor_label) { - int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); + tree binfo = TYPE_BINFO (current_class_type); + tree cond = integer_one_node; + tree exprstmt; + tree in_charge_node = lookup_name (in_charge_identifier, 0); + tree virtual_size; + int ok_to_optimize_dtor = 0; + int empty_dtor = get_last_insn () == last_dtor_insn; - /* If this destructor is empty, then we don't need to check - whether `this' is NULL in some cases. */ - if ((flag_this_is_variable & 1) == 0) - ok_to_optimize_dtor = 1; - else if (get_last_insn () == get_first_nonparm_insn ()) - ok_to_optimize_dtor - = (n_baseclasses == 0 - || (n_baseclasses == 1 - && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0)))); - } + if (current_function_assigns_this) + cond = build (NE_EXPR, boolean_type_node, + current_class_ptr, integer_zero_node); + else + { + int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); + + /* If this destructor is empty, then we don't need to check + whether `this' is NULL in some cases. */ + if ((flag_this_is_variable & 1) == 0) + ok_to_optimize_dtor = 1; + else if (empty_dtor) + ok_to_optimize_dtor + = (n_baseclasses == 0 + || (n_baseclasses == 1 + && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0)))); + } - /* These initializations might go inline. Protect - the binding level of the parms. */ - pushlevel (0); - expand_start_bindings (0); + /* These initializations might go inline. Protect + the binding level of the parms. */ + pushlevel (0); + expand_start_bindings (0); - if (current_function_assigns_this) - { - current_function_assigns_this = 0; - current_function_just_assigned_this = 0; - } + if (current_function_assigns_this) + { + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + } - /* Generate the code to call destructor on base class. - If this destructor belongs to a class with virtual - functions, then set the virtual function table - pointer to represent the type of our base class. */ + /* Generate the code to call destructor on base class. + If this destructor belongs to a class with virtual + functions, then set the virtual function table + 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. */ - TYPE_HAS_DESTRUCTOR (current_class_type) = 0; + /* This side-effect makes call to `build_delete' generate the + code we have to have at the end of this destructor. */ + TYPE_HAS_DESTRUCTOR (current_class_type) = 0; - /* These are two cases where we cannot delegate deletion. */ - if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) - || TYPE_GETS_REG_DELETE (current_class_type)) - exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node, - LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); - else - exprstmt = build_delete (current_class_type, C_C_D, in_charge_node, - LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); - - /* If we did not assign to this, then `this' is non-zero at - the end of a destructor. As a special optimization, don't - emit test if this is an empty destructor. If it does nothing, - it does nothing. If it calls a base destructor, the base - destructor will perform the test. */ - - if (exprstmt != error_mark_node - && (TREE_CODE (exprstmt) != NOP_EXPR - || TREE_OPERAND (exprstmt, 0) != integer_zero_node - || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))) - { - expand_label (dtor_label); - if (cond != integer_one_node) - expand_start_cond (cond, 0); - if (exprstmt != void_zero_node) - /* Don't call `expand_expr_stmt' if we're not going to do - anything, since -Wall will give a diagnostic. */ - expand_expr_stmt (exprstmt); - - /* Run destructor on all virtual baseclasses. */ - if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) - { - tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type))); - expand_start_cond (build (BIT_AND_EXPR, integer_type_node, - in_charge_node, integer_two_node), 0); - while (vbases) + /* These are two cases where we cannot delegate deletion. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) + || TYPE_GETS_REG_DELETE (current_class_type)) + exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); + else + exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); + + /* If we did not assign to this, then `this' is non-zero at + the end of a destructor. As a special optimization, don't + emit test if this is an empty destructor. If it does nothing, + it does nothing. If it calls a base destructor, the base + destructor will perform the test. */ + + if (exprstmt != error_mark_node + && (TREE_CODE (exprstmt) != NOP_EXPR + || TREE_OPERAND (exprstmt, 0) != integer_zero_node + || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))) + { + expand_label (dtor_label); + if (cond != integer_one_node) + expand_start_cond (cond, 0); + if (exprstmt != void_zero_node) + /* Don't call `expand_expr_stmt' if we're not going to do + anything, since -Wall will give a diagnostic. */ + expand_expr_stmt (exprstmt); + + /* Run destructor on all virtual baseclasses. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) { - if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) + tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type))); + expand_start_cond (build (BIT_AND_EXPR, integer_type_node, + in_charge_node, integer_two_node), 0); + while (vbases) { - tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl); - expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)), - ptr, integer_zero_node, - LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0)); + if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) + { + tree vb = get_vbase + (BINFO_TYPE (vbases), + TYPE_BINFO (current_class_type)); + expand_expr_stmt + (build_scoped_method_call + (current_class_ref, vb, dtor_identifier, + build_expr_list (NULL_TREE, integer_zero_node))); + } + vbases = TREE_CHAIN (vbases); } - vbases = TREE_CHAIN (vbases); + expand_end_cond (); } - expand_end_cond (); + + do_pending_stack_adjust (); + if (cond != integer_one_node) + expand_end_cond (); } - do_pending_stack_adjust (); - if (cond != integer_one_node) - expand_end_cond (); - } + TYPE_HAS_DESTRUCTOR (current_class_type) = 1; - 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. */ - if (TYPE_GETS_REG_DELETE (current_class_type)) - /* This NOP_EXPR means we are in a static call context. */ - exprstmt = - build_method_call - (build_indirect_ref - (build1 (NOP_EXPR, build_pointer_type (current_class_type), - error_mark_node), - NULL_PTR), - ansi_opname[(int) DELETE_EXPR], - tree_cons (NULL_TREE, current_class_decl, - build_tree_list (NULL_TREE, virtual_size)), - NULL_TREE, LOOKUP_NORMAL); - else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) - exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0, - virtual_size); - else - exprstmt = NULL_TREE; + virtual_size = c_sizeof (current_class_type); - if (exprstmt) - { - cond = build (BIT_AND_EXPR, integer_type_node, - in_charge_node, integer_one_node); - expand_start_cond (cond, 0); - expand_expr_stmt (exprstmt); - expand_end_cond (); - } + /* At the end, call delete if that's what's requested. */ - /* End of destructor. */ - expand_end_bindings (NULL_TREE, getdecls() != NULL_TREE, 0); - poplevel (2, 0, 0); /* XXX change to 1 */ + /* FDIS sez: At the point of definition of a virtual destructor + (including an implicit definition), non-placement operator + delete shall be looked up in the scope of the destructor's + class and if found shall be accessible and unambiguous. - /* Back to the top of destructor. */ - /* Dont execute destructor code if `this' is NULL. */ + This is somewhat unclear, but I take it to mean that if the + class only defines placement deletes we don't do anything here. + So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain + for us if they ever try to delete one of these. */ - start_sequence (); + if (TYPE_GETS_REG_DELETE (current_class_type) + || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + exprstmt = build_op_delete_call + (DELETE_EXPR, current_class_ptr, virtual_size, + LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); + else + exprstmt = NULL_TREE; - /* Make all virtual function table pointers in non-virtual base - classes point to CURRENT_CLASS_TYPE's virtual function - tables. */ - expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl); - if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) - expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl, 0); - if (! ok_to_optimize_dtor) - { - cond = build_binary_op (NE_EXPR, - current_class_decl, integer_zero_node, 1); - expand_start_cond (cond, 0); - } + if (exprstmt) + { + cond = build (BIT_AND_EXPR, integer_type_node, + in_charge_node, integer_one_node); + expand_start_cond (cond, 0); + expand_expr_stmt (exprstmt); + expand_end_cond (); + } - insns = get_insns (); - end_sequence (); + /* End of destructor. */ + expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0); + poplevel (2, 0, 0); /* XXX change to 1 */ + + /* Back to the top of destructor. */ + /* Don't execute destructor code if `this' is NULL. */ + + start_sequence (); + + /* If the dtor is empty, and we know there is not possible way we + could use any vtable entries, before they are possibly set by + a base class dtor, we don't have to setup the vtables, as we + know that any base class dtoring will set up any vtables it + needs. We avoid MI, because one base class dtor can do a + virtual dispatch to an overridden function that would need to + have a non-related vtable set up, we cannot avoid setting up + vtables in that case. We could change this to see if there is + just one vtable. */ + if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type)) + { + /* Make all virtual function table pointers in non-virtual base + classes point to CURRENT_CLASS_TYPE's virtual function + tables. */ + expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr); - last_parm_insn = get_first_nonparm_insn (); - if (last_parm_insn == NULL_RTX) - last_parm_insn = get_last_insn (); - else - last_parm_insn = previous_insn (last_parm_insn); + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr); + } + + if (! ok_to_optimize_dtor) + { + cond = build_binary_op (NE_EXPR, + current_class_ptr, integer_zero_node, 1); + expand_start_cond (cond, 0); + } - emit_insns_after (insns, last_parm_insn); + insns = get_insns (); + end_sequence (); - if (! ok_to_optimize_dtor) - expand_end_cond (); - } - else if (current_function_assigns_this) - { - /* Does not need to call emit_base_init, because - that is done (if needed) just after assignment to this - is seen. */ + last_parm_insn = get_first_nonparm_insn (); + if (last_parm_insn == NULL_RTX) + last_parm_insn = get_last_insn (); + else + last_parm_insn = previous_insn (last_parm_insn); - if (DECL_CONSTRUCTOR_P (current_function_decl)) - { - end_protect_partials (); - expand_label (ctor_label); - ctor_label = NULL_TREE; + emit_insns_after (insns, last_parm_insn); - if (call_poplevel) - { - decls = getdecls (); - expand_end_bindings (decls, decls != NULL_TREE, 0); - poplevel (decls != NULL_TREE, 0, 0); - } - c_expand_return (current_class_decl); + if (! ok_to_optimize_dtor) + expand_end_cond (); } - else if (TYPE_MAIN_VARIANT (TREE_TYPE ( - DECL_RESULT (current_function_decl))) != void_type_node - && return_label != NULL_RTX) - no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + else if (current_function_assigns_this) + { + /* Does not need to call emit_base_init, because + that is done (if needed) just after assignment to this + is seen. */ - current_function_assigns_this = 0; - current_function_just_assigned_this = 0; - base_init_expr = NULL_TREE; - } - else if (DECL_CONSTRUCTOR_P (fndecl)) - { - tree allocated_this; - tree cond, thenclause; - /* Allow constructor for a type to get a new instance of the object - using `build_new'. */ - tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type); - CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE; + if (DECL_CONSTRUCTOR_P (current_function_decl)) + { + end_protect_partials (); + expand_label (ctor_label); + ctor_label = NULL_TREE; - DECL_RETURNS_FIRST_ARG (fndecl) = 1; + if (call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 0, 0); + } + /* c_expand_return knows to return 'this' from a constructor. */ + c_expand_return (NULL_TREE); + } + else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE + && return_label != NULL_RTX) + no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - if (flag_this_is_variable > 0) - { - cond = build_binary_op (EQ_EXPR, - current_class_decl, integer_zero_node, 1); - thenclause = build_modify_expr (current_class_decl, NOP_EXPR, - build_new (NULL_TREE, current_class_type, void_type_node, 0)); + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + base_init_expr = NULL_TREE; } + else if (DECL_CONSTRUCTOR_P (fndecl)) + { + tree cond = NULL_TREE, thenclause = NULL_TREE; + /* Allow constructor for a type to get a new instance of the object + using `build_new'. */ + tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type); + CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE; - CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; + DECL_RETURNS_FIRST_ARG (fndecl) = 1; - start_sequence (); + if (flag_this_is_variable > 0) + { + cond = build_binary_op (EQ_EXPR, + current_class_ptr, integer_zero_node, 1); + thenclause = build_modify_expr (current_class_ptr, NOP_EXPR, + build_new (NULL_TREE, current_class_type, void_type_node, 0)); + } - if (flag_this_is_variable > 0) - { - expand_start_cond (cond, 0); - expand_expr_stmt (thenclause); - expand_end_cond (); - } + CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; -#if 0 - if (DECL_NAME (fndecl) == NULL_TREE - && TREE_CHAIN (DECL_ARGUMENTS (fndecl)) != NULL_TREE) - build_default_constructor (fndecl); -#endif + start_sequence (); - /* Emit insns from `emit_base_init' which sets up virtual - function table pointer(s). */ - if (base_init_expr) - { - expand_expr_stmt (base_init_expr); - base_init_expr = NULL_TREE; - } + if (flag_this_is_variable > 0) + { + expand_start_cond (cond, 0); + expand_expr_stmt (thenclause); + expand_end_cond (); + } - insns = get_insns (); - end_sequence (); + /* Emit insns from `emit_base_init' which sets up virtual + function table pointer(s). */ + if (base_init_expr) + { + expand_expr_stmt (base_init_expr); + base_init_expr = NULL_TREE; + } - /* This is where the body of the constructor begins. - If there were no insns in this function body, then the - last_parm_insn is also the last insn. + insns = get_insns (); + end_sequence (); - If optimization is enabled, last_parm_insn may move, so - we don't hold on to it (across emit_base_init). */ - last_parm_insn = get_first_nonparm_insn (); - if (last_parm_insn == NULL_RTX) - last_parm_insn = get_last_insn (); - else - last_parm_insn = previous_insn (last_parm_insn); + /* This is where the body of the constructor begins. */ - emit_insns_after (insns, last_parm_insn); + emit_insns_after (insns, last_parm_cleanup_insn); - end_protect_partials (); + end_protect_partials (); - /* This is where the body of the constructor ends. */ - expand_label (ctor_label); - ctor_label = NULL_TREE; + /* This is where the body of the constructor ends. */ + expand_label (ctor_label); + ctor_label = NULL_TREE; - if (call_poplevel) - { - decls = getdecls (); - expand_end_bindings (decls, decls != NULL_TREE, 0); - poplevel (decls != NULL_TREE, 1, 0); - } + if (call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 1, 0); + } - c_expand_return (current_class_decl); + /* c_expand_return knows to return 'this' from a constructor. */ + c_expand_return (NULL_TREE); - current_function_assigns_this = 0; - current_function_just_assigned_this = 0; - } - else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4 - && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") - && DECL_CONTEXT (fndecl) == NULL_TREE) - { - /* Make it so that `main' always returns 0 by default. */ + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + } + else if (DECL_MAIN_P (fndecl)) + { + /* Make it so that `main' always returns 0 by default. */ #ifdef VMS - c_expand_return (integer_one_node); + c_expand_return (integer_one_node); #else - c_expand_return (integer_zero_node); + c_expand_return (integer_zero_node); #endif - } - else if (return_label != NULL_RTX - && current_function_return_value == NULL_TREE - && ! DECL_NAME (DECL_RESULT (current_function_decl))) - no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - - if (flag_gc) - expand_gc_prologue_and_epilogue (); + } + else if (return_label != NULL_RTX + && current_function_return_value == NULL_TREE + && ! DECL_NAME (DECL_RESULT (current_function_decl))) + no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - /* If this function is supposed to return a value, ensure that - we do not fall into the cleanups by mistake. The end of our - function will look like this: + if (flag_exceptions) + expand_exception_blocks (); - user code (may have return stmt somewhere) - goto no_return_label - cleanup_label: - cleanups - goto return_label - no_return_label: - NOTE_INSN_FUNCTION_END - return_label: - things for return + /* If this function is supposed to return a value, ensure that + we do not fall into the cleanups by mistake. The end of our + function will look like this: + + user code (may have return stmt somewhere) + goto no_return_label + cleanup_label: + cleanups + goto return_label + no_return_label: + NOTE_INSN_FUNCTION_END + return_label: + things for return + + If the user omits a return stmt in the USER CODE section, we + will have a control path which reaches NOTE_INSN_FUNCTION_END. + Otherwise, we won't. */ + if (no_return_label) + { + DECL_CONTEXT (no_return_label) = fndecl; + DECL_INITIAL (no_return_label) = error_mark_node; + DECL_SOURCE_FILE (no_return_label) = input_filename; + DECL_SOURCE_LINE (no_return_label) = lineno; + expand_goto (no_return_label); + } - If the user omits a return stmt in the USER CODE section, we - will have a control path which reaches NOTE_INSN_FUNCTION_END. - Otherwise, we won't. */ - if (no_return_label) - { - DECL_CONTEXT (no_return_label) = fndecl; - DECL_INITIAL (no_return_label) = error_mark_node; - DECL_SOURCE_FILE (no_return_label) = input_filename; - DECL_SOURCE_LINE (no_return_label) = lineno; - expand_goto (no_return_label); - } + if (cleanup_label) + { + /* Remove the binding contour which is used + to catch cleanup-generated temporaries. */ + expand_end_bindings (0, 0, 0); + poplevel (0, 0, 0); - if (cleanup_label) - { - /* remove the binding contour which is used - to catch cleanup-generated temporaries. */ - expand_end_bindings (0, 0, 0); - poplevel (0, 0, 0); - } + /* Emit label at beginning of cleanup code for parameters. */ + emit_label (cleanup_label); + } - if (cleanup_label) - /* Emit label at beginning of cleanup code for parameters. */ - emit_label (cleanup_label); + /* Get return value into register if that's where it's supposed to be. */ + if (original_result_rtx) + fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx); - /* Get return value into register if that's where it's supposed to be. */ - if (original_result_rtx) - fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx); + /* Finish building code that will trigger warnings if users forget + to make their functions return values. */ + if (no_return_label || cleanup_label) + emit_jump (return_label); + if (no_return_label) + { + /* We don't need to call `expand_*_return' here because we + don't need any cleanups here--this path of code is only + for error checking purposes. */ + expand_label (no_return_label); + } - /* Finish building code that will trigger warnings if users forget - to make their functions return values. */ - if (no_return_label || cleanup_label) - emit_jump (return_label); - if (no_return_label) - { - /* We don't need to call `expand_*_return' here because we - don't need any cleanups here--this path of code is only - for error checking purposes. */ - expand_label (no_return_label); + /* Generate rtl for function exit. */ + expand_function_end (input_filename, lineno, 1); } - /* Generate rtl for function exit. */ - expand_function_end (input_filename, lineno, 1); - - if (flag_handle_exceptions) - expand_exception_blocks (); - /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ @@ -12147,7 +13013,7 @@ finish_function (lineno, call_poplevel, nested) my_friendly_abort (122); poplevel (1, 0, 1); - /* reset scope for C++: if we were in the scope of a class, + /* 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 class members will ever be referenced in this function @@ -12161,79 +13027,115 @@ finish_function (lineno, call_poplevel, nested) pop_memoized_context (1); /* Must mark the RESULT_DECL as being in this function. */ - DECL_CONTEXT (DECL_RESULT (fndecl)) = DECL_INITIAL (fndecl); - - /* Obey `register' declarations if `setjmp' is called in this fn. */ - if (flag_traditional && current_function_calls_setjmp) - setjmp_protect (DECL_INITIAL (fndecl)); + DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point to the FUNCTION_DECL node itself. */ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; - /* So we can tell if jump_optimize sets it to 1. */ - can_reach_end = 0; + if (! processing_template_decl) + { + int saved_flag_keep_inline_functions = + flag_keep_inline_functions; + + /* So we can tell if jump_optimize sets it to 1. */ + can_reach_end = 0; - /* Run the optimizers and output the assembler code for this function. */ - rest_of_compilation (fndecl); + if (DECL_CONTEXT (fndecl) != NULL_TREE + && hack_decl_function_context (fndecl)) + /* Trick rest_of_compilation into not deferring output of this + function, even if it is inline, since the rtl_obstack for + this function is the function_obstack of the enclosing + function and will be deallocated when the enclosing + function is gone. See save_tree_status. */ + flag_keep_inline_functions = 1; - if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) - { - /* Set DECL_EXTERNAL so that assemble_external will be called as - necessary. We'll clear it again in finish_file. */ - if (! DECL_EXTERNAL (fndecl)) - DECL_NOT_REALLY_EXTERN (fndecl) = 1; - DECL_EXTERNAL (fndecl) = 1; - mark_inline_for_output (fndecl); - } + /* Run the optimizers and output the assembler code for this + function. */ + + if (DECL_ARTIFICIAL (fndecl)) + { + /* Do we really *want* to inline this synthesized method? */ - if (ctype && TREE_ASM_WRITTEN (fndecl)) - note_debug_info_needed (ctype); + int save_fif = flag_inline_functions; + flag_inline_functions = 1; - current_function_returns_null |= can_reach_end; + /* Turn off DECL_INLINE for the moment so function_cannot_inline_p + will check our size. */ + DECL_INLINE (fndecl) = 0; - /* Since we don't normally go through c_expand_return for constructors, - this normally gets the wrong value. - Also, named return values have their return codes emitted after - NOTE_INSN_FUNCTION_END, confusing jump.c. */ - if (DECL_CONSTRUCTOR_P (fndecl) - || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE) - current_function_returns_null = 0; + rest_of_compilation (fndecl); + flag_inline_functions = save_fif; + } + else + rest_of_compilation (fndecl); - if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) - cp_warning ("`noreturn' function `%D' does return", fndecl); - else if ((warn_return_type || pedantic) - && current_function_returns_null - && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node) - { - /* If this function returns non-void and control can drop through, - complain. */ - cp_pedwarn ("control reaches end of non-void function `%D'", fndecl); + flag_keep_inline_functions = saved_flag_keep_inline_functions; + + if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) + { + /* Set DECL_EXTERNAL so that assemble_external will be called as + necessary. We'll clear it again in finish_file. */ + if (! DECL_EXTERNAL (fndecl)) + DECL_NOT_REALLY_EXTERN (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 1; + mark_inline_for_output (fndecl); + } + + if (ctype && TREE_ASM_WRITTEN (fndecl)) + note_debug_info_needed (ctype); + + current_function_returns_null |= can_reach_end; + + /* Since we don't normally go through c_expand_return for constructors, + this normally gets the wrong value. + Also, named return values have their return codes emitted after + NOTE_INSN_FUNCTION_END, confusing jump.c. */ + if (DECL_CONSTRUCTOR_P (fndecl) + || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE) + current_function_returns_null = 0; + + if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) + cp_warning ("`noreturn' function `%D' does return", fndecl); + else if ((warn_return_type || pedantic) + && current_function_returns_null + && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE) + { + /* If this function returns non-void and control can drop through, + complain. */ + cp_warning ("control reaches end of non-void function `%D'", fndecl); + } + /* With just -W, complain only if function returns both with + and without a value. */ + else if (extra_warnings + && current_function_returns_value && current_function_returns_null) + warning ("this function may return with or without a value"); } - /* With just -W, complain only if function returns both with - and without a value. */ - else if (extra_warnings - && current_function_returns_value && current_function_returns_null) - warning ("this function may return with or without a value"); + + --function_depth; /* 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); - if (flag_cadillac) - cadillac_finish_function (fndecl); - if (DECL_SAVED_INSNS (fndecl) == NULL_RTX) { + tree t; + /* Stop pointing to the local nodes about to be freed. */ /* But DECL_INITIAL must remain nonzero so we know this was an actual function definition. */ DECL_INITIAL (fndecl) = error_mark_node; - if (! DECL_CONSTRUCTOR_P (fndecl) - || !TYPE_USES_VIRTUAL_BASECLASSES (TYPE_METHOD_BASETYPE (fntype))) - DECL_ARGUMENTS (fndecl) = NULL_TREE; + for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) + DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX; } if (DECL_STATIC_CONSTRUCTOR (fndecl)) @@ -12249,8 +13151,9 @@ finish_function (lineno, call_poplevel, nested) current_function_decl = NULL_TREE; } - named_label_uses = NULL_TREE; - current_class_decl = NULL_TREE; + named_label_uses = NULL; + current_class_ptr = NULL_TREE; + current_class_ref = NULL_TREE; } /* Create the FUNCTION_DECL for a function definition. @@ -12275,11 +13178,12 @@ finish_function (lineno, call_poplevel, nested) DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING CHANGES TO CODE IN `grokfield'. */ + tree -start_method (declspecs, declarator, raises) - tree declarator, declspecs, raises; +start_method (declspecs, declarator) + tree declarator, declspecs; { - tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises, + tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, NULL_TREE); /* Something too ugly to handle. */ @@ -12287,7 +13191,7 @@ start_method (declspecs, declarator, raises) return NULL_TREE; /* Pass friends other than inline friend functions back. */ - if (TYPE_MAIN_VARIANT (fndecl) == void_type_node) + if (fndecl == void_type_node) return fndecl; if (TREE_CODE (fndecl) != FUNCTION_DECL) @@ -12295,17 +13199,14 @@ start_method (declspecs, declarator, raises) return NULL_TREE; if (IS_SIGNATURE (current_class_type)) - { - IS_DEFAULT_IMPLEMENTATION (fndecl) = 1; - /* In case we need this info later. */ - HAS_DEFAULT_IMPLEMENTATION (current_class_type) = 1; - } + IS_DEFAULT_IMPLEMENTATION (fndecl) = 1; if (DECL_IN_AGGR_P (fndecl)) { if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type) { - if (DECL_CONTEXT (fndecl)) + if (DECL_CONTEXT (fndecl) + && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL) cp_error ("`%D' is already defined in class %s", fndecl, TYPE_NAME_STRING (DECL_CONTEXT (fndecl))); } @@ -12317,11 +13218,8 @@ start_method (declspecs, declarator, raises) if (flag_default_inline) DECL_INLINE (fndecl) = 1; - if (processing_template_defn) - { - SET_DECL_IMPLICIT_INSTANTIATION (fndecl); - repo_template_used (fndecl); - } + if (processing_template_decl) + fndecl = push_template_decl (fndecl); /* We read in the parameters on the maybepermanent_obstack, but we won't be getting back to them until after we @@ -12331,14 +13229,6 @@ start_method (declspecs, declarator, raises) if (! DECL_FRIEND_P (fndecl)) { - if (DECL_CHAIN (fndecl) != NULL_TREE) - { - /* Need a fresh node here so that we don't get circularity - when we link these together. If FNDECL was a friend, then - `pushdecl' does the right thing, which is nothing wrt its - current value of DECL_CHAIN. */ - fndecl = copy_node (fndecl); - } if (TREE_CHAIN (fndecl)) { fndecl = copy_node (fndecl); @@ -12385,7 +13275,7 @@ finish_method (decl) register tree link; - if (TYPE_MAIN_VARIANT (decl) == void_type_node) + if (decl == void_type_node) return decl; old_initial = DECL_INITIAL (fndecl); @@ -12418,13 +13308,12 @@ finish_method (decl) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); for (link = current_binding_level->type_shadowed; link; link = TREE_CHAIN (link)) - IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (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, - current_binding_level->keep, - current_binding_level->tag_transparent); + current_binding_level->keep); poplevel (0, 0, 0); @@ -12462,7 +13351,7 @@ hack_incomplete_structures (type) for (list = ¤t_binding_level->incomplete; *list; ) { tree decl = TREE_VALUE (*list); - if (decl && TREE_TYPE (decl) == type + if ((decl && TREE_TYPE (decl) == type) || (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE && TREE_TYPE (TREE_TYPE (decl)) == type)) @@ -12479,7 +13368,7 @@ hack_incomplete_structures (type) expand_decl (decl); cleanup = maybe_build_cleanup (decl); expand_decl_init (decl); - if (! cp_expand_decl_cleanup (decl, cleanup)) + if (! expand_decl_cleanup (decl, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); } @@ -12490,32 +13379,21 @@ hack_incomplete_structures (type) } } -/* Nonzero if presently building a cleanup. Needed because - SAVE_EXPRs are not the right things to use inside of cleanups. - They are only ever evaluated once, where the cleanup - might be evaluated several times. In this case, a later evaluation - of the cleanup might fill in the SAVE_EXPR_RTL, and it will - not be valid for an earlier cleanup. */ - -int building_cleanup; - /* If DECL is of a type which needs a cleanup, build that cleanup here. - We don't build cleanups if just going for syntax checking, since - fixup_cleanups does not know how to not handle them. + See build_delete for information about AUTO_DELETE. Don't build these on the momentary obstack; they must live the life of the binding contour. */ -tree -maybe_build_cleanup (decl) - tree decl; + +static tree +maybe_build_cleanup_1 (decl, auto_delete) + tree decl, auto_delete; { tree type = TREE_TYPE (decl); if (TYPE_NEEDS_DESTRUCTOR (type)) { int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR; tree rval; - int old_building_cleanup = building_cleanup; - building_cleanup = 1; if (TREE_CODE (decl) != PARM_DECL) temp = suspend_momentary (); @@ -12533,22 +13411,40 @@ maybe_build_cleanup (decl) || flag_expensive_optimizations) flags |= LOOKUP_NONVIRTUAL; - rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0); + rval = build_delete (TREE_TYPE (rval), rval, auto_delete, flags, 0); if (TYPE_USES_VIRTUAL_BASECLASSES (type) && ! TYPE_HAS_DESTRUCTOR (type)) - rval = build_compound_expr (tree_cons (NULL_TREE, rval, - build_tree_list (NULL_TREE, build_vbase_delete (type, decl)))); + rval = build_compound_expr (expr_tree_cons (NULL_TREE, rval, + build_expr_list (NULL_TREE, build_vbase_delete (type, decl)))); if (TREE_CODE (decl) != PARM_DECL) resume_momentary (temp); - building_cleanup = old_building_cleanup; - return rval; } return 0; } + +/* If DECL is of a type which needs a cleanup, build that cleanup + here. The cleanup does free the storage with a call to delete. */ + +tree +maybe_build_cleanup_and_delete (decl) + tree decl; +{ + return maybe_build_cleanup_1 (decl, integer_three_node); +} + +/* If DECL is of a type which needs a cleanup, build that cleanup + here. The cleanup does not free the storage with a call a delete. */ + +tree +maybe_build_cleanup (decl) + tree decl; +{ + return maybe_build_cleanup_1 (decl, integer_two_node); +} /* Expand a C++ expression at the statement level. This is needed to ferret out nodes which have UNKNOWN_TYPE. @@ -12556,13 +13452,21 @@ maybe_build_cleanup (decl) expressions are combined with other, type-providing, expressions, leaving only orphan expressions, such as: - &class::bar; / / takes its address, but does nothing with it. + &class::bar; / / takes its address, but does nothing with it. */ - */ void cplus_expand_expr_stmt (exp) tree exp; { + if (processing_template_decl) + { + add_tree (build_min_nt (EXPR_STMT, exp)); + return; + } + + /* Arrange for all temps to disappear. */ + expand_start_target_temps (); + if (TREE_TYPE (exp) == unknown_type_node) { if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST) @@ -12572,8 +13476,6 @@ cplus_expand_expr_stmt (exp) } else { - int remove_implicit_immediately = 0; - if (TREE_CODE (exp) == FUNCTION_DECL) { cp_warning ("reference, not call, to function `%D'", exp); @@ -12585,12 +13487,22 @@ cplus_expand_expr_stmt (exp) libg++ to miscompile, and tString to core dump. */ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp); #endif - expand_expr_stmt (break_out_cleanups (exp)); + + /* 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)); } /* Clean up any pending cleanups. This happens when a function call returns a cleanup-needing value that nobody uses. */ - expand_cleanups_to (NULL_TREE); + expand_end_target_temps (); } /* When a stmt has been parsed, this function is called. @@ -12618,9 +13530,6 @@ finish_stmt () check_base_init (current_class_type); } current_function_assigns_this = 1; - - if (flag_cadillac) - cadillac_finish_stmt (); } /* Change a static member function definition into a FUNCTION_TYPE, instead @@ -12679,18 +13588,20 @@ struct cp_function tree shadowed_labels; tree ctor_label; tree dtor_label; - tree protect_list; + rtx last_dtor_insn; + rtx last_parm_cleanup_insn; tree base_init_list; tree member_init_list; tree base_init_expr; - tree class_decl; - tree C_C_D; + tree current_class_ptr; + tree current_class_ref; rtx result_rtx; struct cp_function *next; struct binding_level *binding_level; + int static_labelno; }; -struct cp_function *cp_function_chain; +static struct cp_function *cp_function_chain; extern int temp_name_counter; @@ -12717,17 +13628,19 @@ push_cp_function_context (context) p->binding_level = current_binding_level; p->ctor_label = ctor_label; p->dtor_label = dtor_label; + p->last_dtor_insn = last_dtor_insn; + p->last_parm_cleanup_insn = last_parm_cleanup_insn; p->assigns_this = current_function_assigns_this; p->just_assigned_this = current_function_just_assigned_this; p->parms_stored = current_function_parms_stored; p->result_rtx = original_result_rtx; p->base_init_expr = base_init_expr; - p->protect_list = protect_list; p->temp_name_counter = temp_name_counter; p->base_init_list = current_base_init_list; p->member_init_list = current_member_init_list; - p->class_decl = current_class_decl; - p->C_C_D = C_C_D; + p->current_class_ptr = current_class_ptr; + p->current_class_ref = current_class_ref; + p->static_labelno = static_labelno; } /* Restore the variables used during compilation of a C++ function. */ @@ -12745,17 +13658,6 @@ pop_cp_function_context (context) SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link)); -#if 0 - if (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 function definition. */ - DECL_INITIAL (current_function_decl) = error_mark_node; - DECL_ARGUMENTS (current_function_decl) = 0; - } -#endif - pop_function_context_from (context); cp_function_chain = p->next; @@ -12768,7 +13670,8 @@ pop_cp_function_context (context) current_binding_level = p->binding_level; ctor_label = p->ctor_label; dtor_label = p->dtor_label; - protect_list = p->protect_list; + last_dtor_insn = p->last_dtor_insn; + last_parm_cleanup_insn = p->last_parm_cleanup_insn; current_function_assigns_this = p->assigns_this; current_function_just_assigned_this = p->just_assigned_this; current_function_parms_stored = p->parms_stored; @@ -12777,102 +13680,15 @@ pop_cp_function_context (context) temp_name_counter = p->temp_name_counter; current_base_init_list = p->base_init_list; current_member_init_list = p->member_init_list; - current_class_decl = p->class_decl; - C_C_D = p->C_C_D; + current_class_ptr = p->current_class_ptr; + current_class_ref = p->current_class_ref; + static_labelno = p->static_labelno; free (p); } -/* FSF LOCAL dje prefix attributes */ -/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two - lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE). - - The head of the declspec list is stored in DECLSPECS. - The head of the attribute list is stored in PREFIX_ATTRIBUTES. - - Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of - the list elements. We drop the containing TREE_LIST nodes and link the - resulting attributes together the way decl_attributes expects them. */ - -void -split_specs_attrs (specs_attrs, declspecs, prefix_attributes) - tree specs_attrs; - tree *declspecs, *prefix_attributes; -{ - tree t, s, a, next, specs, attrs; - - /* This can happen in c++ (eg: decl: typespec initdecls ';'). */ - if (specs_attrs != NULL_TREE - && TREE_CODE (specs_attrs) != TREE_LIST) - { - *declspecs = specs_attrs; - *prefix_attributes = NULL_TREE; - return; - } - - /* Remember to keep the lists in the same order, element-wise. */ - - specs = s = NULL_TREE; - attrs = a = NULL_TREE; - for (t = specs_attrs; t; t = next) - { - next = TREE_CHAIN (t); - /* Declspecs have a non-NULL TREE_VALUE. */ - if (TREE_VALUE (t) != NULL_TREE) - { - if (specs == NULL_TREE) - specs = s = t; - else - { - TREE_CHAIN (s) = t; - s = t; - } - } - else - { - if (attrs == NULL_TREE) - attrs = a = TREE_PURPOSE (t); - else - { - TREE_CHAIN (a) = TREE_PURPOSE (t); - a = TREE_PURPOSE (t); - } - } - } - - /* Terminate the lists. */ - if (s != NULL_TREE) - TREE_CHAIN (s) = NULL_TREE; - if (a != NULL_TREE) - TREE_CHAIN (a) = NULL_TREE; - - /* All done. */ - *declspecs = specs; - *prefix_attributes = attrs; -} - -/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes. - This function is used by the parser when a rule will accept attributes - in a particular position, but we don't want to support that just yet. - - A warning is issued for every ignored attribute. */ - -tree -strip_attrs (specs_attrs) - tree specs_attrs; +int +in_function_p () { - tree specs, attrs; - - split_specs_attrs (specs_attrs, &specs, &attrs); - - while (attrs) - { - warning ("`%s' attribute ignored", - IDENTIFIER_POINTER (TREE_PURPOSE (attrs))); - attrs = TREE_CHAIN (attrs); - } - - return specs; + return function_depth != 0; } -/* END FSF LOCAL */ - diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h index 0824c13..f55dca5 100644 --- a/contrib/gcc/cp/decl.h +++ b/contrib/gcc/cp/decl.h @@ -31,7 +31,7 @@ enum decl_context }; /* We need this in here to get the decl_context definition. */ -extern tree grokdeclarator PROTO((tree, tree, enum decl_context, int, tree, tree)); +extern tree grokdeclarator PROTO((tree, tree, enum decl_context, int, tree)); /* C++: Keep these around to reduce calls to `get_identifier'. Identifiers for `this' in member functions and the auto-delete diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c index 9b7f88e..c87c607 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, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */ line numbers. For example, the CONST_DECLs for enum values. */ #include "config.h" -#include +#include "system.h" #include "tree.h" #include "rtl.h" #include "flags.h" @@ -36,11 +36,33 @@ Boston, MA 02111-1307, USA. */ #include "decl.h" #include "lex.h" #include "output.h" +#include "except.h" +#include "expr.h" #include "defaults.h" +#include "toplev.h" +#include "dwarf2out.h" +#include "dwarfout.h" + +#if USE_CPPLIB +#include "cpplib.h" +extern cpp_reader parse_in; +extern cpp_options parse_options; +static int cpp_initialized; +#endif + +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 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)); -extern tree get_file_function_name (); -extern tree cleanups_this_call; -static void grok_function_init (); +extern int current_class_depth; /* A list of virtual function tables we must make sure to write out. */ tree pending_vtables; @@ -51,7 +73,7 @@ tree pending_vtables; tree pending_statics; /* A list of functions which were declared inline, but which we - may need to emit outline anyway. */ + may need to emit outline anyway. */ static tree saved_inlines; /* Used to help generate temporary names which are unique within @@ -67,9 +89,23 @@ static int global_temp_name_counter; extern int spew_debug; +/* Nonzero if we're done parsing and into end-of-file activities. */ + +int at_eof; + /* Functions called along with real static constructors and destructors. */ tree static_ctors, static_dtors; + +/* The current open namespace, and ::. */ + +tree current_namespace; +tree global_namespace; + +/* The stack for namespaces of current declarations. */ + +static tree decl_namespace_list; + /* C (and C++) language-specific option variables. */ @@ -99,7 +135,8 @@ int flag_no_builtin; int flag_no_nonansi_builtin; -/* Nonzero means do some things the same way PCC does. */ +/* Nonzero means do some things the same way PCC does. Only provided so + the compiler will link. */ int flag_traditional; @@ -122,7 +159,7 @@ int flag_ansi; int flag_implement_inlines = 1; /* Nonzero means do emit exported implementations of templates, instead of - multiple static copies in each file that needs a definition. */ + multiple static copies in each file that needs a definition. */ int flag_external_templates; @@ -140,20 +177,32 @@ int flag_implicit_templates = 1; int warn_implicit = 1; +/* Nonzero means warn about usage of long long when `-pedantic'. */ + +int warn_long_long = 1; + /* Nonzero means warn when all ctors or dtors are private, and the class has no friends. */ int warn_ctor_dtor_privacy = 1; -/* True if we want to implement vtbvales using "thunks". - The default is off now, but will be on later. */ +/* True if we want to implement vtables using "thunks". + The default is off. */ -int flag_vtable_thunks; +#ifndef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 0 +#endif +int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; /* True if we want to deal with repository information. */ int flag_use_repository; +/* Nonzero if we want to issue diagnostics that the standard says are not + required. */ + +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. */ @@ -165,24 +214,10 @@ int warn_write_strings; int warn_cast_qual; -/* Nonzero means warn that dbx info for template class methods isn't fully - supported yet. */ - -int warn_template_debugging; - -/* Warn about traditional constructs whose meanings changed in ANSI C. */ - -int warn_traditional; - /* Nonzero means warn about sizeof(function) or addition/subtraction of function pointers. */ -int warn_pointer_arith; - -/* Nonzero means warn for non-prototype function decls - or non-prototyped defs without previous prototype. */ - -int warn_strict_prototypes; +int warn_pointer_arith = 1; /* Nonzero means warn for any function def without prototype decl. */ @@ -197,7 +232,11 @@ int warn_redundant_decls; int warn_missing_braces; -/* Warn about *printf or *scanf format/argument anomalies. */ +/* Warn about comparison of signed and unsigned values. */ + +int warn_sign_compare; + +/* Warn about *printf or *scanf format/argument anomalies. */ int warn_format; @@ -219,7 +258,7 @@ int warn_parentheses; int warn_overloaded_virtual; /* Non-zero means warn when declaring a class that has a non virtual - destructor, when it really ought to have a virtual one. */ + destructor, when it really ought to have a virtual one. */ int warn_nonvdtor; /* Non-zero means warn when a function is declared extern and later inline. */ @@ -231,8 +270,32 @@ int warn_reorder; /* Non-zero means warn when synthesis behavior differs from Cfront's. */ int warn_synth; -/* Nonzero means `$' can be in an identifier. - See cccp.c for reasons why this breaks some obscure ANSI C programs. */ +/* Non-zero means warn when we convert a pointer to member function + into a pointer to (void or function). */ +int warn_pmf2ptr = 1; + +/* Nonzero means warn about violation of some Effective C++ style rules. */ + +int warn_ecpp; + +/* Nonzero means warn where overload resolution chooses a promotion from + unsigned to signed over a conversion to an unsigned of the same size. */ + +int warn_sign_promo; + +/* Nonzero means warn when an old-style cast is used. */ + +int warn_old_style_cast; + +/* Warn about #pragma directives that are not recognised. */ + +int warn_unknown_pragmas; /* Tri state variable. */ + +/* Nonzero means warn about use of multicharacter literals. */ + +int warn_multichar = 1; + +/* Nonzero means `$' can be in an identifier. */ #ifndef DOLLARS_IN_IDENTIFIERS #define DOLLARS_IN_IDENTIFIERS 1 @@ -284,15 +347,12 @@ int flag_memoize_lookups; int flag_save_memoized_contexts; int write_virtuals; -/* Nonzero means we should attempt to elide constructors when possible. */ +/* 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. */ int flag_elide_constructors; -/* Nonzero means recognize and handle exception handling constructs. - Use ansi syntax and semantics. WORK IN PROGRESS! */ - -int flag_handle_exceptions; - /* Nonzero means recognize and handle signature language constructs. */ int flag_handle_signatures; @@ -307,17 +367,9 @@ int flag_default_inline = 1; 0 means enums can convert to ints, but not vice-versa. */ int flag_int_enum_equivalence; -/* Controls whether compiler is operating under LUCID's Cadillac - system. 1 means yes, 0 means no. */ -int flag_cadillac; - -/* Controls whether compiler generates code to build objects - that can be collected when they become garbage. */ -int flag_gc; - /* Controls whether compiler generates 'type descriptor' that give run-time type information. */ -int flag_rtti; +int flag_rtti = 1; /* Nonzero if we wish to output cross-referencing information for the GNU class browser. */ @@ -336,7 +388,7 @@ extern int flag_gnu_xref; int flag_assume_nonnull_objects = 1; /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) - objects. */ + objects. */ int flag_huge_objects; @@ -369,6 +421,39 @@ int flag_check_new; int flag_new_for_scope = 1; +/* Nonzero if we want to emit defined symbols with common-like linkage as + weak symbols where possible, in order to conform to C++ semantics. + Otherwise, emit them as local symbols. */ + +int flag_weak = 1; + +/* Nonzero to enable experimental ABI changes. */ + +int flag_new_abi; + +/* Nonzero to not ignore namespace std. */ + +int flag_honor_std; + +/* Maximum template instantiation depth. Must be at least 17 for ANSI + compliance. */ + +int max_tinst_depth = 17; + +/* The name-mangling scheme to use. Must be 1 or greater to support + template functions with identical types, but different template + arguments. */ +int name_mangling_version = 2; + +/* Nonzero means that guiding declarations are allowed. */ +int flag_guiding_decls; + +/* Nonzero if squashed mangling is to be performed. + This uses the B and K codes to reference previously seen class types + and class qualifiers. */ +int flag_do_squangling; + + /* Table of language-dependent -f options. STRING is the option name. VARIABLE is the address of the variable. ON_VALUE is the value to store in VARIABLE @@ -384,6 +469,7 @@ 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}, @@ -394,12 +480,12 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"all-virtual", &flag_all_virtual, 1}, {"memoize-lookups", &flag_memoize_lookups, 1}, {"elide-constructors", &flag_elide_constructors, 1}, - {"handle-exceptions", &flag_handle_exceptions, 1}, + {"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}, - {"gc", &flag_gc, 1}, + {"honor-std", &flag_honor_std, 1}, {"rtti", &flag_rtti, 1}, {"xref", &flag_gnu_xref, 1}, {"nonnull-objects", &flag_assume_nonnull_objects, 1}, @@ -409,26 +495,44 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"huge-objects", &flag_huge_objects, 1}, {"conserve-space", &flag_conserve_space, 1}, {"vtable-thunks", &flag_vtable_thunks, 1}, - {"short-temps", &flag_short_temps, 1}, {"access-control", &flag_access_control, 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}, {"repo", &flag_use_repository, 1}, - {"for-scope", &flag_new_for_scope, 2} + {"for-scope", &flag_new_for_scope, 2}, + {"weak", &flag_weak, 1} }; /* Decode the string P as a language-specific option. - Return 1 if it is recognized (and handle it); - return 0 if not recognized. */ + Return the number of strings consumed for a valid option. + Otherwise return 0. */ int -lang_decode_option (p) - char *p; +lang_decode_option (argc, argv) + int argc; + 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_traditional = 1, dollars_in_ident = 1, flag_writable_strings = 1, + 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. */ @@ -451,68 +555,107 @@ lang_decode_option (p) /* Some kind of -f option. P's value is the option sans `-f'. Search for it in the table of options. */ - int found = 0, j; + int found = 0; + size_t j; p += 2; /* Try special -f options. */ + if (!strcmp (p, "handle-exceptions") + || !strcmp (p, "no-handle-exceptions")) + warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)"); + if (!strcmp (p, "save-memoized")) { flag_memoize_lookups = 1; flag_save_memoized_contexts = 1; found = 1; } - if (!strcmp (p, "no-save-memoized")) + else if (!strcmp (p, "no-save-memoized")) { flag_memoize_lookups = 0; flag_save_memoized_contexts = 0; found = 1; } - else if (! strncmp (p, "cadillac", 8)) + else if (! strcmp (p, "alt-external-templates")) { - flag_cadillac = atoi (p+9); + flag_external_templates = 1; + flag_alt_external_templates = 1; found = 1; } - else if (! strncmp (p, "no-cadillac", 11)) + else if (! strcmp (p, "no-alt-external-templates")) { - flag_cadillac = 0; + flag_alt_external_templates = 0; found = 1; } - else if (! strcmp (p, "gc")) + else if (!strcmp (p, "repo")) { - flag_gc = 1; - /* This must come along for the ride. */ - flag_rtti = 1; + flag_use_repository = 1; + flag_implicit_templates = 0; found = 1; } - else if (! strcmp (p, "no-gc")) + else if (!strcmp (p, "guiding-decls")) { - flag_gc = 0; - /* This must come along for the ride. */ - flag_rtti = 0; + flag_guiding_decls = 1; + name_mangling_version = 0; found = 1; } - else if (! strcmp (p, "alt-external-templates")) + else if (!strcmp (p, "no-guiding-decls")) { - flag_external_templates = 1; - flag_alt_external_templates = 1; + flag_guiding_decls = 0; found = 1; } - else if (! strcmp (p, "no-alt-external-templates")) + else if (!strcmp (p, "ansi-overloading")) + found = 1; + else if (!strcmp (p, "no-ansi-overloading")) { - flag_alt_external_templates = 0; + error ("-fno-ansi-overloading is no longer supported"); found = 1; } - else if (!strcmp (p, "ansi-overloading")) + else if (!strcmp (p, "new-abi")) { - warning ("-fansi-overloading is no longer meaningful"); - found = 1; + flag_new_abi = 1; + flag_do_squangling = 1; + flag_honor_std = 1; + flag_vtable_thunks = 1; } - else if (!strcmp (p, "repo")) + else if (!strcmp (p, "no-new-abi")) { - flag_use_repository = 1; - flag_implicit_templates = 0; - found = 1; + flag_new_abi = 0; + flag_do_squangling = 0; + flag_honor_std = 0; + } + 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: ; + } + 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: ; } else for (j = 0; !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]); @@ -546,6 +689,8 @@ lang_decode_option (p) if (!strcmp (p, "implicit")) warn_implicit = setting; + else if (!strcmp (p, "long-long")) + warn_long_long = setting; else if (!strcmp (p, "return-type")) warn_return_type = setting; else if (!strcmp (p, "ctor-dtor-privacy")) @@ -554,20 +699,18 @@ lang_decode_option (p) warn_write_strings = setting; else if (!strcmp (p, "cast-qual")) warn_cast_qual = setting; - else if (!strcmp (p, "traditional")) - warn_traditional = setting; else if (!strcmp (p, "char-subscripts")) warn_char_subscripts = setting; else if (!strcmp (p, "pointer-arith")) warn_pointer_arith = setting; - else if (!strcmp (p, "strict-prototypes")) - warn_strict_prototypes = setting; else if (!strcmp (p, "missing-prototypes")) warn_missing_prototypes = setting; else if (!strcmp (p, "redundant-decls")) warn_redundant_decls = setting; else if (!strcmp (p, "missing-braces")) warn_missing_braces = setting; + else if (!strcmp (p, "sign-compare")) + warn_sign_compare = setting; else if (!strcmp (p, "format")) warn_format = setting; else if (!strcmp (p, "conversion")) @@ -582,6 +725,22 @@ lang_decode_option (p) warn_reorder = setting; else if (!strcmp (p, "synth")) warn_synth = setting; + else if (!strcmp (p, "pmf-conversions")) + warn_pmf2ptr = setting; + else if (!strcmp (p, "effc++")) + warn_ecpp = setting; + else if (!strcmp (p, "sign-promo")) + warn_sign_promo = setting; + else if (!strcmp (p, "old-style-cast")) + warn_old_style_cast = setting; + else if (!strcmp (p, "overloaded-virtual")) + warn_overloaded_virtual = setting; + else if (!strcmp (p, "multichar")) + warn_multichar = setting; + else if (!strcmp (p, "unknown-pragmas")) + /* 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, "comment")) ; /* cpp handles this one. */ else if (!strcmp (p, "comments")) @@ -592,7 +751,6 @@ lang_decode_option (p) ; /* cpp handles this one. */ else if (!strcmp (p, "all")) { - extra_warnings = setting; warn_return_type = setting; warn_unused = setting; warn_implicit = setting; @@ -601,23 +759,25 @@ lang_decode_option (p) 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_template_debugging = setting; warn_reorder = setting; + warn_sign_promo = setting; + /* Only warn about unknown pragmas that are not in system + headers. */ + warn_unknown_pragmas = 1; } - - else if (!strcmp (p, "overloaded-virtual")) - warn_overloaded_virtual = setting; - else return 0; + else return strings_processed; } else if (!strcmp (p, "-ansi")) - dollars_in_ident = 0, flag_no_nonansi_builtin = 1, flag_ansi = 1, + flag_no_nonansi_builtin = 1, flag_ansi = 1, flag_no_gnu_keywords = 1, flag_operator_names = 1; #ifdef SPEW_DEBUG /* Undocumented, only ever used when you're invoking cc1plus by hand, since @@ -627,7 +787,7 @@ lang_decode_option (p) spew_debug = 1; #endif else - return 0; + return strings_processed; return 1; } @@ -635,6 +795,7 @@ lang_decode_option (p) /* Incorporate `const' and `volatile' qualifiers for member functions. FUNCTION is a TYPE_DECL or a FUNCTION_DECL. QUALS is a list of qualifiers. */ + tree grok_method_quals (ctype, function, quals) tree ctype, function, quals; @@ -682,28 +843,10 @@ grok_method_quals (ctype, function, quals) return ctype; } -#if 0 /* Not used. */ -/* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs. - It leaves DECL_ASSEMBLER_NAMEs with the correct value. */ -/* This does not yet work with user defined conversion operators - It should. */ -static void -substitute_nice_name (decl) - tree decl; -{ - if (DECL_NAME (decl) && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE) - { - char *n = decl_as_string (DECL_NAME (decl), 1); - if (n[strlen (n) - 1] == ' ') - n[strlen (n) - 1] = 0; - DECL_NAME (decl) = get_identifier (n); - } -} -#endif - /* Warn when -fexternal-templates is used and #pragma interface/implementation is not used all the times it should be, inform the user. */ + void warn_if_unknown_interface (decl) tree decl; @@ -734,6 +877,7 @@ warn_if_unknown_interface (decl) } /* A subroutine of the parser, to handle a component list. */ + tree grok_x_components (specs, components) tree specs, components; @@ -758,8 +902,7 @@ grok_x_components (specs, components) { case VAR_DECL: /* Static anonymous unions come out as VAR_DECLs. */ - if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (t)))) + if (ANON_UNION_TYPE_P (TREE_TYPE (t))) return t; /* We return SPECS here, because in the parser it was ending @@ -772,31 +915,37 @@ grok_x_components (specs, components) /* This code may be needed for UNION_TYPEs as well. */ tcode = record_type_node; - if (CLASSTYPE_DECLARED_CLASS(t)) + if (CLASSTYPE_DECLARED_CLASS (t)) tcode = class_type_node; - else if (IS_SIGNATURE(t)) + else if (IS_SIGNATURE (t)) tcode = signature_type_node; - - t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0); - if (TYPE_CONTEXT(t)) - CLASSTYPE_NO_GLOBALIZE(t) = 1; + + if (CLASSTYPE_IS_TEMPLATE (t)) + /* In this case, the TYPE_IDENTIFIER will be something + like S, 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; case UNION_TYPE: case ENUMERAL_TYPE: - if (TREE_CODE(t) == UNION_TYPE) + if (TREE_CODE (t) == UNION_TYPE) tcode = union_type_node; else tcode = enum_type_node; t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0); - if (TREE_CODE(t) == UNION_TYPE && TYPE_CONTEXT(t)) - CLASSTYPE_NO_GLOBALIZE(t) = 1; - if (TREE_CODE (t) == UNION_TYPE - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) + 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 */ @@ -808,13 +957,24 @@ grok_x_components (specs, components) 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"); + 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 (t, NULL_TREE); + x = grok_enum_decls (NULL_TREE); else x = NULL_TREE; return x; @@ -827,13 +987,63 @@ grok_x_components (specs, components) } } else - { - t = TREE_TYPE (components); - if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t)) - return grok_enum_decls (t, components); - else - return components; - } + /* 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); +} + +/* Constructors for types with virtual baseclasses need an "in-charge" flag + saying whether this constructor is responsible for initialization of + virtual baseclasses or not. All destructors also need this "in-charge" + flag, which additionally determines whether or not the destructor should + free the memory for the object. + + This function adds the "in-charge" flag to member function FN if + appropriate. It is called from grokclassfn and tsubst. + FN must be either a constructor or destructor. */ + +void +maybe_retrofit_in_chrg (fn) + tree fn; +{ + tree basetype, arg_types, parms, parm, fntype; + + if (DECL_CONSTRUCTOR_P (fn) + && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn)) + && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn)) + /* OK */; + else if (! DECL_CONSTRUCTOR_P (fn) + && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE) + /* OK */; + else + return; + + if (DECL_CONSTRUCTOR_P (fn)) + DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1; + + /* First add it to DECL_ARGUMENTS... */ + parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); + /* Mark the artificial `__in_chrg' parameter as "artificial". */ + SET_DECL_ARTIFICIAL (parm); + DECL_ARG_TYPE (parm) = integer_type_node; + TREE_READONLY (parm) = 1; + parms = DECL_ARGUMENTS (fn); + TREE_CHAIN (parm) = TREE_CHAIN (parms); + TREE_CHAIN (parms) = parm; + + /* ...and then to TYPE_ARG_TYPES. */ + arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); + basetype = TREE_TYPE (TREE_VALUE (arg_types)); + arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); + fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), + arg_types); + if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) + fntype = build_exception_variant (fntype, + TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); + TREE_TYPE (fn) = fntype; } /* Classes overload their constituent function names automatically. @@ -866,8 +1076,6 @@ grokclassfn (ctype, cname, function, flags, quals) tree arg_types; tree parm; tree qualtype; - tree fntype = TREE_TYPE (function); - tree raises = TYPE_RAISES_EXCEPTIONS (fntype); if (fn_name == NULL_TREE) { @@ -894,24 +1102,6 @@ grokclassfn (ctype, cname, function, flags, quals) && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))) constp = 0; - if (DECL_CONSTRUCTOR_P (function)) - { - if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) - { - DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1; - /* In this case we need "in-charge" flag saying whether - this constructor is responsible for initialization - of virtual baseclasses or not. */ - parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); - /* Mark the artificial `__in_chrg' parameter as "artificial". */ - SET_DECL_ARTIFICIAL (parm); - DECL_ARG_TYPE (parm) = integer_type_node; - DECL_REGISTER (parm) = 1; - TREE_CHAIN (parm) = last_function_parms; - last_function_parms = parm; - } - } - parm = build_decl (PARM_DECL, this_identifier, type); /* Mark the artificial `this' parameter as "artificial". */ SET_DECL_ARTIFICIAL (parm); @@ -925,99 +1115,37 @@ grokclassfn (ctype, cname, function, flags, quals) last_function_parms = parm; } - if (flags == DTOR_FLAG) + DECL_ARGUMENTS (function) = last_function_parms; + /* First approximations. */ + DECL_CONTEXT (function) = ctype; + DECL_CLASS_CONTEXT (function) = ctype; + + if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)) { - char *buf, *dbuf; - tree const_integer_type = build_type_variant (integer_type_node, 1, 0); - int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1; - - arg_types = hash_tree_chain (const_integer_type, void_list_node); - TREE_SIDE_EFFECTS (arg_types) = 1; - /* Build the overload name. It will look like `7Example'. */ - if (IDENTIFIER_TYPE_VALUE (cname)) - dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1); - else if (IDENTIFIER_LOCAL_VALUE (cname)) - dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1); - else - /* Using ctype fixes the `X::Y::~Y()' crash. The cname has no type when - it's defined out of the class definition, since poplevel_class wipes - it out. This used to be internal error 346. */ - dbuf = build_overload_name (ctype, 1, 1); - buf = (char *) alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX)); - bcopy (DESTRUCTOR_DECL_PREFIX, buf, len); - buf[len] = '\0'; - strcat (buf, dbuf); - DECL_ASSEMBLER_NAME (function) = get_identifier (buf); - parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type); - /* Mark the artificial `__in_chrg' parameter as "artificial". */ - SET_DECL_ARTIFICIAL (parm); - TREE_USED (parm) = 1; -#if 0 - /* We don't need to mark the __in_chrg parameter itself as `const' - since its type is already `const int'. In fact we MUST NOT mark - it as `const' cuz that will screw up the debug info (causing it - to say that the type of __in_chrg is `const const int'). */ - TREE_READONLY (parm) = 1; -#endif - DECL_ARG_TYPE (parm) = const_integer_type; - /* This is the same chain as DECL_ARGUMENTS (...). */ - TREE_CHAIN (last_function_parms) = parm; + maybe_retrofit_in_chrg (function); + arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); + } - fntype = build_cplus_method_type (qualtype, void_type_node, - arg_types); - if (raises) - { - fntype = build_exception_variant (fntype, raises); - } - TREE_TYPE (function) = fntype; + if (flags == DTOR_FLAG) + { + DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype); TYPE_HAS_DESTRUCTOR (ctype) = 1; } else { - tree these_arg_types; - - if (DECL_CONSTRUCTOR_FOR_VBASE_P (function)) - { - arg_types = hash_tree_chain (integer_type_node, - TREE_CHAIN (arg_types)); - fntype = build_cplus_method_type (qualtype, - TREE_TYPE (TREE_TYPE (function)), - arg_types); - if (raises) - { - fntype = build_exception_variant (fntype, raises); - } - TREE_TYPE (function) = fntype; - arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); - } - - these_arg_types = arg_types; - if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) /* Only true for static member functions. */ - these_arg_types = hash_tree_chain (build_pointer_type (qualtype), - arg_types); + arg_types = hash_tree_chain (build_pointer_type (qualtype), + arg_types); DECL_ASSEMBLER_NAME (function) - = build_decl_overload (fn_name, these_arg_types, + = build_decl_overload (fn_name, arg_types, 1 + DECL_CONSTRUCTOR_P (function)); - -#if 0 - /* This code is going into the compiler, but currently, it makes - libg++/src/Integer.cc not compile. The problem is that the nice name - winds up going into the symbol table, and conversion operations look - for the manged name. */ - substitute_nice_name (function); -#endif } - - DECL_ARGUMENTS (function) = last_function_parms; - /* First approximations. */ - DECL_CONTEXT (function) = ctype; - DECL_CLASS_CONTEXT (function) = ctype; } /* Work on the expr used by alignof (this is only called by the parser). */ + tree grok_alignof (expr) tree expr; @@ -1025,6 +1153,9 @@ grok_alignof (expr) tree best, t; int bestalign; + if (processing_template_decl) + return build_min (ALIGNOF_EXPR, sizetype, expr); + if (TREE_CODE (expr) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND (expr, 1))) error ("`__alignof__' applied to a bit-field"); @@ -1061,6 +1192,7 @@ grok_alignof (expr) /* Create an ARRAY_REF, checking for the user doing things backwards along the way. */ + tree grok_array_decl (array_expr, index_exp) tree array_expr, index_exp; @@ -1070,6 +1202,10 @@ grok_array_decl (array_expr, index_exp) if (type == error_mark_node || index_exp == error_mark_node) return error_mark_node; + if (processing_template_decl) + return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE, + array_expr, index_exp); + if (type == NULL_TREE) { /* Something has gone very wrong. Assume we are mistakenly reducing @@ -1083,8 +1219,7 @@ grok_array_decl (array_expr, index_exp) type = TREE_TYPE (type); /* If they have an `operator[]', use that. */ - if (TYPE_LANG_SPECIFIC (type) - && TYPE_OVERLOADS_ARRAY_REF (type)) + if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp))) return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, NULL_TREE); @@ -1130,78 +1265,70 @@ grok_array_decl (array_expr, index_exp) for doing an array delete. If DOING_VEC is 2, they gave us the array size as an argument to delete. Implements ARM $5.3.4. This is called from the parser. */ + tree delete_sanity (exp, size, doing_vec, use_global_delete) tree exp, size; int doing_vec, use_global_delete; { - tree t = stabilize_reference (convert_from_reference (exp)); - tree type = TREE_TYPE (t); - enum tree_code code = TREE_CODE (type); + tree t, type; /* For a regular vector delete (aka, no size argument) we will pass this down as a NULL_TREE into build_vec_delete. */ tree maxindex = NULL_TREE; - /* This is used for deleting arrays. */ - tree elt_size; - switch (doing_vec) + if (exp == error_mark_node) + return exp; + + if (processing_template_decl) { - case 2: - maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); - if (! flag_traditional) - pedwarn ("anachronistic use of array size in vector delete"); - /* Fall through. */ - case 1: - elt_size = c_sizeof (type); - break; - default: - if (code != POINTER_TYPE) - { - cp_error ("type `%#T' argument given to `delete', expected pointer", - type); - return error_mark_node; - } + t = build_min (DELETE_EXPR, void_type_node, exp, size); + DELETE_EXPR_USE_GLOBAL (t) = use_global_delete; + DELETE_EXPR_USE_VEC (t) = doing_vec; + return t; + } - /* Deleting a pointer with the value zero is valid and has no effect. */ - if (integer_zerop (t)) - return build1 (NOP_EXPR, void_type_node, t); + if (TREE_CODE (exp) == OFFSET_REF) + exp = resolve_offset_ref (exp); + exp = convert_from_reference (exp); + t = stabilize_reference (exp); + t = build_expr_type_conversion (WANT_POINTER, t, 1); + + if (t == NULL_TREE || t == error_mark_node) + { + cp_error ("type `%#T' argument given to `delete', expected pointer", + TREE_TYPE (exp)); + return error_mark_node; } - if (code == POINTER_TYPE) + if (doing_vec == 2) { -#if 0 - /* As of Valley Forge, you can delete a pointer to constant. */ - /* You can't delete a pointer to constant. */ - if (TREE_READONLY (TREE_TYPE (type))) - { - error ("`const *' cannot be deleted"); - return error_mark_node; - } -#endif - /* You also can't delete functions. */ - if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) - { - error ("cannot delete a function"); - return error_mark_node; - } + maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); + pedwarn ("anachronistic use of array size in vector delete"); } -#if 0 - /* If the type has no destructor, then we should build a regular - delete, instead of a vector delete. Otherwise, we would end - up passing a bogus offset into __builtin_delete, which is - not expecting it. */ - if (doing_vec - && TREE_CODE (type) == POINTER_TYPE - && !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type))) + type = TREE_TYPE (t); + + /* As of Valley Forge, you can delete a pointer to const. */ + + /* You can't delete functions. */ + if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) { - doing_vec = 0; - use_global_delete = 1; + error ("cannot delete a function"); + return error_mark_node; } -#endif + + /* 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 + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE) + cp_warning ("deleting array `%#D'", TREE_OPERAND (t, 0)); + + /* Deleting a pointer with the value zero is valid and has no effect. */ + if (integer_zerop (t)) + return build1 (NOP_EXPR, void_type_node, t); if (doing_vec) - return build_vec_delete (t, maxindex, elt_size, integer_one_node, + return build_vec_delete (t, maxindex, integer_one_node, integer_two_node, use_global_delete); else { @@ -1210,16 +1337,107 @@ delete_sanity (exp, size, doing_vec, use_global_delete) { /* Only do access checking here; we'll be calling op delete from the destructor. */ - tree tmp = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, t, - size_zero_node, NULL_TREE); + tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node, + LOOKUP_NORMAL, NULL_TREE); if (tmp == error_mark_node) return error_mark_node; } return build_delete (type, t, integer_three_node, - LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, - use_global_delete); + LOOKUP_NORMAL, use_global_delete); + } +} + +/* Report an error if the indicated template declaration is not the + sort of thing that should be a member template. */ + +void +check_member_template (tmpl) + tree tmpl; +{ + tree decl; + + my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); + decl = DECL_TEMPLATE_RESULT (tmpl); + + if (TREE_CODE (decl) == FUNCTION_DECL + || (TREE_CODE (decl) == TYPE_DECL + && IS_AGGR_TYPE (TREE_TYPE (decl)))) + { + if (current_function_decl) + /* 14.5.2.2 [temp.mem] + + A local class shall not have member templates. */ + cp_error ("declaration of member template `%#D' in local class", + decl); + + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) + { + /* 14.5.2.3 [temp.mem] + + A member function template shall not be virtual. */ + cp_error + ("invalid use of `virtual' in template declaration of `%#D'", + decl); + DECL_VIRTUAL_P (decl) = 0; + } + + /* The debug-information generating code doesn't know what to do + with member templates. */ + DECL_IGNORED_P (tmpl) = 1; + } + else + cp_error ("template declaration of `%#D'", decl); +} + +/* Return true iff TYPE is a valid Java parameter or return type. */ + +int +acceptable_java_type (type) + tree type; +{ + if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type)) + return 1; + if (TREE_CODE (type) == POINTER_TYPE) + { + type = TREE_TYPE (type); + if (TREE_CODE (type) == RECORD_TYPE) + { + complete_type (type); + return TYPE_FOR_JAVA (type); + } } + return 0; +} + +/* For a METHOD in a Java class CTYPE, return 1 if + the parameter and return types are valid Java types. + Otherwise, print appropriate error messages, and return 0. */ + +int +check_java_method (ctype, method) + tree ctype, method; +{ + int jerr = 0; + tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method)); + tree ret_type = TREE_TYPE (TREE_TYPE (method)); + if (! acceptable_java_type (ret_type)) + { + cp_error ("Java method '%D' has non-Java return type `%T'", + method, ret_type); + jerr++; + } + for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types)) + { + tree type = TREE_VALUE (arg_types); + if (! acceptable_java_type (type)) + { + cp_error ("Java method '%D' has non-Java parameter type `%T'", + method, type); + jerr++; + } + } + return jerr ? 0 : 1; } /* Sanity check: report error if this function FUNCTION is not @@ -1227,14 +1445,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete) CNAME is the same here as it is for grokclassfn above. */ tree -check_classfn (ctype, cname, function) - tree ctype, cname, function; +check_classfn (ctype, function) + tree ctype, function; { tree fn_name = DECL_NAME (function); - tree fndecl; - tree method_vec = CLASSTYPE_METHOD_VEC (ctype); + tree fndecl, fndecls; + tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype)); tree *methods = 0; tree *end = 0; + tree templates = NULL_TREE; if (method_vec != 0) { @@ -1242,65 +1461,100 @@ check_classfn (ctype, cname, function) end = TREE_VEC_END (method_vec); /* First suss out ctors and dtors. */ - if (*methods && fn_name == DECL_NAME (*methods)) + if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) + && DECL_CONSTRUCTOR_P (function)) + goto got_it; + if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) + && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))) goto got_it; while (++methods != end) { - if (fn_name == DECL_NAME (*methods)) + fndecl = *methods; + if (fn_name == DECL_NAME (OVL_CURRENT (*methods))) { got_it: - fndecl = *methods; - while (fndecl) + for (fndecls = *methods; fndecls != NULL_TREE; + fndecls = OVL_NEXT (fndecls)) { - if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl)) - return fndecl; -#if 0 - /* This should work, but causes libg++ to fail - make check-tFix. */ - /* We have to do more extensive argument checking here, as - the name may have been changed by asm("new_name"). */ - if (decls_match (function, fndecl)) + fndecl = OVL_CURRENT (fndecls); + /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL 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)) + && (DECL_ASSEMBLER_NAME (function) + == DECL_ASSEMBLER_NAME (fndecl))) return fndecl; -#else + + /* We cannot simply call decls_match because this + doesn't work for static member functions that are + pretending to be methods, and because the name + may have been changed by asm("new_name"). */ if (DECL_NAME (function) == DECL_NAME (fndecl)) { tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); /* Get rid of the this parameter on functions that become - static. */ + static. */ if (DECL_STATIC_FUNCTION_P (fndecl) && 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 (DECL_STATIC_FUNCTION_P (fndecl) - && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) - revert_static_member_fn (&function, NULL, NULL); - return fndecl; - } + && compparms (p1, p2, 3) + && (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); } -#endif - fndecl = DECL_CHAIN (fndecl); } 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) { tree fndecl = *methods; cp_error ("prototype for `%#D' does not match any in class `%T'", function, ctype); - cp_error_at ("candidate%s: %+#D", DECL_CHAIN (fndecl) ? "s are" : " is", - fndecl); - while (fndecl = DECL_CHAIN (fndecl), fndecl) - cp_error_at (" %#D", fndecl); + cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is", + OVL_CURRENT (fndecl)); + while (fndecl = OVL_NEXT (fndecl), fndecl) + cp_error_at (" %#D", OVL_CURRENT(fndecl)); } else { @@ -1309,8 +1563,8 @@ check_classfn (ctype, cname, function) function, ctype); } - /* If we did not find the method in the class, add it to - avoid spurious errors. */ + /* If we did not find the method in the class, add it to avoid + spurious errors. */ add_method (ctype, methods, function); return NULL_TREE; } @@ -1336,8 +1590,8 @@ check_classfn (ctype, cname, function) CHANGES TO CODE IN `start_method'. */ tree -grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) - tree declarator, declspecs, raises, init, asmspec_tree, attrlist; +grokfield (declarator, declspecs, init, asmspec_tree, attrlist) + tree declarator, declspecs, init, asmspec_tree, attrlist; { register tree value; char *asmspec = 0; @@ -1356,14 +1610,25 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) flags = 0; } + if (declspecs == NULL_TREE + && TREE_CODE (declarator) == SCOPE_REF + && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE) + { + /* Access declaration */ + if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0)))) + ; + else if (TREE_COMPLEXITY (declarator) == current_class_depth) + pop_nested_class (1); + return do_class_using_decl (declarator); + } + if (init && TREE_CODE (init) == TREE_LIST && TREE_VALUE (init) == error_mark_node && TREE_CHAIN (init) == NULL_TREE) - init = NULL_TREE; + init = NULL_TREE; - value = grokdeclarator (declarator, declspecs, FIELD, init != 0, - raises, NULL_TREE); + value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE); if (! value) return value; /* friend or constructor went bad. */ @@ -1374,7 +1639,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) if (DECL_NAME (value) != NULL_TREE && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) - cp_error ("member `%D' conflicts with virtual function table field name", value); + cp_error ("member `%D' conflicts with virtual function table field name", + value); /* Stash away type declarations. */ if (TREE_CODE (value) == TYPE_DECL) @@ -1384,15 +1650,11 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) DECL_CLASS_CONTEXT (value) = current_class_type; CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; - /* If we declare a typedef name for something that has no name, - the typedef name is used for linkage. See 7.1.3 p4 94/0158. */ - if (TYPE_NAME (TREE_TYPE (value)) - && TREE_CODE (TYPE_NAME (TREE_TYPE (value))) == TYPE_DECL - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (value)))) - { - TYPE_NAME (TREE_TYPE (value)) = value; - TYPE_STUB_DECL (TREE_TYPE (value)) = value; - } + /* 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)); pushdecl_class_level (value); return value; @@ -1412,9 +1674,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) return void_type_node; } - if (flag_cadillac) - cadillac_start_decl (value); - if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); @@ -1458,6 +1717,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) because `decl_const_value' would mis-interpret it as only meaning that this VAR_DECL is defined. */ init = build1 (NOP_EXPR, TREE_TYPE (value), init); + else if (processing_template_decl) + ; else if (! TREE_CONSTANT (init)) { /* We can allow references to things that are effectively @@ -1477,45 +1738,51 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) /* The corresponding pop_obstacks is in cp_finish_decl. */ push_obstacks_nochange (); + if (processing_template_decl && ! current_function_decl + && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL)) + value = push_template_decl (value); + if (attrlist) cplus_decl_attributes (value, TREE_PURPOSE (attrlist), TREE_VALUE (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. */ - if (TREE_PUBLIC (value)) + /* current_class_type can be NULL_TREE in case of error. */ + if (asmspec == 0 && current_class_type) { - /* 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)); - } - 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; + 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); @@ -1539,15 +1806,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) } if (TREE_CODE (value) == FUNCTION_DECL) { - check_default_args (value); - if (DECL_CHAIN (value) != NULL_TREE) - { - /* Need a fresh node here so that we don't get circularity - when we link these together. */ - value = copy_node (value); - /* When does this happen? */ - my_friendly_assert (init == NULL_TREE, 193); - } if (asmspec) { /* This must override the asm specifier which was placed @@ -1583,7 +1841,7 @@ grokbitfield (declarator, declspecs, width) tree declarator, declspecs, width; { register tree value = grokdeclarator (declarator, declspecs, BITFIELD, - 0, NULL_TREE, NULL_TREE); + 0, NULL_TREE); if (! value) return NULL_TREE; /* friends went bad. */ @@ -1621,216 +1879,20 @@ grokbitfield (declarator, declspecs, width) if (width != error_mark_node) { - /* detect invalid field size. */ - if (TREE_CODE (width) == CONST_DECL) - width = DECL_INITIAL (width); - else if (TREE_READONLY_DECL_P (width)) - width = decl_constant_value (width); - if (TREE_CODE (width) != INTEGER_CST) - { - cp_error ("structure field `%D' width not an integer constant", - value); - DECL_INITIAL (value) = NULL_TREE; - } - else - { - constant_expression_warning (width); - DECL_INITIAL (value) = width; - DECL_BIT_FIELD (value) = 1; - } + constant_expression_warning (width); + DECL_INITIAL (value) = width; + DECL_BIT_FIELD (value) = 1; } DECL_IN_AGGR_P (value) = 1; return value; } -#if 0 -/* Like GROKFIELD, except that the declarator has been - buried in DECLSPECS. Find the declarator, and - return something that looks like it came from - GROKFIELD. */ -tree -groktypefield (declspecs, parmlist) - tree declspecs; - tree parmlist; -{ - tree spec = declspecs; - tree prev = NULL_TREE; - - tree type_id = NULL_TREE; - tree quals = NULL_TREE; - tree lengths = NULL_TREE; - tree decl = NULL_TREE; - - while (spec) - { - register tree id = TREE_VALUE (spec); - - if (TREE_CODE (spec) != TREE_LIST) - /* Certain parse errors slip through. For example, - `int class ();' is not caught by the parser. Try - weakly to recover here. */ - return NULL_TREE; - - if (TREE_CODE (id) == TYPE_DECL - || (TREE_CODE (id) == IDENTIFIER_NODE && TREE_TYPE (id))) - { - /* We have a constructor/destructor or - conversion operator. Use it. */ - if (prev) - TREE_CHAIN (prev) = TREE_CHAIN (spec); - else - declspecs = TREE_CHAIN (spec); - - type_id = id; - goto found; - } - prev = spec; - spec = TREE_CHAIN (spec); - } - - /* Nope, we have a conversion operator to a scalar type or something - else, that includes things like constructor declarations for - templates. */ - spec = declspecs; - while (spec) - { - tree id = TREE_VALUE (spec); - - if (TREE_CODE (id) == IDENTIFIER_NODE) - { - if (id == ridpointers[(int)RID_INT] - || id == ridpointers[(int)RID_DOUBLE] - || id == ridpointers[(int)RID_FLOAT] - || id == ridpointers[(int)RID_WCHAR]) - { - if (type_id) - error ("extra `%s' ignored", - IDENTIFIER_POINTER (id)); - else - type_id = id; - } - else if (id == ridpointers[(int)RID_LONG] - || id == ridpointers[(int)RID_SHORT] - || id == ridpointers[(int)RID_CHAR]) - { - lengths = tree_cons (NULL_TREE, id, lengths); - } - else if (id == ridpointers[(int)RID_VOID]) - { - if (type_id) - error ("spurious `void' type ignored"); - else - error ("conversion to `void' type invalid"); - } - else if (id == ridpointers[(int)RID_AUTO] - || id == ridpointers[(int)RID_REGISTER] - || id == ridpointers[(int)RID_TYPEDEF] - || id == ridpointers[(int)RID_CONST] - || id == ridpointers[(int)RID_VOLATILE]) - { - error ("type specifier `%s' used invalidly", - IDENTIFIER_POINTER (id)); - } - else if (id == ridpointers[(int)RID_FRIEND] - || id == ridpointers[(int)RID_VIRTUAL] - || id == ridpointers[(int)RID_INLINE] - || id == ridpointers[(int)RID_UNSIGNED] - || id == ridpointers[(int)RID_SIGNED] - || id == ridpointers[(int)RID_STATIC] - || id == ridpointers[(int)RID_EXTERN]) - { - quals = tree_cons (NULL_TREE, id, quals); - } - else - { - /* Happens when we have a global typedef - and a class-local member function with - the same name. */ - type_id = id; - goto found; - } - } - else if (TREE_CODE (id) == RECORD_TYPE) - { - type_id = TYPE_NAME (id); - if (TREE_CODE (type_id) == TYPE_DECL) - type_id = DECL_NAME (type_id); - if (type_id == NULL_TREE) - error ("identifier for aggregate type conversion omitted"); - } - else if (TREE_CODE_CLASS (TREE_CODE (id)) == 't') - error ("`operator' missing on conversion operator or tag missing from type"); - else - my_friendly_abort (194); - spec = TREE_CHAIN (spec); - } - - if (type_id) - declspecs = chainon (lengths, quals); - else if (lengths) - { - if (TREE_CHAIN (lengths)) - error ("multiple length specifiers"); - type_id = ridpointers[(int)RID_INT]; - declspecs = chainon (lengths, quals); - } - else if (quals) - { - error ("no type given, defaulting to `operator int ...'"); - type_id = ridpointers[(int)RID_INT]; - declspecs = quals; - } - else - return NULL_TREE; - - found: - decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE), - declspecs, FIELD, 0, NULL_TREE, NULL_TREE); - if (decl == NULL_TREE) - return NULL_TREE; - - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CHAIN (decl) != NULL_TREE) - { - /* Need a fresh node here so that we don't get circularity - when we link these together. */ - decl = copy_node (decl); - } - - if (decl == void_type_node - || (TREE_CODE (decl) == FUNCTION_DECL - && TREE_CODE (TREE_TYPE (decl)) != METHOD_TYPE)) - /* bunch of friends. */ - return decl; - - if (DECL_IN_AGGR_P (decl)) - { - cp_error ("`%D' already defined in the class ", decl); - return void_type_node; - } - - cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0); - - /* If this declaration is common to another declaration - complain about such redundancy, and return NULL_TREE - so that we don't build a circular list. */ - if (DECL_CHAIN (decl)) - { - cp_error ("function `%D' declared twice in class %T", decl, - DECL_CONTEXT (decl)); - return NULL_TREE; - } - DECL_IN_AGGR_P (decl) = 1; - return decl; -} -#endif - tree grokoptypename (declspecs, declarator) tree declspecs, declarator; { - tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, - NULL_TREE, NULL_TREE); + tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); return build_typename_overload (t); } @@ -1874,11 +1936,18 @@ copy_assignment_arg_p (parmtype, virtualp) tree parmtype; int virtualp; { + if (current_class_type == NULL_TREE) + return 0; + if (TREE_CODE (parmtype) == REFERENCE_TYPE) parmtype = TREE_TYPE (parmtype); if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type) - || (virtualp && DERIVED_FROM_P (parmtype, current_class_type))) +#if 0 + /* Non-standard hack to support old Booch components. */ + || (! virtualp && DERIVED_FROM_P (parmtype, current_class_type)) +#endif + ) return 1; return 0; @@ -1895,14 +1964,17 @@ grok_function_init (decl, init) if (TREE_CODE (type) == FUNCTION_TYPE) cp_error ("initializer specified for non-member function `%D'", decl); +#if 0 + /* We'll check for this in finish_struct_1. */ else if (DECL_VINDEX (decl) == NULL_TREE) cp_error ("initializer specified for non-virtual method `%D'", decl); +#endif else if (integer_zerop (init)) { #if 0 /* Mark this function as being "defined". */ DECL_INITIAL (decl) = error_mark_node; - /* pure virtual destructors must be defined. */ + /* pure virtual destructors must be defined. */ /* pure virtual needs to be defined (as abort) only when put in vtbl. For wellformed call, it should be itself. pr4737 */ if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))) @@ -1922,88 +1994,10 @@ grok_function_init (decl, init) TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1; } } - else if (TREE_CODE (init) == OFFSET_REF - && TREE_OPERAND (init, 0) == NULL_TREE - && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE) - { - tree basetype = DECL_CLASS_CONTEXT (init); - tree basefn = TREE_OPERAND (init, 1); - if (TREE_CODE (basefn) != FUNCTION_DECL) - cp_error ("non-method initializer invalid for method `%D'", decl); - else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn)))) - sorry ("base member function from other than first base class"); - else - { - tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1); - if (binfo == error_mark_node) - ; - else if (binfo == 0) - error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)), - TYPE_METHOD_BASETYPE (type)); - else - { - /* Mark this function as being defined, - and give it new rtl. */ - DECL_INITIAL (decl) = error_mark_node; - DECL_RTL (decl) = DECL_RTL (basefn); - } - } - } else cp_error ("invalid initializer for virtual method `%D'", decl); } -/* When we get a declaration of the form - - type cname::fname ... - - the node for `cname::fname' gets built here in a special way. - Namely, we push into `cname's scope. When this declaration is - processed, we pop back out. */ -tree -build_push_scope (cname, name) - tree cname; - tree name; -{ - extern int current_class_depth; - tree ctype, rval; - int is_ttp = 0; - - if (cname == error_mark_node) - return error_mark_node; - - ctype = IDENTIFIER_TYPE_VALUE (cname); - - if (TREE_CODE (ctype) == TEMPLATE_TYPE_PARM) - is_ttp = 1; - else if (ctype == NULL_TREE || ! IS_AGGR_TYPE (ctype)) - { - cp_error ("`%T' not defined as aggregate type", cname); - return name; - } - else if (IS_SIGNATURE (ctype)) - { - error ("cannot push into signature scope, scope resolution operator ignored"); - return name; - } - - rval = build_parse_node (SCOPE_REF, cname, name); - - /* Don't need to push the scope if we're already in it. - We also don't need to push the scope for a ptr-to-member/method. */ - - if (ctype == current_class_type || TREE_CODE (name) != IDENTIFIER_NODE - || is_ttp) - return rval; - - /* We do need to push the scope in this case, since CTYPE helps - determine subsequent initializers (i.e., Foo::Bar x = foo_enum_1;). */ - - push_nested_class (ctype, 3); - TREE_COMPLEXITY (rval) = current_class_depth; - return rval; -} - void cplus_decl_attributes (decl, attributes, prefix_attributes) tree decl, attributes, prefix_attributes; @@ -2025,22 +2019,25 @@ cplus_decl_attributes (decl, attributes, prefix_attributes) specified class. Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE. When given a template, this routine doesn't lose the specialization. */ + tree constructor_name_full (thing) tree thing; { - if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE) - return DECL_NAME (UPT_TEMPLATE (thing)); - if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) + if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM + || TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM + || TREE_CODE (thing) == TYPENAME_TYPE) + thing = TYPE_NAME (thing); + else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) { if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing)) - thing = DECL_NAME (TREE_VEC_ELT (TYPE_METHODS (thing), 0)); + thing = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0))); else thing = TYPE_NAME (thing); } if (TREE_CODE (thing) == TYPE_DECL || (TREE_CODE (thing) == TEMPLATE_DECL - && DECL_TEMPLATE_IS_CLASS (thing))) + && TREE_CODE (DECL_TEMPLATE_RESULT (thing)) == TYPE_DECL)) thing = DECL_NAME (thing); my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197); return thing; @@ -2051,6 +2048,7 @@ constructor_name_full (thing) specified class. Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE. When given a template, return the plain unspecialized name. */ + tree constructor_name (thing) tree thing; @@ -2060,13 +2058,13 @@ constructor_name (thing) t = IDENTIFIER_TEMPLATE (thing); if (!t) return thing; - t = TREE_PURPOSE (t); - return DECL_NAME (t); + return t; } /* Cache the value of this class's main virtual function table pointer in a register variable. This will save one indirection if a more than one virtual function call is made this function. */ + void setup_vtbl_ptr () { @@ -2074,10 +2072,18 @@ setup_vtbl_ptr () if (base_init_expr == 0 && DECL_CONSTRUCTOR_P (current_function_decl)) - emit_base_init (current_class_type, 0); + { + if (processing_template_decl) + add_tree (build_min_nt + (CTOR_INITIALIZER, + current_member_init_list, current_base_init_list)); + else + emit_base_init (current_class_type, 0); + } } /* Record the existence of an addressable inline function. */ + void mark_inline_for_output (decl) tree decl; @@ -2147,6 +2153,7 @@ get_temp_name (type, staticp) } TREE_USED (decl) = 1; TREE_STATIC (decl) = staticp; + DECL_ARTIFICIAL (decl) = 1; /* If this is a local variable, then lay out its rtl now. Otherwise, callers of this function are responsible for dealing @@ -2165,39 +2172,99 @@ get_temp_name (type, staticp) It is not entered into current_binding_level, because that breaks things when it comes time to do final cleanups (which take place "outside" the binding contour of the function). */ + tree get_temp_regvar (type, init) tree type, init; { - static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' }; tree decl; - sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++); - decl = build_decl (VAR_DECL, get_identifier (buf), type); + decl = build_decl (VAR_DECL, NULL_TREE, type); TREE_USED (decl) = 1; DECL_REGISTER (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; - if (init) - store_init_value (decl, init); - + DECL_RTL (decl) = assign_temp (type, 2, 0, 1); /* We can expand these without fear, since they cannot need constructors or destructors. */ - expand_decl (decl); - expand_decl_init (decl); - - if (type_needs_gc_entry (type)) - DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index); + expand_expr (build_modify_expr (decl, INIT_EXPR, init), + NULL_RTX, VOIDmode, 0); return decl; } -/* Make the macro TEMP_NAME_P available to units which do not - include c-tree.h. */ -int -temp_name_p (decl) - tree decl; +/* Hunts through the global anonymous union ANON_DECL, building + appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and + returns a VAR_DECL whose size is the same as the size of the + ANON_DECL, if one is available. */ + +tree +build_anon_union_vars (anon_decl, elems, static_p, external_p) + tree anon_decl; + tree* elems; + int static_p; + int external_p; { - return TEMP_NAME_P (decl); + tree type = TREE_TYPE (anon_decl); + tree main_decl = NULL_TREE; + tree field; + + for (field = TYPE_FIELDS (type); + field != NULL_TREE; + field = TREE_CHAIN (field)) + { + tree decl; + if (TREE_CODE (field) != FIELD_DECL) + continue; + + if (TREE_PRIVATE (field)) + cp_pedwarn_at ("private member `%#D' in anonymous union", field); + else if (TREE_PROTECTED (field)) + cp_pedwarn_at ("protected member `%#D' in anonymous union", field); + + if (DECL_NAME (field) == NULL_TREE + && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + { + decl = build_anon_union_vars (field, elems, static_p, external_p); + if (!decl) + continue; + } + else + { + decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); + /* tell `pushdecl' that this is not tentative. */ + DECL_INITIAL (decl) = error_mark_node; + TREE_PUBLIC (decl) = 0; + TREE_STATIC (decl) = static_p; + DECL_EXTERNAL (decl) = external_p; + decl = pushdecl (decl); + DECL_INITIAL (decl) = NULL_TREE; + } + + /* Only write out one anon union element--choose the one that + can hold them all. */ + if (main_decl == NULL_TREE + && simple_cst_equal (DECL_SIZE (decl), + DECL_SIZE (anon_decl)) == 1) + main_decl = decl; + else + /* ??? This causes there to be no debug info written out + about this decl. */ + TREE_ASM_WRITTEN (decl) = 1; + + if (DECL_NAME (field) == NULL_TREE + && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + /* The remainder of the processing was already done in the + recursive call. */ + continue; + + /* If there's a cleanup to do, it belongs in the + TREE_PURPOSE of the following TREE_LIST. */ + *elems = scratch_tree_cons (NULL_TREE, decl, *elems); + TREE_TYPE (*elems) = type; + } + + return main_decl; } /* Finish off the processing of a UNION_TYPE structure. @@ -2206,18 +2273,19 @@ temp_name_p (decl) union is an anonymous union, we arrange for that as well. PUBLIC_P is nonzero if this union is not declared static. */ + void finish_anon_union (anon_union_decl) tree anon_union_decl; { tree type = TREE_TYPE (anon_union_decl); - tree field, main_decl = NULL_TREE; tree elems = NULL_TREE; + tree main_decl; int public_p = TREE_PUBLIC (anon_union_decl); int static_p = TREE_STATIC (anon_union_decl); int external_p = DECL_EXTERNAL (anon_union_decl); - if ((field = TYPE_FIELDS (type)) == NULL_TREE) + if (TYPE_FIELDS (type) == NULL_TREE) return; if (public_p) @@ -2226,46 +2294,9 @@ finish_anon_union (anon_union_decl) return; } - for (; field; field = TREE_CHAIN (field)) - { - tree decl; - if (TREE_CODE (field) != FIELD_DECL) - continue; - - if (TREE_PRIVATE (field)) - cp_pedwarn_at ("private member `%#D' in anonymous union", field); - else if (TREE_PROTECTED (field)) - cp_pedwarn_at ("protected member `%#D' in anonymous union", field); - - decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); - /* tell `pushdecl' that this is not tentative. */ - DECL_INITIAL (decl) = error_mark_node; - TREE_PUBLIC (decl) = public_p; - TREE_STATIC (decl) = static_p; - DECL_EXTERNAL (decl) = external_p; - decl = pushdecl (decl); - - /* Only write out one anon union element--choose the one that - can hold them all. */ - if (main_decl == NULL_TREE - && 1 == simple_cst_equal (DECL_SIZE (decl), - DECL_SIZE (anon_union_decl))) - { - main_decl = decl; - } - else - { - /* ??? This causes there to be no debug info written out - about this decl. */ - TREE_ASM_WRITTEN (decl) = 1; - } + main_decl = build_anon_union_vars (anon_union_decl, &elems, + static_p, external_p); - DECL_INITIAL (decl) = NULL_TREE; - /* If there's a cleanup to do, it belongs in the - TREE_PURPOSE of the following TREE_LIST. */ - elems = tree_cons (NULL_TREE, decl, elems); - TREE_TYPE (elems) = type; - } if (static_p) { if (main_decl) @@ -2283,84 +2314,6 @@ finish_anon_union (anon_union_decl) /* The following call assumes that there are never any cleanups for anonymous unions--a reasonable assumption. */ expand_anon_union_decl (anon_union_decl, NULL_TREE, elems); - - if (flag_cadillac) - cadillac_finish_anon_union (anon_union_decl); -} - -/* Finish and output a table which is generated by the compiler. - NAME is the name to give the table. - TYPE is the type of the table entry. - INIT is all the elements in the table. - PUBLICP is non-zero if this table should be given external access. */ -tree -finish_table (name, type, init, publicp) - tree name, type, init; - int publicp; -{ - tree itype, atype, decl; - static tree empty_table; - int is_empty = 0; - tree asmspec; - - itype = build_index_type (size_int (list_length (init) - 1)); - atype = build_cplus_array_type (type, itype); - layout_type (atype); - - if (TREE_VALUE (init) == integer_zero_node - && TREE_CHAIN (init) == NULL_TREE) - { -#if 0 - if (empty_table == NULL_TREE) -#endif - { - empty_table = get_temp_name (atype, 1); - init = build (CONSTRUCTOR, atype, NULL_TREE, init); - TREE_CONSTANT (init) = 1; - TREE_STATIC (init) = 1; - DECL_INITIAL (empty_table) = init; - asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)), - IDENTIFIER_POINTER (DECL_NAME (empty_table))); - cp_finish_decl (empty_table, NULL_TREE, asmspec, 0, 0); - } - is_empty = 1; - } - - if (name == NULL_TREE) - { - if (is_empty) - return empty_table; - decl = get_temp_name (atype, 1); - } - else - { - decl = build_decl (VAR_DECL, name, atype); - decl = pushdecl (decl); - TREE_STATIC (decl) = 1; - } - - if (is_empty == 0) - { - TREE_PUBLIC (decl) = publicp; - init = build (CONSTRUCTOR, atype, NULL_TREE, init); - TREE_CONSTANT (init) = 1; - TREE_STATIC (init) = 1; - DECL_INITIAL (decl) = init; - asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (decl)), - IDENTIFIER_POINTER (DECL_NAME (decl))); - } - else - { - /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */ - DECL_EXTERNAL (decl) = 1; - TREE_STATIC (decl) = 0; - init = 0; - asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)), - IDENTIFIER_POINTER (DECL_NAME (empty_table))); - } - - cp_finish_decl (decl, NULL_TREE, asmspec, 0, 0); - return decl; } /* Finish processing a builtin type TYPE. It's name is NAME, @@ -2369,6 +2322,7 @@ finish_table (name, type, init, publicp) used in FIELDS. It is given the same alignment as ALIGN_TYPE. */ + void finish_builtin_type (type, name, fields, len, align_type) tree type; @@ -2395,6 +2349,7 @@ finish_builtin_type (type, name, fields, len, align_type) #else TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type); #endif + TYPE_STUB_DECL (type) = TYPE_NAME (type); layout_decl (TYPE_NAME (type), 0); } @@ -2402,8 +2357,6 @@ finish_builtin_type (type, name, fields, len, align_type) `operator new' and `operator delete' correspond to what compiler will be expecting. */ -extern tree sizetype; - tree coerce_new_type (type) tree type; @@ -2433,7 +2386,10 @@ tree coerce_delete_type (type) tree type; { - int e1 = 0, e2 = 0, e3 = 0; + int e1 = 0, e2 = 0; +#if 0 + e3 = 0; +#endif tree arg_types = TYPE_ARG_TYPES (type); if (TREE_CODE (type) == METHOD_TYPE) @@ -2441,12 +2397,15 @@ coerce_delete_type (type) type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types)); arg_types = TREE_CHAIN (arg_types); } + if (TREE_TYPE (type) != void_type_node) e1 = 1, error ("`operator delete' must return type `void'"); + if (arg_types == NULL_TREE || TREE_VALUE (arg_types) != ptr_type_node) e2 = 1, error ("`operator delete' takes type `void *' as first parameter"); +#if 0 if (arg_types && TREE_CHAIN (arg_types) && TREE_CHAIN (arg_types) != void_list_node) @@ -2466,8 +2425,10 @@ coerce_delete_type (type) error ("`...' invalid in specification of `operator delete'"); } } + if (e3) - arg_types = tree_cons (NULL_TREE, ptr_type_node, build_tree_list (NULL_TREE, sizetype)); + arg_types = tree_cons (NULL_TREE, ptr_type_node, + build_tree_list (NULL_TREE, sizetype)); else if (e3 |= e2) { if (arg_types == NULL_TREE) @@ -2476,37 +2437,96 @@ coerce_delete_type (type) arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); } else e3 |= e1; +#endif - if (e3) + if (e2) + arg_types = tree_cons (NULL_TREE, ptr_type_node, + arg_types ? TREE_CHAIN (arg_types): NULL_TREE); + if (e2 || e1) type = build_function_type (void_type_node, arg_types); return type; } +extern tree abort_fndecl; + static void mark_vtable_entries (decl) tree 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 = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); + tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) + : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); tree fn = TREE_OPERAND (fnaddr, 0); TREE_ADDRESSABLE (fn) = 1; - if (DECL_ABSTRACT_VIRTUAL_P (fn)) + if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn)) { - extern tree abort_fndecl; - if (flag_vtable_thunks) - fnaddr = TREE_VALUE (entries); - TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl; + TREE_OPERAND (fnaddr, 0) = fn = copy_node (fn); + DECL_RTL (fn) = DECL_RTL (abort_fndecl); + mark_used (abort_fndecl); + } + if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn)) + { + DECL_EXTERNAL (fn) = 0; + emit_thunk (fn); } - assemble_external (fn); + mark_used (fn); } } +/* Set DECL up to have the closest approximation of "initialized common" + linkage available. */ + +void +comdat_linkage (decl) + tree decl; +{ + if (flag_weak) + make_decl_one_only (decl); + else + TREE_PUBLIC (decl) = 0; + + if (DECL_LANG_SPECIFIC (decl)) + DECL_COMDAT (decl) = 1; +} + +/* For win32 we also want to put explicit instantiations in + linkonce sections, so that they will be merged with implicit + instantiations; otherwise we get duplicate symbol errors. */ + +void +maybe_make_one_only (decl) + tree decl; +{ + /* This is not necessary on targets that support weak symbols, because + the implicit instantiations will defer to the explicit one. */ + if (! supports_one_only () || SUPPORTS_WEAK) + 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. */ + + if (TREE_CODE (decl) == FUNCTION_DECL) + make_decl_one_only (decl); + else + comdat_linkage (decl); +} + /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL, based on TYPE and other static flags. @@ -2534,6 +2554,11 @@ 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 { @@ -2542,11 +2567,12 @@ import_export_vtable (decl, type, final) int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type); +#ifndef MULTIPLE_SYMBOL_SPACES if (! found && ! final) { tree method; - for (method = CLASSTYPE_METHODS (type); method != NULL_TREE; - method = DECL_NEXT_METHOD (method)) + for (method = TYPE_METHODS (type); method != NULL_TREE; + method = TREE_CHAIN (method)) if (DECL_VINDEX (method) != NULL_TREE && ! DECL_THIS_INLINE (method) && ! DECL_ABSTRACT_VIRTUAL_P (method)) @@ -2555,17 +2581,11 @@ import_export_vtable (decl, type, final) break; } } +#endif if (final || ! found) { -#ifdef ASSEMBLE_EXTERNAL - if (TREE_PUBLIC (decl)) - cp_error ("all virtual functions redeclared inline"); -#endif - if (SUPPORTS_WEAK) - DECL_WEAK (decl) = 1; - else - TREE_PUBLIC (decl) = 0; + comdat_linkage (decl); DECL_EXTERNAL (decl) = 0; } else @@ -2576,86 +2596,84 @@ import_export_vtable (decl, type, final) } } -static void -import_export_template (type) - tree type; -{ - if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) - && ! flag_implicit_templates - && CLASSTYPE_INTERFACE_UNKNOWN (type)) - { - SET_CLASSTYPE_INTERFACE_KNOWN (type); - CLASSTYPE_INTERFACE_ONLY (type) = 1; - CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 0; - } -} - -static void -finish_prevtable_vardecl (prev, vars) - tree prev, vars; +/* Determine whether or not we want to specifically import or export CTYPE, + using various heuristics. */ + +void +import_export_class (ctype) + tree ctype; { - tree ctype = DECL_CONTEXT (vars); - import_export_template (ctype); + /* -1 for imported, 1 for exported. */ + int import_export = 0; + + if (CLASSTYPE_INTERFACE_KNOWN (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; +#endif - if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype) + /* If we got -fno-implicit-templates, we import template classes that + weren't explicitly instantiated. */ + if (import_export == 0 + && CLASSTYPE_IMPLICIT_INSTANTIATION (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 + && TYPE_VIRTUAL_P (ctype) && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) { tree method; - for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE; - method = DECL_NEXT_METHOD (method)) + for (method = TYPE_METHODS (ctype); method != NULL_TREE; + method = TREE_CHAIN (method)) { if (DECL_VINDEX (method) != NULL_TREE && !DECL_THIS_INLINE (method) && !DECL_ABSTRACT_VIRTUAL_P (method)) { - SET_CLASSTYPE_INTERFACE_KNOWN (ctype); - CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = ! DECL_EXTERNAL (method); - CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method); + import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); break; } } } +#endif - import_export_vtable (vars, ctype, 1); - - /* We cannot use TREE_USED here, as it may be set by the expanding of a - ctor that is used to build a global object. The long term plan is to - make the TD entries statically initialized and move this to - finish_vtable_vardecl time. */ - if (flag_rtti && write_virtuals >= 0 - && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || 1 || TREE_USED (vars))) + if (import_export) { - /* Kick out the type descriptor before we dump out global - initializers, as they are initialized at run time and - we have to find them when we scan for things that need initialized - at the top level. */ - build_t_desc (ctype, 1); + SET_CLASSTYPE_INTERFACE_KNOWN (ctype); + CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0); + CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0); } } -static void +static int finish_vtable_vardecl (prev, vars) tree prev, vars; { + 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) || TREE_USED (vars))) + && ! DECL_EXTERNAL (vars) + && ((TREE_PUBLIC (vars) && ! DECL_WEAK (vars) && ! DECL_ONE_ONLY (vars)) + || CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT (vars)) + || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)) + || (hack_decl_function_context (vars) && TREE_USED (vars))) + && ! TREE_ASM_WRITTEN (vars)) { -#if 0 - /* The long term plan it to make the TD entries statically initialized, - have the entries built and emitted here. When that happens, this - can be enabled, and the other call to build_t_desc removed. */ - /* Kick out the type descriptor before writing out the vtable. */ - if (flag_rtti) - build_t_desc (DECL_CONTEXT (vars), 1); -#endif - /* Write it out. */ mark_vtable_entries (vars); if (TREE_TYPE (DECL_INITIAL (vars)) == 0) store_init_value (vars, DECL_INITIAL (vars)); -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) + if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG) { /* Mark the VAR_DECL node representing the vtable itself as a "gratuitous" one, thereby forcing dwarfout.c to ignore it. @@ -2680,32 +2698,35 @@ finish_vtable_vardecl (prev, vars) DECL_IGNORED_P (vars) = 1; } -#endif /* DWARF_DEBUGGING_INFO */ rest_of_decl_compilation (vars, NULL_PTR, 1, 1); + return 1; } - else if (! TREE_USED (vars)) + else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))) /* We don't know what to do with this one yet. */ - return; + return 0; /* We know that PREV must be non-zero here. */ TREE_CHAIN (prev) = TREE_CHAIN (vars); + return 0; } -static void +static int prune_vtable_vardecl (prev, vars) tree prev, vars; { /* We know that PREV must be non-zero here. */ TREE_CHAIN (prev) = TREE_CHAIN (vars); + return 1; } -void +int walk_vtables (typedecl_fn, vardecl_fn) - register void (*typedecl_fn)(); - register void (*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)) { @@ -2713,7 +2734,8 @@ walk_vtables (typedecl_fn, vardecl_fn) if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars)) { - if (vardecl_fn) (*vardecl_fn) (prev, vars); + if (vardecl_fn) + flag |= (*vardecl_fn) (prev, vars); if (prev && TREE_CHAIN (prev) != vars) continue; @@ -2728,6 +2750,8 @@ walk_vtables (typedecl_fn, vardecl_fn) prev = vars; } + + return flag; } static void @@ -2746,8 +2770,8 @@ finish_sigtable_vardecl (prev, vars) void walk_sigtables (typedecl_fn, vardecl_fn) - register void (*typedecl_fn)(); - register void (*vardecl_fn)(); + register void (*typedecl_fn) PROTO((tree, tree)); + register void (*vardecl_fn) PROTO((tree, tree)); { tree prev, vars; @@ -2773,10 +2797,10 @@ walk_sigtables (typedecl_fn, vardecl_fn) } /* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an - inline function at end-of-file. */ + inline function or template instantiation at end-of-file. */ void -import_export_inline (decl) +import_export_decl (decl) tree decl; { if (DECL_INTERFACE_KNOWN (decl)) @@ -2784,12 +2808,18 @@ import_export_inline (decl) if (DECL_TEMPLATE_INSTANTIATION (decl)) { - if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates) + DECL_NOT_REALLY_EXTERN (decl) = 1; + if (DECL_IMPLICIT_INSTANTIATION (decl) + && (flag_implicit_templates || DECL_THIS_INLINE (decl))) { - if (SUPPORTS_WEAK) - DECL_WEAK (decl) = 1; + 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 - TREE_PUBLIC (decl) = 0; + DECL_COMDAT (decl) = 1; } else DECL_NOT_REALLY_EXTERN (decl) = 0; @@ -2797,31 +2827,307 @@ import_export_inline (decl) else if (DECL_FUNCTION_MEMBER_P (decl)) { tree ctype = DECL_CLASS_CONTEXT (decl); - if (CLASSTYPE_INTERFACE_KNOWN (ctype) && ! DECL_ARTIFICIAL (decl)) + import_export_class (ctype); + if (CLASSTYPE_INTERFACE_KNOWN (ctype) + && (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))) { DECL_NOT_REALLY_EXTERN (decl) = ! (CLASSTYPE_INTERFACE_ONLY (ctype) || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); } - else if (SUPPORTS_WEAK) - DECL_WEAK (decl) = 1; else - TREE_PUBLIC (decl) = 0; + comdat_linkage (decl); } - else if (DECL_C_STATIC (decl)) - TREE_PUBLIC (decl) = 0; - else if (SUPPORTS_WEAK) - DECL_WEAK (decl) = 1; + /* tinfo function */ + else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl)) + { + tree ctype = TREE_TYPE (DECL_NAME (decl)); + + if (IS_AGGR_TYPE (ctype)) + import_export_class (ctype); + + if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype) + && TYPE_VIRTUAL_P (ctype) + /* If the type is a cv-qualified variant of a type, then we + must emit the tinfo function in this translation unit + 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)) + { + DECL_NOT_REALLY_EXTERN (decl) + = ! (CLASSTYPE_INTERFACE_ONLY (ctype) + || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); + + /* For WIN32 we also want to put explicit instantiations in + linkonce sections. */ + if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype)) + maybe_make_one_only (decl); + } + else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype)) + DECL_NOT_REALLY_EXTERN (decl) = 0; + else + comdat_linkage (decl); + } else - TREE_PUBLIC (decl) = 0; + comdat_linkage (decl); DECL_INTERFACE_KNOWN (decl) = 1; } +tree +build_cleanup (decl) + tree decl; +{ + tree temp; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (type) == ARRAY_TYPE) + temp = decl; + else + { + mark_addressable (decl); + temp = build1 (ADDR_EXPR, build_pointer_type (type), decl); + } + temp = build_delete (TREE_TYPE (temp), temp, + integer_two_node, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); + return temp; +} + extern int parse_time, varconst_time; +extern tree pending_templates; +extern tree maybe_templates; + +static tree +get_sentry (base) + tree base; +{ + tree sname = get_id_2 ("__sn", base); + /* For struct X foo __attribute__((weak)), there is a counter + __snfoo. Since base is already an assembler name, sname should + be globally unique */ + tree sentry = IDENTIFIER_GLOBAL_VALUE (sname); + if (! sentry) + { + push_obstacks_nochange (); + end_temporary_allocation (); + sentry = build_decl (VAR_DECL, sname, integer_type_node); + TREE_PUBLIC (sentry) = 1; + DECL_ARTIFICIAL (sentry) = 1; + TREE_STATIC (sentry) = 1; + TREE_USED (sentry) = 1; + DECL_COMMON (sentry) = 1; + pushdecl_top_level (sentry); + cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0, 0); + pop_obstacks (); + } + return sentry; +} + +/* Start the process of running a particular set of global constructors + or destructors. Subroutine of do_[cd]tors. */ + +static void +start_objects (method_type) + int method_type; +{ + tree fnname; + + /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ + + fnname = get_file_function_name (method_type); + + start_function (void_list_node, + make_call_declarator (fnname, void_list_node, NULL_TREE, + NULL_TREE), + NULL_TREE, 0); + +#if defined(ASM_OUTPUT_CONSTRUCTOR) && defined(ASM_OUTPUT_DESTRUCTOR) + /* It can be a static function as long as collect2 does not have + to scan the object file to find its ctor/dtor routine. */ + TREE_PUBLIC (current_function_decl) = 0; +#endif + + store_parm_decls (); + pushlevel (0); + clear_last_expr (); + push_momentary (); + expand_start_bindings (0); +} + +/* 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; +{ + 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); + + /* Finish up. */ + expand_end_bindings (getdecls (), 1, 0); + poplevel (1, 0, 0); + pop_momentary (); + finish_function (lineno, 0, 0); + + if (method_type == 'I') + assemble_constructor (fnname); + else + assemble_destructor (fnname); +} + +/* Generate a function to run a set of global destructors. Subroutine of + finish_file. */ + +static void +do_dtors () +{ + tree vars = static_aggregates; + + for (; vars; vars = TREE_CHAIN (vars)) + { + tree decl = TREE_VALUE (vars); + tree type = TREE_TYPE (decl); + tree temp; + + 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))); + + if (! current_function_decl) + start_objects ('D'); + + temp = build_cleanup (decl); + + 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); + } + + expand_expr_stmt (temp); + + if (protect) + expand_end_cond (); + } + } + + finish_objects ('D'); +} + +/* Generate a function to run a set of global constructors. Subroutine of + finish_file. */ + +static void +do_ctors () +{ + tree vars = static_aggregates; -#define TIMEVAR(VAR, BODY) \ -do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0) + /* Reverse the list so it's in the right order for ctors. */ + vars = nreverse (vars); + + for (; vars; vars = TREE_CHAIN (vars)) + { + 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; + + 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; + } + + 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); + } + + expand_start_target_temps (); + + 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 (); + + /* Cleanup any temporaries needed for the initial value. */ + expand_end_target_temps (); + + if (protect) + expand_end_cond (); + + 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); + } + + finish_objects ('I'); +} /* This routine is called from the last rule in yyparse (). Its job is to create all the code needed to initialize and @@ -2838,18 +3144,15 @@ finish_file () tree vars; int needs_cleaning = 0, needs_messing_up = 0; - if (flag_detailed_statistics) - dump_tree_statistics (); + at_eof = 1; /* Bad parse errors. Just forget about it. */ if (! global_bindings_p () || current_class_type) return; - start_time = get_run_time (); + check_decl_namespace (); - /* Push into C language context, because that's all - we'll need here. */ - push_lang_context (lang_name_c); + start_time = get_run_time (); /* Otherwise, GDB can get confused, because in only knows about source for LINENO-1 lines. */ @@ -2858,6 +3161,45 @@ finish_file () interface_unknown = 1; interface_only = 0; + for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname)) + { + tree srcloc = TREE_PURPOSE (fnname); + tree decl = TREE_VALUE (fnname); + + input_filename = SRCLOC_FILE (srcloc); + lineno = SRCLOC_LINE (srcloc); + + 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); + } + + for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname)) + { + tree args, fn, decl = TREE_VALUE (fnname); + + if (DECL_INITIAL (decl)) + continue; + + fn = TREE_PURPOSE (fnname); + args = get_bindings (fn, decl, NULL_TREE); + fn = instantiate_template (fn, args); + instantiate_decl (fn); + } + + cat_namespace_levels(); + + /* Push into C language context, because that's all + we'll need here. */ + push_lang_context (lang_name_c); + #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 @@ -2870,7 +3212,7 @@ finish_file () 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. */ + 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 */ @@ -2883,199 +3225,28 @@ finish_file () pushdecl (vars); #endif - /* Walk to mark the inline functions we need, then output them so - that we can pick up any other tdecls that those routines need. */ - walk_vtables ((void (*)())0, finish_prevtable_vardecl); - + 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; - if (static_ctors || vars || might_have_exceptions_p ()) + if (static_ctors || vars) needs_messing_up = 1; - if (static_dtors) + if (static_dtors || vars) needs_cleaning = 1; - /* See if we really need the hassle. */ - while (vars && needs_cleaning == 0) - { - tree decl = TREE_VALUE (vars); - tree type = TREE_TYPE (decl); - if (TYPE_NEEDS_DESTRUCTOR (type)) - { - needs_cleaning = 1; - needs_messing_up = 1; - break; - } - else - needs_messing_up |= TYPE_NEEDS_CONSTRUCTING (type); - vars = TREE_CHAIN (vars); - } - - if (needs_cleaning == 0) - goto mess_up; - - fnname = get_file_function_name ('D'); - start_function (void_list_node, - build_parse_node (CALL_EXPR, fnname, void_list_node, - NULL_TREE), - NULL_TREE, NULL_TREE, 0); - fnname = DECL_ASSEMBLER_NAME (current_function_decl); - store_parm_decls (); - - pushlevel (0); - clear_last_expr (); - push_momentary (); - expand_start_bindings (0); - - /* These must be done in backward order to destroy, - in which they happen to be! */ - for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars)) + /* The aggregates are listed in reverse declaration order, for cleaning. */ + if (needs_cleaning) { - tree decl = TREE_VALUE (vars); - tree type = TREE_TYPE (decl); - tree temp = TREE_PURPOSE (vars); - - if (TYPE_NEEDS_DESTRUCTOR (type)) - { - if (TREE_STATIC (vars)) - expand_start_cond (build_binary_op (NE_EXPR, temp, integer_zero_node, 1), 0); - if (TREE_CODE (type) == ARRAY_TYPE) - temp = decl; - else - { - mark_addressable (decl); - temp = build1 (ADDR_EXPR, build_pointer_type (type), decl); - } - temp = build_delete (TREE_TYPE (temp), temp, - integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); - expand_expr_stmt (temp); - - if (TREE_STATIC (vars)) - expand_end_cond (); - } + do_dtors (); } - for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors)) - expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors), - NULL_TREE)); - - expand_end_bindings (getdecls(), 1, 0); - poplevel (1, 0, 0); - pop_momentary (); - - finish_function (lineno, 0, 0); - - assemble_destructor (IDENTIFIER_POINTER (fnname)); - - /* if it needed cleaning, then it will need messing up: drop through */ - - mess_up: - /* Must do this while we think we are at the top level. */ - vars = nreverse (static_aggregates); + /* do_ctors will reverse the lists for messing up. */ if (needs_messing_up) { - fnname = get_file_function_name ('I'); - start_function (void_list_node, - build_parse_node (CALL_EXPR, fnname, - void_list_node, NULL_TREE), - NULL_TREE, NULL_TREE, 0); - fnname = DECL_ASSEMBLER_NAME (current_function_decl); - store_parm_decls (); - - pushlevel (0); - clear_last_expr (); - push_momentary (); - expand_start_bindings (0); - - if (might_have_exceptions_p ()) - register_exception_table (); - - while (vars) - { - tree decl = TREE_VALUE (vars); - tree init = TREE_PURPOSE (vars); - tree old_cleanups = cleanups_this_call; - - /* 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) - || (init && TREE_CODE (init) == TREE_LIST - && value_member (error_mark_node, init))) - { - vars = TREE_CHAIN (vars); - continue; - } - - if (TREE_CODE (decl) == VAR_DECL) - { - /* 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. */ - DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl); - DECL_STATIC_FUNCTION_P (current_function_decl) = 1; - - 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, 0); - free_temp_slots (); - } - else - expand_assignment (decl, init, 0, 0); - - DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE; - } - else if (TREE_CODE (decl) == SAVE_EXPR) - { - if (! PARM_DECL_EXPR (decl)) - { - /* a `new' expression at top level. */ - expand_expr (decl, const0_rtx, VOIDmode, 0); - free_temp_slots (); - 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, 0); - free_temp_slots (); - } - else - expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0); - } - } - else if (decl == error_mark_node) - ; - else my_friendly_abort (22); - vars = TREE_CHAIN (vars); - /* Cleanup any temporaries needed for the initial value. */ - expand_cleanups_to (old_cleanups); - } - - for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors)) - expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors), - NULL_TREE)); - - expand_end_bindings (getdecls(), 1, 0); - poplevel (1, 0, 0); - pop_momentary (); - - finish_function (lineno, 0, 0); - assemble_constructor (IDENTIFIER_POINTER (fnname)); + do_ctors (); } - expand_builtin_throw (); - permanent_allocation (1); /* Done with C language context needs. */ @@ -3086,10 +3257,21 @@ finish_file () while (pending_statics) { tree decl = TREE_VALUE (pending_statics); - if (TREE_USED (decl) == 1 - || TREE_READONLY (decl) == 0 - || DECL_INITIAL (decl) == 0) - rest_of_decl_compilation (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1); + + /* 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 + + DECL_DEFER_OUTPUT (decl) = 0; + rest_of_decl_compilation + (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1); + pending_statics = TREE_CHAIN (pending_statics); } @@ -3100,18 +3282,17 @@ finish_file () start_time = get_run_time (); if (flag_handle_signatures) - walk_sigtables ((void (*)())0, finish_sigtable_vardecl); + walk_sigtables ((void (*) PROTO ((tree, tree))) 0, + finish_sigtable_vardecl); for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname)) { tree decl = TREE_VALUE (fnname); - import_export_inline (decl); - if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) - && TREE_PUBLIC (decl) && ! DECL_WEAK (decl) - && DECL_NOT_REALLY_EXTERN (decl)) - synthesize_method (decl); + import_export_decl (decl); } + mark_all_runtime_matches (); + /* Now write out inline functions which had their addresses taken and which were not declared virtual and which were not declared `extern inline'. */ @@ -3120,87 +3301,92 @@ finish_file () while (reconsider) { - tree last = saved_inlines = tree_cons (NULL_TREE, NULL_TREE, - saved_inlines); - tree last_head = last; - tree place = TREE_CHAIN (saved_inlines); + tree *p = &saved_inlines; reconsider = 0; - walk_vtables ((void (*)())0, finish_vtable_vardecl); + /* 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); + + reconsider |= walk_vtables ((void (*) PROTO((tree, tree))) 0, + finish_vtable_vardecl); - for (; place; place = TREE_CHAIN (place)) + while (*p) { - tree decl = TREE_VALUE (place); + tree decl = TREE_VALUE (*p); - /* Slice out the empty elements put in just above in the - previous reconsidering. */ - if (decl == NULL_TREE) + if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) + && TREE_USED (decl) + && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) { - TREE_CHAIN (last) = TREE_CHAIN (place); - continue; - } - - if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)) - { - if (TREE_USED (decl)) - { - synthesize_method (decl); - if (TREE_ASM_WRITTEN (decl)) - reconsider = 1; - } + if (DECL_MUTABLE_P (decl)) + synthesize_tinfo_fn (decl); else - { - last = place; - continue; - } + synthesize_method (decl); + reconsider = 1; } - if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0) - { - TREE_CHAIN (last) = TREE_CHAIN (place); - continue; - } + /* Catch new template instantiations. */ + if (decl != TREE_VALUE (*p)) + continue; - if ((TREE_PUBLIC (decl) && ! DECL_WEAK (decl)) - || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) - || flag_keep_inline_functions) + 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) { - TREE_CHAIN (last) = TREE_CHAIN (place); - if (DECL_NOT_REALLY_EXTERN (decl)) { DECL_EXTERNAL (decl) = 0; reconsider = 1; - temporary_allocation (); + /* 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); } - continue; + *p = TREE_CHAIN (*p); } - - last = place; + else + p = &TREE_CHAIN (*p); } } + + /* 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. + + 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); + + if (DECL_NOT_REALLY_EXTERN (decl) + && !DECL_COMDAT (decl) + && DECL_INITIAL (decl) != NULL_TREE) + DECL_EXTERNAL (decl) = 0; + } } /* Now delete from the chain of variables all virtual function tables. We output them all ourselves, because each will be treated specially. */ - walk_vtables ((void (*)())0, prune_vtable_vardecl); - - for (vars = getdecls (); vars; vars = TREE_CHAIN (vars)) - { - if (TREE_CODE (vars) == THUNK_DECL) - emit_thunk (vars); - else if (TREE_CODE (vars) == FUNCTION_DECL - && ! DECL_INTERFACE_KNOWN (vars) - && DECL_C_STATIC (vars)) - TREE_PUBLIC (vars) = 0; - } - - if (might_have_exceptions_p ()) - emit_exception_table (); + walk_vtables ((void (*) PROTO((tree, tree))) 0, + prune_vtable_vardecl); if (write_virtuals == 2) { @@ -3222,7 +3408,10 @@ finish_file () varconst_time += this_time - start_time; if (flag_detailed_statistics) - dump_time_statistics (); + { + dump_tree_statistics (); + dump_time_statistics (); + } } /* This is something of the form 'A()()()()()+1' that has turned out to be an @@ -3233,6 +3422,7 @@ finish_file () Maybe this shouldn't be recursive, but how often will it actually be used? (jason) */ + tree reparse_absdcl_as_expr (type, decl) tree type, decl; @@ -3244,7 +3434,7 @@ reparse_absdcl_as_expr (type, decl) /* recurse */ decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0)); - decl = build_x_function_call (decl, NULL_TREE, current_class_decl); + decl = build_x_function_call (decl, NULL_TREE, current_class_ref); if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node) decl = require_complete_type (decl); @@ -3259,13 +3449,15 @@ reparse_absdcl_as_expr (type, decl) In the above example, DECL is the `(int)(int)(int)', and EXPR is the `1'. */ + tree reparse_absdcl_as_casts (decl, expr) tree decl, expr; { tree type; - if (TREE_CODE (expr) == CONSTRUCTOR) + if (TREE_CODE (expr) == CONSTRUCTOR + && TREE_TYPE (expr) == 0) { type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); decl = TREE_OPERAND (decl, 0); @@ -3289,62 +3481,298 @@ reparse_absdcl_as_casts (decl, expr) { type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); decl = TREE_OPERAND (decl, 0); - expr = build_c_cast (type, expr, 0); + expr = build_c_cast (type, expr); } + if (warn_old_style_cast) + warning ("use of old-style cast"); + return expr; } -/* Recursive helper function for reparse_decl_as_expr. It may be a good - idea to reimplement this using an explicit stack, rather than recursion. */ -static tree -reparse_decl_as_expr1 (decl) - tree decl; +/* Given plain tree nodes for an expression, build up the full semantics. */ + +tree +build_expr_from_tree (t) + tree t; { - switch (TREE_CODE (decl)) + if (t == NULL_TREE || t == error_mark_node) + return t; + + switch (TREE_CODE (t)) { case IDENTIFIER_NODE: - return do_identifier (decl); + return do_identifier (t, 0, NULL_TREE); + + case LOOKUP_EXPR: + if (LOOKUP_EXPR_GLOBAL (t)) + return do_scoped_id (TREE_OPERAND (t, 0), 0); + else + return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE); + + case TEMPLATE_ID_EXPR: + return (lookup_template_function + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)))); + case INDIRECT_REF: return build_x_indirect_ref - (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), "unary *"); - case ADDR_EXPR: - return build_x_unary_op (ADDR_EXPR, - reparse_decl_as_expr1 (TREE_OPERAND (decl, 0))); + (build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *"); + + case CAST_EXPR: + return build_functional_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case REINTERPRET_CAST_EXPR: + return build_reinterpret_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case CONST_CAST_EXPR: + return build_const_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case DYNAMIC_CAST_EXPR: + return build_dynamic_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case STATIC_CAST_EXPR: + return build_static_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case NEGATE_EXPR: case BIT_NOT_EXPR: - return build_x_unary_op (BIT_NOT_EXPR, - reparse_decl_as_expr1 (TREE_OPERAND (decl, 0))); + case ABS_EXPR: + case TRUTH_NOT_EXPR: + case ADDR_EXPR: + case CONVERT_EXPR: /* Unary + */ + if (TREE_TYPE (t)) + return t; + return build_x_unary_op (TREE_CODE (t), + build_expr_from_tree (TREE_OPERAND (t, 0))); + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + case BIT_AND_EXPR: + case BIT_ANDTC_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case RSHIFT_EXPR: + case LSHIFT_EXPR: + case RROTATE_EXPR: + case LROTATE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + case MEMBER_REF: + return build_x_binary_op + (TREE_CODE (t), + build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1))); + + case DOTSTAR_EXPR: + return build_m_component_ref + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1))); + case SCOPE_REF: - return build_offset_ref (TREE_OPERAND (decl, 0), TREE_OPERAND (decl, 1)); + return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)); + case ARRAY_REF: - return grok_array_decl (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), - TREE_OPERAND (decl, 1)); + if (TREE_OPERAND (t, 0) == NULL_TREE) + /* new-type-id */ + return build_parse_node (ARRAY_REF, NULL_TREE, + build_expr_from_tree (TREE_OPERAND (t, 1))); + return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1))); + + case SIZEOF_EXPR: + case ALIGNOF_EXPR: + { + tree r = build_expr_from_tree (TREE_OPERAND (t, 0)); + if (TREE_CODE_CLASS (TREE_CODE (r)) != 't') + r = TREE_TYPE (r); + return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r); + } + + case MODOP_EXPR: + return build_x_modify_expr + (build_expr_from_tree (TREE_OPERAND (t, 0)), + TREE_CODE (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (t, 2))); + + case ARROW_EXPR: + return build_x_arrow + (build_expr_from_tree (TREE_OPERAND (t, 0))); + + case NEW_EXPR: + return build_new + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (t, 2)), + NEW_EXPR_USE_GLOBAL (t)); + + case DELETE_EXPR: + return delete_sanity + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)), + DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t)); + + case COMPOUND_EXPR: + if (TREE_OPERAND (t, 1) == NULL_TREE) + return build_x_compound_expr + (build_expr_from_tree (TREE_OPERAND (t, 0))); + else + my_friendly_abort (42); + + case METHOD_CALL_EXPR: + if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF) + { + tree ref = TREE_OPERAND (t, 0); + return build_scoped_method_call + (build_expr_from_tree (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (ref, 0)), + 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); + + case CALL_EXPR: + if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF) + { + tree ref = TREE_OPERAND (t, 0); + return build_member_call + (build_expr_from_tree (TREE_OPERAND (ref, 0)), + TREE_OPERAND (ref, 1), + build_expr_from_tree (TREE_OPERAND (t, 1))); + } + else + { + tree name = TREE_OPERAND (t, 0); + tree id; + tree args = build_expr_from_tree (TREE_OPERAND (t, 1)); + if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR + && !LOOKUP_EXPR_GLOBAL (name) + && TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE + && (!current_class_type + || !lookup_member (current_class_type, id, 0, 0))) + { + /* Do Koenig lookup if there are no class members. */ + name = do_identifier (id, 0, args); + } + else if (TREE_CODE (name) == TEMPLATE_ID_EXPR + || ! really_overloaded_fn (name)) + name = build_expr_from_tree (name); + return build_x_function_call (name, args, current_class_ref); + } + + case COND_EXPR: + return build_x_conditional_expr + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (t, 2))); + + case TREE_LIST: + { + tree purpose, value, chain; + + if (t == void_list_node) + return t; + + purpose = TREE_PURPOSE (t); + if (purpose) + purpose = build_expr_from_tree (purpose); + value = TREE_VALUE (t); + if (value) + value = build_expr_from_tree (value); + chain = TREE_CHAIN (t); + if (chain && chain != void_type_node) + chain = build_expr_from_tree (chain); + return expr_tree_cons (purpose, value, chain); + } + + case COMPONENT_REF: + return build_x_component_ref + (build_expr_from_tree (TREE_OPERAND (t, 0)), + TREE_OPERAND (t, 1), NULL_TREE, 1); + + case THROW_EXPR: + return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0))); + + case CONSTRUCTOR: + { + tree r; + + /* digest_init will do the wrong thing if we let it. */ + if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) + return t; + + r = build_nt (CONSTRUCTOR, NULL_TREE, + build_expr_from_tree (CONSTRUCTOR_ELTS (t))); + + if (TREE_TYPE (t)) + return digest_init (TREE_TYPE (t), r, 0); + return r; + } + + case TYPEID_EXPR: + if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't') + return get_typeid (TREE_OPERAND (t, 0)); + return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0))); + + case VAR_DECL: + return convert_from_reference (t); + default: - my_friendly_abort (5); - return NULL_TREE; + return t; } } /* This is something of the form `int (*a)++' that has turned out to be an expr. It was only converted into parse nodes, so we need to go through and build up the semantics. Most of the work is done by - reparse_decl_as_expr1, above. + build_expr_from_tree, above. In the above example, TYPE is `int' and DECL is `*a'. */ + tree reparse_decl_as_expr (type, decl) tree type, decl; { - decl = reparse_decl_as_expr1 (decl); + decl = build_expr_from_tree (decl); if (type) - return build_functional_cast (type, build_tree_list (NULL_TREE, decl)); + return build_functional_cast (type, build_expr_list (NULL_TREE, decl)); else return decl; } /* This is something of the form `int (*a)' that has turned out to be a decl. It was only converted into parse nodes, so we need to do the - checking that make_{pointer,reference}_declarator do. */ + checking that make_{pointer,reference}_declarator do. */ tree finish_decl_parsing (decl) @@ -3385,20 +3813,13 @@ check_cp_case_value (value) if (value == NULL_TREE) return value; - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value) == NOP_EXPR - && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) - value = TREE_OPERAND (value, 0); + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + STRIP_TYPE_NOPS (value); if (TREE_READONLY_DECL_P (value)) { value = decl_constant_value (value); - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value) == NOP_EXPR - && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) - value = TREE_OPERAND (value, 0); + STRIP_TYPE_NOPS (value); } value = fold (value); @@ -3418,81 +3839,832 @@ check_cp_case_value (value) return value; } -tree current_namespace; +/* Return 1 if root encloses child. */ -/* Get the inner part of a namespace id. It doesn't have any prefix, nor - postfix. Returns 0 if in global namespace. */ -tree -get_namespace_id () +static int +is_namespace_ancestor (root, child) + tree root, child; { - tree x = current_namespace; - if (x) - x = TREE_PURPOSE (x); - return x; + if (root == child) + return 1; + if (root == global_namespace) + return 1; + if (child == global_namespace) + return 0; + return is_namespace_ancestor (root, CP_DECL_CONTEXT (child)); } + + +/* Return the namespace that is the common ancestor + of two given namespaces. */ -/* Build up a DECL_ASSEMBLER_NAME for NAME in the current namespace. */ tree -current_namespace_id (name) +namespace_ancestor (ns1, ns2) + tree ns1, ns2; +{ + if (is_namespace_ancestor (ns1, ns2)) + return ns1; + return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2); +} + +/* Insert used into the using list of user. Set indirect_flag if this + directive is not directly from the source. Also find the common + ancestor and let our users know about the new namespace */ +static void +add_using_namespace (user, used, indirect) + tree user; + tree used; + int indirect; +{ + tree t; + /* Using oneself is a no-op. */ + if (user == used) + return; + my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380); + my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380); + /* Check if we already have this. */ + t = purpose_member (used, DECL_NAMESPACE_USING (user)); + if (t != NULL_TREE) + { + if (!indirect) + /* Promote to direct usage. */ + TREE_INDIRECT_USING (t) = 0; + return; + } + + /* Add used to the user's using list. */ + DECL_NAMESPACE_USING (user) + = perm_tree_cons (used, namespace_ancestor (user, used), + DECL_NAMESPACE_USING (user)); + + TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect; + + /* Add user to the used's users list. */ + DECL_NAMESPACE_USERS (used) + = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used)); + + /* Recursively add all namespaces used. */ + for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t)) + /* indirect usage */ + add_using_namespace (user, TREE_PURPOSE (t), 1); + + /* Tell everyone using us about the new used namespaces. */ + for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) + add_using_namespace (TREE_PURPOSE (t), used, 1); +} + +/* 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). */ + +static tree +merge_functions (s1, s2) + tree s1; + tree s2; +{ + for (; s2; s2 = OVL_NEXT (s2)) + { + tree fn = OVL_CURRENT (s2); + if (! ovl_member (fn, s1)) + s1 = build_overload (fn, s1); + } + return s1; +} + +/* This should return an error not all definitions define functions. + It is not an error if we find two functions with exactly the + same signature, only if these are selected in overload resolution. + old is the current set of bindings, new the freshly-found binding. + XXX Do we want to give *all* candidates in case of ambiguity? + XXX In what way should I treat extern declarations? + XXX I don't want to repeat the entire duplicate_decls here */ + +static tree +ambiguous_decl (name, old, new, flags) + tree name; + tree old; + tree new; + int flags; +{ + tree val, type; + my_friendly_assert (old != NULL_TREE, 393); + /* Copy the value. */ + val = BINDING_VALUE (new); + if (val) + switch (TREE_CODE (val)) + { + case TEMPLATE_DECL: + /* 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))) + val = NULL_TREE; + break; + case TYPE_DECL: + if (LOOKUP_NAMESPACES_ONLY (flags)) + val = NULL_TREE; + break; + case NAMESPACE_DECL: + if (LOOKUP_TYPES_ONLY (flags)) + val = NULL_TREE; + break; + default: + if (LOOKUP_QUALIFIERS_ONLY (flags)) + val = NULL_TREE; + } + + if (!BINDING_VALUE (old)) + BINDING_VALUE (old) = val; + else if (val && val != BINDING_VALUE (old)) + { + if (is_overloaded_fn (BINDING_VALUE (old)) + && is_overloaded_fn (val)) + { + BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old), + val); + } + else + { + /* 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)); + cp_error_at (" also declared as `%#D' here", val); + } + return error_mark_node; + } + } + /* ... and copy the type. */ + type = BINDING_TYPE (new); + if (LOOKUP_NAMESPACES_ONLY (flags)) + type = NULL_TREE; + if (!BINDING_TYPE (old)) + BINDING_TYPE (old) = type; + else if (type && BINDING_TYPE (old) != type) + { + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("`%D' denotes an ambiguous type",name); + cp_error_at (" first type here", BINDING_TYPE (old)); + cp_error_at (" other type here", type); + } + } + return old; +} + +/* Add the bindings of name in used namespaces to val. + The using list is defined by usings, and the lookup goes to scope. + Returns zero on errors. */ + +int +lookup_using_namespace (name, val, usings, scope, flags) + tree name, val, usings, scope; + int flags; +{ + tree iter; + tree val1; + /* Iterate over all used namespaces in current, searching for using + directives of scope. */ + for (iter = usings; iter; iter = TREE_CHAIN (iter)) + if (TREE_VALUE (iter) == scope) + { + val1 = binding_for_name (name, TREE_PURPOSE (iter)); + /* Resolve ambiguities. */ + val = ambiguous_decl (name, val, val1, flags); + } + return val != error_mark_node; +} + +/* [namespace.qual] + Excepts the name to lookup and its qualifying scope. + Returns the name/type pair found into the CPLUS_BINDING result, + or 0 on error. */ + +int +qualified_lookup_using_namespace (name, scope, result, flags) tree name; + tree scope; + tree result; + int flags; +{ + /* Maintain a list of namespaces visited... */ + tree seen = NULL_TREE; + /* ... and a list of namespace yet to see. */ + tree todo = NULL_TREE; + tree usings; + while (scope && (result != error_mark_node)) + { + seen = temp_tree_cons (scope, NULL_TREE, seen); + result = ambiguous_decl (name, result, + binding_for_name (name, scope), flags); + if (!BINDING_VALUE (result) && !BINDING_TYPE (result)) + /* Consider using directives. */ + for (usings = DECL_NAMESPACE_USING (scope); usings; + usings = TREE_CHAIN (usings)) + /* If this was a real directive, and we have not seen it. */ + if (!TREE_INDIRECT_USING (usings) + && !purpose_member (TREE_PURPOSE (usings), seen)) + todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo); + if (todo) + { + scope = TREE_PURPOSE (todo); + todo = TREE_CHAIN (todo); + } + else + scope = NULL_TREE; /* If there never was a todo list. */ + } + return result != error_mark_node; +} + +/* [namespace.memdef]/2 */ + +/* Set the context of a declaration to scope. Complain if we are not + outside scope. */ + +void +set_decl_namespace (decl, scope) + tree decl; + tree scope; +{ + tree old; + if (scope == std_node) + scope = global_namespace; + /* Get rid of namespace aliases. */ + scope = ORIGINAL_NAMESPACE (scope); + + if (!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); + if (scope != current_namespace) + { + /* See whether this has been declared in the namespace. */ + old = namespace_binding (DECL_NAME (decl), scope); + if (!old) + /* No old declaration at all. */ + goto complain; + if (!is_overloaded_fn (decl)) + /* Don't compare non-function decls with decls_match here, + since it can't check for the correct constness at this + point. pushdecl will find those errors later. */ + return; + /* Since decl is a function, old should contain a function decl. */ + if (!is_overloaded_fn (old)) + goto complain; + for (; old; old = OVL_NEXT (old)) + if (decls_match (decl, OVL_CURRENT (old))) + return; + } + else + return; + complain: + cp_error ("`%D' should have been declared inside `%D'", + decl, scope); +} + +/* Compute the namespace where a declaration is defined. */ + +tree +decl_namespace (decl) + tree decl; +{ + while (DECL_CONTEXT (decl)) + { + decl = DECL_CONTEXT (decl); + if (TREE_CODE (decl) == NAMESPACE_DECL) + return decl; + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') + decl = TYPE_STUB_DECL (decl); + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 390); + } + + return global_namespace; +} + +/* Return the namespace where the current declaration is declared. */ + +tree +current_decl_namespace () +{ + tree result; + /* If we have been pushed into a different namespace, use it. */ + if (decl_namespace_list) + return TREE_PURPOSE (decl_namespace_list); + + if (current_class_type) + result = decl_namespace (TYPE_STUB_DECL (current_class_type)); + else if (current_function_decl) + result = decl_namespace (current_function_decl); + else + result = current_namespace; + return result; +} + +/* Temporarily set the namespace for the current declaration. */ + +void +push_decl_namespace (decl) + tree decl; +{ + if (TREE_CODE (decl) != NAMESPACE_DECL) + decl = decl_namespace (decl); + decl_namespace_list = tree_cons (decl, NULL_TREE, decl_namespace_list); +} + +void +pop_decl_namespace () +{ + decl_namespace_list = TREE_CHAIN (decl_namespace_list); +} + +static void +check_decl_namespace () { - tree old_id = get_namespace_id (); - char *buf; + my_friendly_assert (decl_namespace_list == NULL_TREE, 980711); +} + +/* [basic.lookup.koenig] */ +/* A non-zero return value in the functions below indicates an error. + All nodes allocated in the procedure are on the scratch obstack. */ + +struct arg_lookup +{ + tree name; + tree namespaces; + tree classes; + tree functions; +}; + +static int arg_assoc PROTO((struct arg_lookup*, tree)); +static int arg_assoc_args PROTO((struct arg_lookup*, tree)); + +/* Add a function to the lookup structure. + Returns 1 on error. */ + +static int +add_function (k, fn) + struct arg_lookup *k; + tree fn; +{ + if (ovl_member (fn, k->functions)) + return 0; + /* We must find only functions, or exactly one non-function. */ + if (k->functions && is_overloaded_fn (k->functions) + && is_overloaded_fn (fn)) + k->functions = build_overload (fn, k->functions); + else + if(k->functions) + { + tree f1 = OVL_CURRENT (k->functions); + tree f2 = fn; + if (is_overloaded_fn (f1)) + { + fn = f1; f1 = f2; f2 = fn; + } + cp_error_at ("`%D' is not a function,", f1); + cp_error_at (" conflict with `%D'", f2); + cp_error (" in call to `%D'", k->name); + return 1; + } + else + k->functions = fn; + return 0; +} + +/* Add functions of a namespace to the lookup structure. + Returns 1 on error. */ + +static int +arg_assoc_namespace (k, scope) + struct arg_lookup *k; + tree scope; +{ + tree value; + + if (purpose_member (scope, k->namespaces)) + return 0; + k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces); + + value = namespace_binding (k->name, scope); + if (!value) + return 0; + + for (; value; value = OVL_NEXT (value)) + if (add_function (k, OVL_CURRENT (value))) + return 1; + + return 0; +} + +/* Adds everything associated with class to the lookup structure. + Returns 1 on error. */ + +static int +arg_assoc_class (k, type) + struct arg_lookup* k; + tree type; +{ + tree list, friends, context; + int i; + + if (purpose_member (type, k->classes)) + return 0; + k->classes = tree_cons (type, NULL_TREE, k->classes); + + context = decl_namespace (TYPE_MAIN_DECL (type)); + if (arg_assoc_namespace (k, context)) + return 1; + + /* Process baseclasses. */ + for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++) + if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i))) + return 1; + + /* Process friends. */ + for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; + list = TREE_CHAIN (list)) + if (k->name == TREE_PURPOSE (list)) + for (friends = TREE_VALUE (list); friends; + friends = TREE_CHAIN (friends)) + /* Only interested in global functions with potentially hidden + (i.e. unqualified) declarations. */ + if (TREE_PURPOSE (list) == error_mark_node && TREE_VALUE (list) + && decl_namespace (TREE_VALUE (list)) == context) + if (add_function (k, TREE_VALUE (list))) + return 1; + + /* Process template arguments. */ + if (CLASSTYPE_TEMPLATE_INFO (type)) + { + list = innermost_args (CLASSTYPE_TI_ARGS (type), 0); + for (i = 0; i < TREE_VEC_LENGTH (list); ++i) + arg_assoc (k, TREE_VEC_ELT (list, i)); + } + + return 0; +} + +/* Adds everything associated with a given type. + Returns 1 on error. */ + +static int +arg_assoc_type (k, type) + struct arg_lookup *k; + tree type; +{ + switch (TREE_CODE (type)) + { + case VOID_TYPE: + case INTEGER_TYPE: + case REAL_TYPE: + case COMPLEX_TYPE: + case CHAR_TYPE: + case BOOLEAN_TYPE: + return 0; + case RECORD_TYPE: + if (TYPE_PTRMEMFUNC_P (type)) + return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type)); + return arg_assoc_class (k, type); + case POINTER_TYPE: + case REFERENCE_TYPE: + case ARRAY_TYPE: + return arg_assoc_type (k, TREE_TYPE (type)); + case UNION_TYPE: + case ENUMERAL_TYPE: + return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type))); + case OFFSET_TYPE: + /* Pointer to member: associate class type and value type. */ + if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type))) + return 1; + return arg_assoc_type (k, TREE_TYPE (type)); + case METHOD_TYPE: + /* The basetype is referenced in the first arg type, so just + fall through. */ + case FUNCTION_TYPE: + /* Associate the parameter types. */ + if (arg_assoc_args (k, TYPE_ARG_TYPES (type))) + return 1; + /* Associate the return type. */ + return arg_assoc_type (k, TREE_TYPE (type)); + case TEMPLATE_TYPE_PARM: + return 0; + case LANG_TYPE: + if (type == unknown_type_node) + return 0; + /* else fall through */ + default: + my_friendly_abort (390); + } + return 0; +} - /* Global names retain old encoding. */ - if (! old_id) - return name; +/* Adds everything associated with arguments. Returns 1 on error. */ - buf = (char *) alloca (8 + IDENTIFIER_LENGTH (old_id) - + IDENTIFIER_LENGTH (name)); - sprintf (buf, "__ns_%s_%s", IDENTIFIER_POINTER (old_id), - IDENTIFIER_POINTER (name)); - return get_identifier (buf); +static int +arg_assoc_args (k, args) + struct arg_lookup* k; + tree args; +{ + for (; args; args = TREE_CHAIN (args)) + if (arg_assoc (k, TREE_VALUE (args))) + return 1; + return 0; } +/* Adds everything associated with a given tree_node. Returns 1 on error. */ + +static int +arg_assoc (k, n) + struct arg_lookup* k; + tree n; +{ + if (n == error_mark_node) + return 0; + + if (TREE_CODE_CLASS (TREE_CODE (n)) == 't') + return arg_assoc_type (k, n); + + if (! type_unknown_p (n)) + return arg_assoc_type (k, TREE_TYPE (n)); + + if (TREE_CODE (n) == ADDR_EXPR) + n = TREE_OPERAND (n, 0); + while (TREE_CODE (n) == TREE_LIST) + n = TREE_VALUE (n); + + my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715); + + for (; n; n = TREE_CHAIN (n)) + if (arg_assoc (k, OVL_FUNCTION (n))) + return 1; + + return 0; +} + +/* Performs Koenig lookup depending on arguments, where fns + are the functions found in normal lookup. */ + +tree +lookup_arg_dependent (name, fns, args) + tree name; + tree fns; + tree args; +{ + struct arg_lookup k; + k.name = name; + k.functions = fns; + k.namespaces = NULL_TREE; + k.classes = NULL_TREE; + + push_scratch_obstack (); + arg_assoc_args (&k, args); + pop_obstacks (); + return k.functions; +} + +/* Process a namespace-alias declaration. */ + 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. */ + cp_error ("unknown namespace `%D'", namespace); + return; + } + + namespace = ORIGINAL_NAMESPACE (namespace); + + /* Build the alias. */ + alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); + DECL_NAMESPACE_ALIAS (alias) = namespace; + pushdecl (alias); } -tree -do_toplevel_using_decl (decl) +/* Check a non-member using-declaration. Return the name and scope + being used, and the USING_DECL, or NULL_TREE on failure. */ + +static tree +validate_nonmember_using_decl (decl, scope, name) tree decl; + tree *scope; + tree *name; { - if (decl == NULL_TREE || decl == error_mark_node) + if (TREE_CODE (decl) == SCOPE_REF + && TREE_OPERAND (decl, 0) == std_node) + { + *scope = global_namespace; + *name = TREE_OPERAND (decl, 1); + } + else if (TREE_CODE (decl) == SCOPE_REF) + { + *scope = TREE_OPERAND (decl, 0); + *name = TREE_OPERAND (decl, 1); + } + else if (TREE_CODE (decl) == IDENTIFIER_NODE + || TREE_CODE (decl) == TYPE_DECL) + { + *scope = global_namespace; + *name = decl; + } + else + my_friendly_abort (382); + if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd') + *name = DECL_NAME (*name); + /* Make a USING_DECL. */ + return push_using_decl (*scope, *name); +} + +/* Process local and global using-declarations. */ + +static void +do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) + tree scope, name; + tree oldval, oldtype; + tree *newval, *newtype; +{ + tree decls; + struct tree_binding _decls; + + *newval = *newtype = NULL_TREE; + decls = binding_init (&_decls); + if (!qualified_lookup_using_namespace (name, scope, decls, 0)) + /* Lookup error */ return; - if (TREE_CODE (decl) == SCOPE_REF) - decl = resolve_scope_to_name (NULL_TREE, decl); + if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls)) + { + cp_error ("`%D' not declared", name); + return; + } - /* Is this the right way to do an id list? */ - if (TREE_CODE (decl) != TREE_LIST) + /* Check for using functions. */ + if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls))) { - pushdecl (decl); + tree tmp, tmp1; + + if (oldval && !is_overloaded_fn (oldval)) + { + duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval); + oldval = NULL_TREE; + } + + *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. */ + 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; + + /* Duplicate use, ignore */ + if (tmp1) + continue; + + *newval = build_overload (OVL_CURRENT (tmp), *newval); + if (TREE_CODE (*newval) != OVERLOAD) + *newval = ovl_cons (*newval, NULL_TREE); + OVL_USED (*newval) = 1; + } } - else - while (decl) - { - pushdecl (TREE_VALUE (decl)); - decl = TREE_CHAIN (decl); - } + else + { + *newval = BINDING_VALUE (decls); + if (oldval) + duplicate_decls (*newval, oldval); + } + + *newtype = BINDING_TYPE (decls); + if (oldtype && *newtype && oldtype != *newtype) + { + cp_error ("using directive `%D' introduced ambiguous type `%T'", + name, oldtype); + return; + } +} + +/* Process a using-declaration not appearing in class or local scope. */ + +void +do_toplevel_using_decl (decl) + tree decl; +{ + tree scope, name, binding; + tree oldval, oldtype, newval, newtype; + + decl = validate_nonmember_using_decl (decl, &scope, &name); + if (decl == NULL_TREE) + return; + + binding = binding_for_name (name, current_namespace); + + oldval = BINDING_VALUE (binding); + oldtype = BINDING_TYPE (binding); + + do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); + + /* Copy declarations found. */ + if (newval) + BINDING_VALUE (binding) = newval; + if (newtype) + BINDING_TYPE (binding) = newtype; + return; +} + +/* Process a using-declaration at function scope. */ + +void +do_local_using_decl (decl) + tree decl; +{ + tree scope, name; + tree oldval, oldtype, newval, newtype; + + decl = validate_nonmember_using_decl (decl, &scope, &name); + if (decl == NULL_TREE) + return; + + oldval = lookup_name_current_level (name); + oldtype = lookup_type_current_level (name); + + do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); + + if (newval) + set_identifier_local_value (name, newval); + if (newtype) + set_identifier_type_value (name, newtype); } tree do_class_using_decl (decl) tree decl; { - tree type; + tree name, value; - /* Ignore for now, unimplemented. */ - return NULL_TREE; + if (TREE_CODE (decl) != SCOPE_REF + || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (decl, 0))) != 't') + { + cp_error ("using-declaration for non-member at class scope"); + return NULL_TREE; + } + name = TREE_OPERAND (decl, 1); + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + cp_error ("using-declaration for destructor"); + return NULL_TREE; + } + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716); + + value = build_lang_field_decl (USING_DECL, name, void_type_node); + DECL_INITIAL (value) = TREE_OPERAND (decl, 0); + return value; } +/* Process a using-directive. */ + void do_using_directive (namespace) tree namespace; { + if (namespace == std_node) + return; + /* using namespace A::B::C; */ + if (TREE_CODE (namespace) == SCOPE_REF) + namespace = TREE_OPERAND (namespace, 1); + if (TREE_CODE (namespace) == IDENTIFIER_NODE) + { + /* Lookup in lexer did not find a namespace. */ + cp_error ("namespace `%T' undeclared", namespace); + return; + } + if (TREE_CODE (namespace) != NAMESPACE_DECL) + { + cp_error ("`%T' is not a namespace", namespace); + return; + } + namespace = ORIGINAL_NAMESPACE (namespace); + if (!toplevel_bindings_p ()) + push_using_directive (namespace); + else + /* direct usage */ + add_using_namespace (current_namespace, namespace, 0); } void @@ -3507,9 +4679,46 @@ check_default_args (x) saw_def = 1; else if (saw_def) { - cp_error ("default argument missing for parameter %P of `%#D'", - i, x); + cp_error_at ("default argument missing for parameter %P of `%+#D'", + i, x); break; } } } + +void +mark_used (decl) + tree decl; +{ + TREE_USED (decl) = 1; + 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)) + instantiate_decl (decl); +} + +/* Helper function for named_class_head_sans_basetype nonterminal. */ + +tree +handle_class_head (aggr, scope, id) + tree aggr, scope, id; +{ + if (TREE_CODE (id) == TYPE_DECL) + return id; + + 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); + + id = xref_tag + (aggr, make_anon_name (), NULL_TREE, 1); + return TYPE_MAIN_DECL (id); +} diff --git a/contrib/gcc/cp/errfn.c b/contrib/gcc/cp/errfn.c index 4da07fa..8d20682 100644 --- a/contrib/gcc/cp/errfn.c +++ b/contrib/gcc/cp/errfn.c @@ -20,16 +20,22 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "tree.h" -#include -#include +#include "toplev.h" + +#ifdef __STDC__ +#include +#else +#include +#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 the char*s returned. See error.c for an example use of this code. */ -typedef char* cp_printer PROTO((HOST_WIDE_INT, int)); +typedef char* cp_printer PROTO((tree, int)); extern cp_printer * cp_printers[256]; /* Whether or not we should try to be quiet for errors and warnings; this is @@ -44,187 +50,235 @@ extern int cp_line_of PROTO((tree)); #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap) -#define NARGS 4 -#define arglist a1, a2, a3, a4 -#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4; -#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4; -#define ARGSLIST args[0], args[1], args[2], args[3] +/* 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, arglist) +cp_thing (errfn, atarg1, format, ap) errorfn *errfn; int atarg1; - char *format; - arglist_dcl + const char *format; + va_list ap; +#endif { - char *fmt; - char *f; - char *ap; - int arg; - HOST_WIDE_INT atarg = atarg1 ? a1 : 0; - HOST_WIDE_INT args[NARGS]; - ARGSINIT - - fmt = STRDUP(format); - - for (f = fmt, arg = 0; *f; ++f) + static char *buf; + static long buflen; + int nargs = 0; + long len; + long offset; + const char *f; + tree atarg = 0; + + len = strlen (format) + 1; + if (len > buflen) + { + buflen = len; + buf = xrealloc (buf, buflen); + } + offset = 0; + + for (f = format; *f; ++f) { cp_printer * function; int alternate; int maybe_here; /* ignore text */ - if (*f != '%') continue; + if (*f != '%') + { + buf[offset++] = *f; + continue; + } ++f; alternate = 0; maybe_here = 0; - /* ignore most flags */ - while (*f == ' ' || *f == '-' || *f == '+' || *f == '#') + /* Check for '+' and '#' (in that order). */ + if (*f == '+') { - if (*f == '+') - maybe_here = 1; - else if (*f == '#') - alternate = 1; + maybe_here = 1; ++f; } - - /* ignore field width */ - if (*f == '*') + if (*f == '#') { + alternate = 1; ++f; - ++arg; } - else - while (isdigit (*f)) - ++f; - /* ignore precision */ - if (*f == '.') + /* no field width or precision */ + + function = cp_printers[(int)*f]; + + if (function || *f == 's') { - ++f; - if (*f == '*') + char *p; + int plen; + + if (*f == 's') { - ++f; - ++arg; + p = va_arg (ap, char *); + nargs++; } else - while (isdigit (*f)) - ++f; - } + { + tree t = va_arg (ap, tree); + nargs++; - /* ignore "long" */ - if (*f == 'l') - ++f; + /* This indicates that ATARG comes from a different + location than normal. */ + if (maybe_here && atarg1) + atarg = t; - function = cp_printers[(int)*f]; + /* If atarg1 is set and this is the first argument, then + set ATARG appropriately. */ + if (atarg1 && nargs == 1) + atarg = t; - if (function) - { - char *p; - - if (arg >= NARGS) abort (); - - if (maybe_here && atarg1) - atarg = args[arg]; + p = (*function) (t, alternate); + } - /* Must use a temporary to avoid calling *function twice */ - p = (*function) (args[arg], alternate); - args[arg] = (HOST_WIDE_INT) STRDUP(p); - *f = 's'; + plen = strlen (p); + len += plen; + if (len > buflen) + { + buflen = len; + buf = xrealloc (buf, len); + } + strcpy (buf + offset, p); + offset += plen; } + 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. */ - ++arg; /* Assume valid format string */ - + len += 2; + if (len > buflen) + { + buflen = len; + buf = xrealloc (buf, len); + } + strcpy (buf + offset, "%%"); + offset += 2; + } + else + { + if (*f != 'd') + abort (); + len += HOST_BITS_PER_INT / 2; + if (len > buflen) + { + buflen = len; + buf = xrealloc (buf, len); + } + sprintf (buf + offset, "%d", va_arg (ap, int)); + nargs++; + offset += strlen (buf + offset); + /* With an ANSI C library one could write + out += sprintf (...); */ + } } + buf[offset] = '\0'; + + /* If ATARG1 is set, but we haven't extracted any arguments, then + extract one tree argument for ATARG. */ + if (nargs == 0 && atarg1) + atarg = va_arg (ap, tree); if (atarg) { - char *file = cp_file_of ((tree) atarg); - int line = cp_line_of ((tree) atarg); - (*errfn) (file, line, fmt, ARGSLIST); + char *file = cp_file_of (atarg); + int line = cp_line_of (atarg); + (*errfn) (file, line, buf); } else - (*errfn) (fmt, ARGSLIST); + (*errfn) (buf); } -void -cp_error (format, arglist) - char *format; - arglist_dcl +#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) { - extern errorfn error; + va_list ap; + INIT; if (! cp_silent) - cp_thing (error, 0, format, arglist); + cp_thing ((errorfn *) error, 0, format, ap); + va_end (ap); } -void -cp_warning (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_warning) { - extern errorfn warning; + va_list ap; + INIT; if (! cp_silent) - cp_thing (warning, 0, format, arglist); + cp_thing ((errorfn *) warning, 0, format, ap); + va_end (ap); } -void -cp_pedwarn (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_pedwarn) { - extern errorfn pedwarn; + va_list ap; + INIT; if (! cp_silent) - cp_thing (pedwarn, 0, format, arglist); + cp_thing ((errorfn *) pedwarn, 0, format, ap); + va_end (ap); } -void -cp_compiler_error (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_compiler_error) { extern errorfn compiler_error; + va_list ap; + INIT; if (! cp_silent) - cp_thing (compiler_error, 0, format, arglist); + cp_thing (compiler_error, 0, format, ap); + va_end (ap); } -void -cp_sprintf (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_sprintf) { - cp_thing ((errorfn *) sprintf, 0, format, arglist); + va_list ap; + INIT; + cp_thing ((errorfn *) sprintf, 0, format, ap); + va_end (ap); } -void -cp_error_at (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_error_at) { - extern errorfn error_with_file_and_line; + va_list ap; + INIT; if (! cp_silent) - cp_thing (error_with_file_and_line, 1, format, arglist); + cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap); + va_end (ap); } -void -cp_warning_at (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_warning_at) { - extern errorfn warning_with_file_and_line; + va_list ap; + INIT; if (! cp_silent) - cp_thing (warning_with_file_and_line, 1, format, arglist); + cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap); + va_end (ap); } -void -cp_pedwarn_at (format, arglist) - char *format; - arglist_dcl +DECLARE (cp_pedwarn_at) { - extern errorfn pedwarn_with_file_and_line; + va_list ap; + INIT; if (! cp_silent) - cp_thing (pedwarn_with_file_and_line, 1, format, arglist); + 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 4eb196e..bb21bcb 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, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1993, 94-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -20,10 +20,11 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "tree.h" #include "cp-tree.h" #include "obstack.h" -#include +#include "toplev.h" typedef char* cp_printer (); @@ -34,21 +35,22 @@ typedef char* cp_printer (); #define L language_as_string #define O op_as_string #define P parm_as_string +#define Q assop_as_string #define T type_as_string #define V cv_as_string -#define _ (cp_printer *) 0 +#define o (cp_printer *) 0 cp_printer * cp_printers[256] = -{ +{ /*0 1 2 3 4 5 6 7 8 9 A B C D E F */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */ - _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */ - P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */ + o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x00 */ + 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 */ + 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 */ }; #undef C #undef D @@ -56,9 +58,10 @@ cp_printer * cp_printers[256] = #undef L #undef O #undef P +#undef Q #undef T #undef V -#undef _ +#undef o #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free @@ -77,16 +80,32 @@ static char *scratch_firstobj; IDENTIFIER_LENGTH (ID))) # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) -# define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \ +# define OB_PUTI(CST) do { sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(CST)); \ OB_PUTCP (digit_buffer); } while (0) # define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N)); # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t))) -static void dump_type (), dump_decl (), dump_function_decl (); -static void dump_expr (), dump_unary_op (), dump_binary_op (); -static void dump_aggr_type (), dump_type_prefix (), dump_type_suffix (); -static void dump_function_name (); +enum pad { none, before, after }; + +static void dump_type PROTO((tree, int)); +static void dump_type_real PROTO((tree, int, int)); +static void dump_simple_decl PROTO((tree, tree, int)); +static void dump_decl PROTO((tree, int)); +static void dump_function_decl PROTO((tree, int)); +static void dump_expr PROTO((tree, int)); +static void dump_unary_op PROTO((char *, tree, int)); +static void dump_binary_op PROTO((char *, tree)); +static void dump_aggr_type PROTO((tree, int, int)); +static void dump_type_prefix PROTO((tree, int, int)); +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_char PROTO((int)); +static char *aggr_variety PROTO((tree)); +static tree ident_fndecl PROTO((tree)); void init_error () @@ -95,8 +114,6 @@ init_error () scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0); } -enum pad { none, before, after }; - static void dump_readonly_or_volatile (t, p) tree t; @@ -119,11 +136,13 @@ dump_readonly_or_volatile (t, p) value. */ static char digit_buffer[128]; -/* Dump into the obstack a human-readable equivalent of TYPE. */ +/* Dump into the obstack a human-readable equivalent of TYPE. */ + static void -dump_type (t, v) +dump_type_real (t, v, canonical_name) tree t; int v; /* verbose? */ + int canonical_name; { if (t == NULL_TREE) return; @@ -145,19 +164,19 @@ dump_type (t, v) /* i.e. function taking no arguments */ if (t != void_list_node) { - dump_type (TREE_VALUE (t), v); + 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)); + dump_expr (TREE_PURPOSE (t), 0); } if (TREE_CHAIN (t)) { if (TREE_CHAIN (t) != void_list_node) { OB_PUTC2 (',', ' '); - dump_type (TREE_CHAIN (t), v); + dump_type_real (TREE_CHAIN (t), v, canonical_name); } } else OB_PUTS (" ..."); @@ -169,7 +188,7 @@ dump_type (t, v) break; case TREE_VEC: - dump_type (BINFO_TYPE (t), v); + dump_type_real (BINFO_TYPE (t), v, canonical_name); break; case RECORD_TYPE: @@ -179,21 +198,27 @@ dump_type (t, v) && (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t))) { if (TYPE_READONLY (t) | TYPE_VOLATILE (t)) - dump_readonly_or_volatile (t); - dump_type (SIGNATURE_TYPE (t), v); + dump_readonly_or_volatile (t, after); + dump_type_real (SIGNATURE_TYPE (t), v, canonical_name); if (IS_SIGNATURE_POINTER (t)) OB_PUTC ('*'); else OB_PUTC ('&'); } else - dump_aggr_type (t, v); + dump_aggr_type (t, v, canonical_name); break; case TYPE_DECL: + case TEMPLATE_DECL: dump_decl (t, v); break; + case COMPLEX_TYPE: + OB_PUTS ("complex "); + dump_type_real (TREE_TYPE (t), v, canonical_name); + break; + case INTEGER_TYPE: if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t)) OB_PUTS ("unsigned "); @@ -204,17 +229,56 @@ dump_type (t, v) case REAL_TYPE: case VOID_TYPE: case BOOLEAN_TYPE: - dump_readonly_or_volatile (t, after); - OB_PUTID (TYPE_IDENTIFIER (t)); + { + tree type; + dump_readonly_or_volatile (t, after); + type = canonical_name ? TYPE_MAIN_VARIANT (t) : t; + if (TYPE_NAME (type) && TYPE_IDENTIFIER (type)) + OB_PUTID (TYPE_IDENTIFIER (type)); + else + /* Types like intQI_type_node and friends have no names. + These don't come up in user error messages, but it's nice + to be able to print them from the debugger. */ + OB_PUTS ("{anonymous}"); + } break; - case TEMPLATE_TYPE_PARM: - OB_PUTID (TYPE_IDENTIFIER (t)); + case TEMPLATE_TEMPLATE_PARM: + if (!CLASSTYPE_TEMPLATE_INFO (t)) + { + /* For parameters inside template signature. */ + if (TYPE_IDENTIFIER (t)) + OB_PUTID (TYPE_IDENTIFIER (t)); + else + OB_PUTS ("{anonymous template template parm}"); + } + else + { + int i; + tree args = CLASSTYPE_TI_ARGS (t); + OB_PUTID (TYPE_IDENTIFIER (t)); + OB_PUTC ('<'); + for (i = 0; i < TREE_VEC_LENGTH (args); i++) + { + tree arg = TREE_VEC_ELT (args, i); + if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't' + || TREE_CODE (arg) == TEMPLATE_DECL) + dump_type_real (arg, 0, canonical_name); + else + dump_expr (arg, 0); + if (i < TREE_VEC_LENGTH (args)-1) + OB_PUTC2 (',', ' '); + } + OB_PUTC ('>'); + } break; - case UNINSTANTIATED_P_TYPE: - OB_PUTID (DECL_NAME (UPT_TEMPLATE (t))); - OB_PUTS ("<...>"); + case TEMPLATE_TYPE_PARM: + dump_readonly_or_volatile (t, after); + if (TYPE_IDENTIFIER (t)) + OB_PUTID (TYPE_IDENTIFIER (t)); + else + OB_PUTS ("{anonymous template type parm}"); break; /* This is not always necessary for pointers and such, but doing this @@ -226,8 +290,15 @@ dump_type (t, v) offset_type: case FUNCTION_TYPE: case METHOD_TYPE: - dump_type_prefix (t, v); - dump_type_suffix (t, v); + dump_type_prefix (t, v, canonical_name); + dump_type_suffix (t, v, canonical_name); + break; + + case TYPENAME_TYPE: + OB_PUTS ("typename "); + dump_type_real (TYPE_CONTEXT (t), 0, canonical_name); + OB_PUTS ("::"); + OB_PUTID (TYPE_IDENTIFIER (t)); break; default: @@ -252,12 +323,22 @@ aggr_variety (t) return "struct"; } -/* Print out a class declaration, in the form `class foo'. */ static void -dump_aggr_type (t, v) +dump_type (t, v) tree t; int v; /* verbose? */ { + dump_type_real (t, v, 0); +} + +/* Print out a class declaration, in the form `class foo'. */ + +static void +dump_aggr_type (t, v, canonical_name) + tree t; + int v; /* verbose? */ + int canonical_name; +{ tree name; char *variety = aggr_variety (t); @@ -269,9 +350,9 @@ dump_aggr_type (t, v) OB_PUTC (' '); } - name = TYPE_NAME (t); + name = TYPE_NAME (canonical_name ? TYPE_MAIN_VARIANT (t) : t); - if (name && DECL_CONTEXT (name)) + if (name && DECL_CONTEXT (name) && DECL_CONTEXT (name) != global_namespace) { /* FUNCTION_DECL or RECORD_TYPE */ dump_decl (DECL_CONTEXT (name), 0); @@ -308,9 +389,10 @@ dump_aggr_type (t, v) int *[]&. */ static void -dump_type_prefix (t, v) +dump_type_prefix (t, v, canonical_name) tree t; int v; /* verbosity */ + int canonical_name; { if (TYPE_PTRMEMFUNC_P (t)) { @@ -324,7 +406,7 @@ dump_type_prefix (t, v) { tree sub = TREE_TYPE (t); - dump_type_prefix (sub, v); + 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) @@ -358,7 +440,7 @@ dump_type_prefix (t, v) case REFERENCE_TYPE: { tree sub = TREE_TYPE (t); - dump_type_prefix (sub, v); + dump_type_prefix (sub, v, canonical_name); switch (TREE_CODE (sub)) { @@ -382,11 +464,11 @@ dump_type_prefix (t, v) case OFFSET_TYPE: offset_type: - dump_type_prefix (TREE_TYPE (t), v); + dump_type_prefix (TREE_TYPE (t), v, canonical_name); if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */ { OB_PUTC (' '); - dump_type (TYPE_OFFSET_BASETYPE (t), 0); + dump_type_real (TYPE_OFFSET_BASETYPE (t), 0, canonical_name); OB_PUTC2 (':', ':'); } OB_PUTC ('*'); @@ -396,19 +478,19 @@ dump_type_prefix (t, v) /* Can only be reached through function pointer -- this would not be correct if FUNCTION_DECLs used it. */ case FUNCTION_TYPE: - dump_type_prefix (TREE_TYPE (t), v); + dump_type_prefix (TREE_TYPE (t), v, canonical_name); OB_PUTC2 (' ', '('); break; case METHOD_TYPE: - dump_type_prefix (TREE_TYPE (t), v); + dump_type_prefix (TREE_TYPE (t), v, canonical_name); OB_PUTC2 (' ', '('); - dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0); + dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0, canonical_name); OB_PUTC2 (':', ':'); break; case ARRAY_TYPE: - dump_type_prefix (TREE_TYPE (t), v); + dump_type_prefix (TREE_TYPE (t), v, canonical_name); break; case ENUMERAL_TYPE: @@ -419,14 +501,16 @@ dump_type_prefix (t, v) case REAL_TYPE: case RECORD_TYPE: case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: case TREE_LIST: case TYPE_DECL: case TREE_VEC: - case UNINSTANTIATED_P_TYPE: case UNION_TYPE: case UNKNOWN_TYPE: case VOID_TYPE: - dump_type (t, v); + case TYPENAME_TYPE: + case COMPLEX_TYPE: + dump_type_real (t, v, canonical_name); break; default: @@ -436,9 +520,10 @@ dump_type_prefix (t, v) } static void -dump_type_suffix (t, v) +dump_type_suffix (t, v, canonical_name) tree t; int v; /* verbose? */ + int canonical_name; { if (TYPE_PTRMEMFUNC_P (t)) t = TYPE_PTRMEMFUNC_FN_TYPE (t); @@ -450,7 +535,7 @@ dump_type_suffix (t, v) case OFFSET_TYPE: if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) OB_PUTC (')'); - dump_type_suffix (TREE_TYPE (t), v); + dump_type_suffix (TREE_TYPE (t), v, canonical_name); break; /* Can only be reached through function pointer */ @@ -471,16 +556,25 @@ dump_type_suffix (t, v) if (TREE_CODE (t) == METHOD_TYPE) dump_readonly_or_volatile (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before); - dump_type_suffix (TREE_TYPE (t), v); + dump_type_suffix (TREE_TYPE (t), v, canonical_name); break; } case ARRAY_TYPE: OB_PUTC ('['); if (TYPE_DOMAIN (t)) - OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1); + { + if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == INTEGER_CST) + OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1); + else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR) + dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0), 0); + else + dump_expr (fold (build_binary_op + (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)), + integer_one_node, 1)), 0); + } OB_PUTC (']'); - dump_type_suffix (TREE_TYPE (t), v); + dump_type_suffix (TREE_TYPE (t), v, canonical_name); break; case ENUMERAL_TYPE: @@ -491,13 +585,15 @@ dump_type_suffix (t, v) case REAL_TYPE: case RECORD_TYPE: case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: case TREE_LIST: case TYPE_DECL: case TREE_VEC: - case UNINSTANTIATED_P_TYPE: case UNION_TYPE: case UNKNOWN_TYPE: case VOID_TYPE: + case TYPENAME_TYPE: + case COMPLEX_TYPE: break; default: @@ -508,7 +604,8 @@ dump_type_suffix (t, v) /* Return a function declaration which corresponds to the IDENTIFIER_NODE argument. */ -tree + +static tree ident_fndecl (t) tree t; { @@ -538,9 +635,9 @@ ident_fndecl (t) #endif #define GLOBAL_IORD_P(NODE) \ - !strncmp(IDENTIFIER_POINTER(NODE),GLOBAL_THING,sizeof(GLOBAL_THING)-1) + ! strncmp (IDENTIFIER_POINTER(NODE), GLOBAL_THING, sizeof (GLOBAL_THING) - 1) -void +static void dump_global_iord (t) tree t; { @@ -560,6 +657,31 @@ dump_global_iord (t) } static void +dump_simple_decl (t, type, v) + tree t; + tree type; + int v; +{ + if (v > 0) + { + dump_type_prefix (type, v, 0); + OB_PUTC (' '); + dump_readonly_or_volatile (t, after); + } + if (DECL_CLASS_SCOPE_P (t)) + { + dump_type (DECL_CONTEXT (t), 0); + OB_PUTC2 (':', ':'); + } + if (DECL_NAME (t)) + dump_decl (DECL_NAME (t), v); + else + OB_PUTS ("{anon}"); + if (v > 0) + dump_type_suffix (type, v, 0); +} + +static void dump_decl (t, v) tree t; int v; /* verbosity */ @@ -576,18 +698,20 @@ dump_decl (t, v) case TYPE_DECL: { /* Don't say 'typedef class A' */ - tree type = TREE_TYPE (t); - if (((IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type)) - || TREE_CODE (type) == ENUMERAL_TYPE) - && type == TYPE_MAIN_VARIANT (type)) + if (DECL_ARTIFICIAL (t)) { - dump_type (type, v); + if (v > 0 && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM) + /* Say `class T' not just `T'. */ + OB_PUTS ("class "); + + dump_type (TREE_TYPE (t), v); break; } } if (v > 0) OB_PUTS ("typedef "); - goto general; + dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) + ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), v); break; case VAR_DECL: @@ -600,32 +724,24 @@ dump_decl (t, v) /* else fall through */ case FIELD_DECL: case PARM_DECL: - general: - if (v > 0) - { - dump_type_prefix (TREE_TYPE (t), v); - OB_PUTC (' '); - dump_readonly_or_volatile (t, after); - } - /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */ - if (DECL_CONTEXT (t) - && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't') - { - dump_type (DECL_CONTEXT (t), 0); - OB_PUTC2 (':', ':'); - } - if (DECL_NAME (t)) - dump_decl (DECL_NAME (t), v); - else - OB_PUTS ("{anon}"); - if (v > 0) - dump_type_suffix (TREE_TYPE (t), v); + dump_simple_decl (t, TREE_TYPE (t), v); break; case NAMESPACE_DECL: + if (DECL_CONTEXT (t) != global_namespace) + { + dump_decl (DECL_CONTEXT (t), v); + OB_PUTC2 (':',':'); + } OB_PUTID (DECL_NAME (t)); break; + case SCOPE_REF: + dump_decl (TREE_OPERAND (t, 0), 0); + OB_PUTS ("::"); + dump_decl (TREE_OPERAND (t, 1), 0); + break; + case ARRAY_REF: dump_decl (TREE_OPERAND (t, 0), v); OB_PUTC ('['); @@ -646,7 +762,7 @@ dump_decl (t, v) break; /* These special cases are duplicated here so that other functions - can feed identifiers to cp_error and get them demangled properly. */ + can feed identifiers to cp_error and get them demangled properly. */ case IDENTIFIER_NODE: { tree f; if (DESTRUCTOR_NAME_P (t) @@ -677,45 +793,64 @@ dump_decl (t, v) case FUNCTION_DECL: if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t))) dump_global_iord (DECL_ASSEMBLER_NAME (t)); + else if (! DECL_LANG_SPECIFIC (t)) + OB_PUTS ("{internal}"); else dump_function_decl (t, v); break; case TEMPLATE_DECL: { - tree args = DECL_TEMPLATE_PARMS (t); - int i, len = args ? TREE_VEC_LENGTH (args) : 0; - OB_PUTS ("template <"); - for (i = 0; i < len; i++) + tree orig_args = DECL_TEMPLATE_PARMS (t); + tree args; + int i; + for (args = orig_args = nreverse (orig_args); + args; + args = TREE_CHAIN (args)) { - tree arg = TREE_VEC_ELT (args, i); - tree defval = TREE_PURPOSE (arg); - arg = TREE_VALUE (arg); - if (TREE_CODE (arg) == TYPE_DECL) - { - OB_PUTS ("class "); - OB_PUTID (DECL_NAME (arg)); - } - else - dump_decl (arg, 1); + int len = TREE_VEC_LENGTH (TREE_VALUE (args)); - if (defval) + OB_PUTS ("template <"); + for (i = 0; i < len; i++) { - OB_PUTS (" = "); - dump_decl (defval, 1); - } + tree arg = TREE_VEC_ELT (TREE_VALUE (args), i); + tree defval = TREE_PURPOSE (arg); + arg = TREE_VALUE (arg); + if (TREE_CODE (arg) == TYPE_DECL) + { + if (DECL_NAME (arg)) + { + OB_PUTS ("class "); + OB_PUTID (DECL_NAME (arg)); + } + else + OB_PUTS ("class"); + } + else + dump_decl (arg, 1); + + if (defval) + { + OB_PUTS (" = "); + if (TREE_CODE (arg) == TYPE_DECL + || TREE_CODE (arg) == TEMPLATE_DECL) + dump_type (defval, 1); + else + dump_expr (defval, 1); + } - OB_PUTC2 (',', ' '); + OB_PUTC2 (',', ' '); + } + if (len != 0) + OB_UNPUT (2); + OB_PUTC2 ('>', ' '); } - if (len != 0) - OB_UNPUT (2); - OB_PUTC2 ('>', ' '); + nreverse(orig_args); - if (DECL_TEMPLATE_IS_CLASS (t)) - { - OB_PUTS ("class "); - OB_PUTID (DECL_NAME (t)); - } + if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL) + dump_type (TREE_TYPE (t), v); + else if (TREE_TYPE (t) == NULL_TREE) + my_friendly_abort (353); else switch (NEXT_CODE (t)) { case METHOD_TYPE: @@ -724,20 +859,60 @@ dump_decl (t, v) break; default: - my_friendly_abort (353); + /* This case can occur with some illegal code. */ + dump_type (TREE_TYPE (t), v); + } + } + break; + + case TEMPLATE_ID_EXPR: + { + tree args; + tree name = TREE_OPERAND (t, 0); + if (is_overloaded_fn (name)) + name = DECL_NAME (get_first_fn (name)); + dump_decl (name, v); + OB_PUTC ('<'); + for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args)) + { + if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (args))) == 't' + || TREE_CODE (TREE_VALUE (args)) == TEMPLATE_DECL) + dump_type (TREE_VALUE (args), 0); + else + dump_expr (TREE_VALUE (args), 0); + if (TREE_CHAIN (args)) + OB_PUTC2 (',', ' '); } + OB_PUTC ('>'); } break; + case LOOKUP_EXPR: + dump_decl (TREE_OPERAND (t, 0), v); + break; + case LABEL_DECL: OB_PUTID (DECL_NAME (t)); break; case CONST_DECL: - if (NEXT_CODE (t) == ENUMERAL_TYPE) - goto general; - else + if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE) + || (DECL_INITIAL (t) && + TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX)) + dump_simple_decl (t, TREE_TYPE (t), v); + else if (DECL_NAME (t)) + dump_decl (DECL_NAME (t), v); + else if (DECL_INITIAL (t)) dump_expr (DECL_INITIAL (t), 0); + else + OB_PUTS ("enumerator"); + break; + + case USING_DECL: + OB_PUTS ("using "); + dump_type (DECL_INITIAL (t), 0); + OB_PUTS ("::"); + OB_PUTID (DECL_NAME (t)); break; default: @@ -755,11 +930,18 @@ dump_function_decl (t, v) tree t; int v; { - tree name = DECL_ASSEMBLER_NAME (t); - tree fntype = TREE_TYPE (t); - tree parmtypes = TYPE_ARG_TYPES (fntype); + tree name; + tree fntype; + tree parmtypes; tree cname = NULL_TREE; + if (TREE_CODE (t) == TEMPLATE_DECL) + t = DECL_TEMPLATE_RESULT (t); + + name = DECL_ASSEMBLER_NAME (t); + fntype = TREE_TYPE (t); + parmtypes = TYPE_ARG_TYPES (fntype); + /* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */ if (DECL_CONTEXT (t)) cname = DECL_CLASS_CONTEXT (t); @@ -778,7 +960,7 @@ dump_function_decl (t, v) && ! DECL_CONSTRUCTOR_P (t) && ! DESTRUCTOR_NAME_P (name)) { - dump_type_prefix (TREE_TYPE (fntype), 1); + dump_type_prefix (TREE_TYPE (fntype), 1, 0); OB_PUTC (' '); } } @@ -809,7 +991,7 @@ dump_function_decl (t, v) OB_PUTC (')'); if (v && ! IDENTIFIER_TYPENAME_P (name)) - dump_type_suffix (TREE_TYPE (fntype), 1); + dump_type_suffix (TREE_TYPE (fntype), 1, 0); if (TREE_CODE (fntype) == METHOD_TYPE) { @@ -825,6 +1007,7 @@ dump_function_decl (t, v) /* Handle the function name for a FUNCTION_DECL node, grokking operators and destructors properly. */ + static void dump_function_name (t) tree t; @@ -858,11 +1041,98 @@ dump_function_name (t) } else dump_decl (name, 0); + + if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)) + { + tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE; + + 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 struct S { void f(); }; + + and we are printing S::f(). This is a template + instantiation, but we don't print anything after the f. */ + ; + else + { + 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) + { + 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); + } + + need_comma = 1; + } + } + 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++) + { + 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); + } + + need_comma = 1; + } + } + } + OB_PUTC ('>'); + } + } } static void dump_char (c) - char c; + int c; { switch (c) { @@ -897,7 +1167,7 @@ dump_char (c) OB_PUTS ("\\\""); break; default: - if (isprint (c)) + if (ISPRINT (c)) OB_PUTC (c); else { @@ -908,6 +1178,7 @@ dump_char (c) } /* Print out a list of initializers (subr of dump_expr) */ + static void dump_expr_list (l) tree l; @@ -922,6 +1193,7 @@ dump_expr_list (l) } /* Print out an expression */ + static void dump_expr (t, nop) tree t; @@ -934,6 +1206,8 @@ dump_expr (t, nop) case FIELD_DECL: case CONST_DECL: case FUNCTION_DECL: + case TEMPLATE_DECL: + case NAMESPACE_DECL: dump_decl (t, -1); break; @@ -950,12 +1224,12 @@ dump_expr (t, nop) } else if (type == boolean_type_node) { - if (t == boolean_false_node) + if (t == boolean_false_node + || (TREE_INT_CST_LOW (t) == 0 + && TREE_INT_CST_HIGH (t) == 0)) OB_PUTS ("false"); else if (t == boolean_true_node) OB_PUTS ("true"); - else - my_friendly_abort (366); } else if (type == char_type_node) { @@ -995,7 +1269,7 @@ dump_expr (t, nop) #else { unsigned char *p = (unsigned char *) &TREE_REAL_CST (t); - int i; + size_t i; strcpy (digit_buffer, "0x"); for (i = 0; i < sizeof TREE_REAL_CST (t); i++) sprintf (digit_buffer + 2 + 2*i, "%02x", *p++); @@ -1044,10 +1318,11 @@ dump_expr (t, nop) } break; - case NEW_EXPR: + case AGGR_INIT_EXPR: OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t))); OB_PUTC ('('); - dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1))); + if (TREE_OPERAND (t, 1)) + dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1))); OB_PUTC (')'); break; @@ -1059,7 +1334,7 @@ dump_expr (t, nop) if (TREE_CODE (fn) == ADDR_EXPR) fn = TREE_OPERAND (fn, 0); - if (NEXT_CODE (fn) == METHOD_TYPE) + if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE) { tree ob = TREE_VALUE (args); if (TREE_CODE (ob) == ADDR_EXPR) @@ -1076,16 +1351,37 @@ dump_expr (t, nop) args = TREE_CHAIN (args); } dump_expr (fn, 0); - OB_PUTC('('); + OB_PUTC ('('); dump_expr_list (args); OB_PUTC (')'); } break; - case WITH_CLEANUP_EXPR: - /* Note that this only works for G++ cleanups. If somebody - builds a general cleanup, there's no way to represent it. */ - dump_expr (TREE_OPERAND (t, 0), 0); + case NEW_EXPR: + { + tree type = TREE_OPERAND (t, 1); + if (NEW_EXPR_USE_GLOBAL (t)) + OB_PUTS ("::"); + OB_PUTS ("new "); + if (TREE_OPERAND (t, 0)) + { + OB_PUTC ('('); + dump_expr_list (TREE_OPERAND (t, 0)); + OB_PUTS (") "); + } + if (TREE_CODE (type) == ARRAY_REF) + type = build_cplus_array_type + (TREE_OPERAND (type, 0), + build_index_type (size_binop (MINUS_EXPR, TREE_OPERAND (type, 1), + integer_one_node))); + dump_type (type, 0); + if (TREE_OPERAND (t, 2)) + { + OB_PUTC ('('); + dump_expr_list (TREE_OPERAND (t, 2)); + OB_PUTC (')'); + } + } break; case TARGET_EXPR: @@ -1188,7 +1484,8 @@ dump_expr (t, nop) } else { - if (NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE) + if (TREE_OPERAND (t,0) != NULL_TREE + && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE) dump_expr (TREE_OPERAND (t, 0), nop); else dump_unary_op ("*", t, nop); @@ -1215,7 +1512,7 @@ dump_expr (t, nop) /* FIXME: This is a KLUDGE workaround for a parsing problem. There should be another level of INDIRECT_REF so that I don't have to do this. */ - if (NEXT_CODE (t) == POINTER_TYPE) + if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE) { tree next = TREE_TYPE (TREE_TYPE (t)); @@ -1240,8 +1537,46 @@ dump_expr (t, nop) break; case CONSTRUCTOR: + if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) + { + tree idx = build_component_ref (t, index_identifier, NULL_TREE, 0); + + if (integer_all_onesp (idx)) + { + tree pfn = PFN_FROM_PTRMEMFUNC (t); + dump_expr (pfn, 0); + break; + } + if (TREE_CODE (idx) == INTEGER_CST + && TREE_INT_CST_HIGH (idx) == 0) + { + tree virtuals; + unsigned HOST_WIDE_INT n; + + t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); + t = TYPE_METHOD_BASETYPE (t); + virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t))); + + n = TREE_INT_CST_LOW (idx); + + /* Map vtable index back one, to allow for the null pointer to + member. */ + --n; + + while (n > 0 && virtuals) + { + --n; + virtuals = TREE_CHAIN (virtuals); + } + if (virtuals) + { + dump_expr (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); + break; + } + } + } OB_PUTC ('{'); - dump_expr_list (CONSTRUCTOR_ELTS (t), 0); + dump_expr_list (CONSTRUCTOR_ELTS (t)); OB_PUTC ('}'); break; @@ -1255,12 +1590,82 @@ dump_expr (t, nop) dump_expr (TREE_OPERAND (t, 1), 0); else { - sorry ("operand of OFFSET_REF not understood"); - goto error; + dump_expr (TREE_OPERAND (t, 0), 0); + OB_PUTS (" .* "); + dump_expr (TREE_OPERAND (t, 1), 0); } break; } + case TEMPLATE_PARM_INDEX: + dump_decl (TEMPLATE_PARM_DECL (t), -1); + break; + + case IDENTIFIER_NODE: + OB_PUTID (t); + break; + + case SCOPE_REF: + dump_type (TREE_OPERAND (t, 0), 0); + OB_PUTS ("::"); + dump_expr (TREE_OPERAND (t, 1), 0); + break; + + case CAST_EXPR: + if (TREE_OPERAND (t, 0) == NULL_TREE + || TREE_CHAIN (TREE_OPERAND (t, 0))) + { + dump_type (TREE_TYPE (t), 0); + OB_PUTC ('('); + dump_expr_list (TREE_OPERAND (t, 0)); + OB_PUTC (')'); + } + else + { + OB_PUTC ('('); + dump_type (TREE_TYPE (t), 0); + OB_PUTC (')'); + OB_PUTC ('('); + dump_expr_list (TREE_OPERAND (t, 0)); + OB_PUTC (')'); + } + break; + + case LOOKUP_EXPR: + OB_PUTID (TREE_OPERAND (t, 0)); + break; + + case ARROW_EXPR: + dump_expr (TREE_OPERAND (t, 0), nop); + OB_PUTS ("->"); + break; + + case SIZEOF_EXPR: + case ALIGNOF_EXPR: + if (TREE_CODE (t) == SIZEOF_EXPR) + OB_PUTS ("sizeof ("); + else + { + my_friendly_assert (TREE_CODE (t) == ALIGNOF_EXPR, 0); + OB_PUTS ("__alignof__ ("); + } + if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't') + dump_type (TREE_OPERAND (t, 0), 0); + else + dump_unary_op ("*", t, 0); + OB_PUTC (')'); + break; + + case DEFAULT_ARG: + OB_PUTS ("{unparsed}"); + break; + + case TRY_CATCH_EXPR: + case WITH_CLEANUP_EXPR: + case CLEANUP_POINT_EXPR: + dump_expr (TREE_OPERAND (t, 0), nop); + break; + case TREE_LIST: if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL) { @@ -1278,7 +1683,6 @@ dump_expr (t, nop) /* fall through to ERROR_MARK... */ case ERROR_MARK: - error: OB_PUTCP ("{error}"); break; } @@ -1311,34 +1715,47 @@ dump_unary_op (opstring, t, nop) } char * -fndecl_as_string (cname, fndecl, print_ret_type_p) - tree cname, fndecl; +fndecl_as_string (fndecl, print_ret_type_p) + tree fndecl; int print_ret_type_p; { return decl_as_string (fndecl, print_ret_type_p); } -/* Same, but handtype a _TYPE. +/* Same, but handle a _TYPE. Called from convert_to_reference, mangle_class_name_for_template, - build_unary_op, and GNU_xref_decl. */ + build_unary_op, and GNU_xref_decl. If CANONICAL_NAME is non-zero, + when describing a typedef, we use the name of the type described, + rather than the name of the typedef. */ + char * -type_as_string (typ, v) +type_as_string_real (typ, v, canonical_name) tree typ; int v; + int canonical_name; { OB_INIT (); - dump_type (typ, v); + dump_type_real (typ, v, canonical_name); OB_FINISH (); return (char *)obstack_base (&scratch_obstack); } + +char * +type_as_string (typ, v) + tree typ; + int v; +{ + return type_as_string_real (typ, v, 0); +} + char * expr_as_string (decl, v) tree decl; - int v; + int v ATTRIBUTE_UNUSED; { OB_INIT (); @@ -1351,6 +1768,7 @@ expr_as_string (decl, v) /* A cross between type_as_string and fndecl_as_string. Only called from substitute_nice_name. */ + char * decl_as_string (decl, v) tree decl; @@ -1365,14 +1783,48 @@ decl_as_string (decl, v) return (char *)obstack_base (&scratch_obstack); } +/* Generate the three forms of printable names for lang_printable_name. */ + +char * +lang_decl_name (decl, v) + tree decl; + int v; +{ + if (v >= 2) + return decl_as_string (decl, 1); + + OB_INIT (); + + if (v == 1 && DECL_CLASS_SCOPE_P (decl)) + { + tree cname; + if (TREE_CODE (decl) == FUNCTION_DECL) + cname = DECL_CLASS_CONTEXT (decl); + else + cname = DECL_CONTEXT (decl); + dump_type (cname, 0); + OB_PUTC2 (':', ':'); + } + + if (TREE_CODE (decl) == FUNCTION_DECL) + dump_function_name (decl); + else + dump_decl (DECL_NAME (decl), 0); + + OB_FINISH (); + + return (char *)obstack_base (&scratch_obstack); +} + + char * cp_file_of (t) tree t; { - if (TREE_CODE (t) == PARM_DECL) + if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t)) return DECL_SOURCE_FILE (DECL_CONTEXT (t)); else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') - return DECL_SOURCE_FILE (TYPE_NAME (t)); + return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t)); else return DECL_SOURCE_FILE (t); } @@ -1382,18 +1834,13 @@ cp_line_of (t) tree t; { int line = 0; - if (TREE_CODE (t) == PARM_DECL) + 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)) t = TREE_TYPE (t); if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') - { - if (IS_AGGR_TYPE (t)) - line = CLASSTYPE_SOURCE_LINE (t); - else - line = DECL_SOURCE_LINE (TYPE_NAME (t)); - } + line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t)); else line = DECL_SOURCE_LINE (t); @@ -1406,7 +1853,7 @@ cp_line_of (t) char * code_as_string (c, v) enum tree_code c; - int v; + int v ATTRIBUTE_UNUSED; { return tree_code_name [c]; } @@ -1414,7 +1861,7 @@ code_as_string (c, v) char * language_as_string (c, v) enum languages c; - int v; + int v ATTRIBUTE_UNUSED; { switch (c) { @@ -1424,6 +1871,9 @@ language_as_string (c, v) case lang_cplusplus: return "C++"; + case lang_java: + return "Java"; + default: my_friendly_abort (355); return 0; @@ -1431,9 +1881,11 @@ language_as_string (c, v) } /* Return the proper printed version of a parameter to a C++ function. */ + char * parm_as_string (p, v) - int p, v; + int p; + int v ATTRIBUTE_UNUSED; { if (p < 0) return "`this'"; @@ -1445,7 +1897,7 @@ parm_as_string (p, v) char * op_as_string (p, v) enum tree_code p; - int v; + int v ATTRIBUTE_UNUSED; { static char buf[] = "operator "; @@ -1457,20 +1909,48 @@ op_as_string (p, v) } char * +assop_as_string (p, v) + enum tree_code p; + int v ATTRIBUTE_UNUSED; +{ + static char buf[] = "operator "; + + if (p == 0) + return "{unknown}"; + + strcpy (buf + 9, assignop_tab [p]); + return buf; +} + +char * args_as_string (p, v) tree p; int v; { if (p == NULL_TREE) - return "..."; + return ""; + + if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't') + return type_as_string (p, v); - return type_as_string (p, v); + OB_INIT (); + for (; p; p = TREE_CHAIN (p)) + { + if (TREE_VALUE (p) == null_node) + OB_PUTS ("NULL"); + else + dump_type (error_type (TREE_VALUE (p)), v); + if (TREE_CHAIN (p)) + OB_PUTS (", "); + } + OB_FINISH (); + return (char *)obstack_base (&scratch_obstack); } char * cv_as_string (p, v) tree p; - int v; + int v ATTRIBUTE_UNUSED; { OB_INIT (); diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c index 51577f8..d294497 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, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc. Contributed by Michael Tiemann Rewritten by Mike Stump , based upon an initial re-implementation courtesy Tad Hunt. @@ -22,91 +22,48 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* High-level class interface. */ - #include "config.h" +#include "system.h" #include "tree.h" #include "rtl.h" #include "cp-tree.h" #include "flags.h" #include "obstack.h" #include "expr.h" +#include "output.h" +#include "except.h" +#include "function.h" +#include "defaults.h" +#include "toplev.h" +#include "eh-common.h" -tree protect_list; - -extern void (*interim_eh_hook) PROTO((tree)); rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx)); -/* holds the fndecl for __builtin_return_address () */ +/* Holds the fndecl for __builtin_return_address. */ tree builtin_return_address_fndecl; -tree throw_fndecl; - -static int -doing_eh (do_warn) - int do_warn; -{ - if (! flag_handle_exceptions) - { - static int warned = 0; - if (! warned && do_warn) - { - error ("exception handling disabled, use -fhandle-exceptions to enable."); - warned = 1; - } - return 0; - } - return 1; -} - - -/* -NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer -to supporting exception handling as per ANSI C++ working draft. -It is a complete rewrite of all the EH stuff that was here before - Shortcomings: - 1. Throw specifications of functions still don't work. - Cool Things: - 1. Destructors are called properly :-) - 2. No overhead for the non-exception thrown case. - 3. Fixing shortcoming 1 is simple. - -Tad Hunt (tad@mail.csh.rit.edu) - -*/ /* A couple of backend routines from m88k.c */ -/* used to cache a call to __builtin_return_address () */ -static tree BuiltinReturnAddress; - - -#include - -/* XXX - Tad: for EH */ -/* output an exception table entry */ - -static void -output_exception_table_entry (file, start_label, end_label, eh_label) - FILE *file; - rtx start_label, end_label, eh_label; -{ - char label[100]; - - assemble_integer (start_label, GET_MODE_SIZE (Pmode), 1); - assemble_integer (end_label, GET_MODE_SIZE (Pmode), 1); - assemble_integer (eh_label, GET_MODE_SIZE (Pmode), 1); - putc ('\n', file); /* blank line */ -} - -static void -easy_expand_asm (str) - char *str; -{ - expand_asm (build_string (strlen (str)+1, str)); -} - +static void push_eh_cleanup PROTO((void)); +static tree build_eh_type_type PROTO((tree)); +static tree build_eh_type PROTO((tree)); +static void expand_end_eh_spec PROTO((tree)); +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)); +static tree get_eh_type PROTO((void)); +static tree get_eh_caught PROTO((void)); +static tree get_eh_handlers PROTO((void)); +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)); #if 0 -/* This is the startup, and finish stuff per exception table. */ +/* This is the startup, and finish stuff per exception table. */ /* XXX - Tad: exception handling section */ #ifndef EXCEPT_SECTION_ASM_OP @@ -114,14 +71,6 @@ easy_expand_asm (str) #endif #ifdef EXCEPT_SECTION_ASM_OP -typedef struct { - void *start_protect; - void *end_protect; - void *exception_handler; - } exception_table; -#endif /* EXCEPT_SECTION_ASM_OP */ - -#ifdef EXCEPT_SECTION_ASM_OP /* on machines which support it, the exception table lives in another section, but it needs a label so we can reference it... This sets up that @@ -145,45 +94,9 @@ asm (TEXT_SECTION_ASM_OP); #endif -void -exception_section () -{ -#ifdef ASM_OUTPUT_SECTION_NAME - named_section (NULL_TREE, ".gcc_except_table"); -#else - if (flag_pic) - data_section (); - else -#if defined(TARGET_POWERPC) /* are we on a __rs6000? */ - data_section (); -#else - readonly_data_section (); -#endif -#endif -} - - - - -/* from: my-cp-except.c */ - -/* VI: ":set ts=4" */ -#if 0 -#include */ -#include "config.h" -#include "tree.h" -#include "rtl.h" -#include "cp-tree.h" -#endif #include "decl.h" -#if 0 -#include "flags.h" -#endif #include "insn-flags.h" #include "obstack.h" -#if 0 -#include "expr.h" -#endif /* ====================================================================== Briefly the algorithm works like this: @@ -194,15 +107,15 @@ exception_section () output to start the protection for that block. When a destructor or end try block is encountered, pop_eh_entry - (&eh_stack) is called. Pop_eh_entry () returns the ehEntry it - created when push_eh_entry () was called. The ehEntry structure + (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it + created when push_eh_entry () was called. The eh_entry structure contains three things at this point. The start protect label, the end protect label, and the exception handler label. The end protect label should be output before the call to the destructor (if any). If it was a destructor, then its parse tree is stored - in the finalization variable in the ehEntry structure. Otherwise + in the finalization variable in the eh_entry structure. Otherwise the finalization variable is set to NULL to reflect the fact that - is the the end of a try block. Next, this modified ehEntry node + it is the end of a try block. Next, this modified eh_entry node is enqueued in the finalizations queue by calling enqueue_eh_entry (&queue,entry). @@ -231,12 +144,12 @@ exception_section () any of those finalizations throw an exception, we must call terminate according to the ARM (section r.15.6.1). What this means is that we need to dequeue and emit finalizations for each - entry in the ehQueue until we get to an entry with a NULL + entry in the eh_queue until we get to an entry with a NULL finalization field. For any of the finalization entries, if it is not a call to terminate (), we must protect it by giving it another start label, end label, and exception handler label, setting its finalization tree to be a call to terminate (), and - enqueue'ing this new ehEntry to be output at an outer level. + enqueue'ing this new eh_entry to be output at an outer level. Finally, after all that is done, we can get around to outputting the catch block which basically wraps all the "catch (...) {...}" statements in a big if/then/else construct that matches the @@ -244,66 +157,21 @@ exception_section () ===================================================================== */ -extern rtx emit_insn PROTO((rtx)); -extern rtx gen_nop PROTO(()); - /* local globals for function calls ====================================================================== */ -/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and - "set_unexpected ()" after default_conversion. (lib-except.c) */ -static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch, Throw; +/* Used to cache "terminate" and "__throw_type_match*". */ +static tree Terminate, CatchMatch; -/* used to cache __find_first_exception_table_match () - for throw (lib-except.c) */ +/* Used to cache __find_first_exception_table_match for throw. */ static tree FirstExceptionMatch; -/* used to cache a call to __unwind_function () (lib-except.c) */ +/* Used to cache a call to __unwind_function. */ static tree Unwind; -/* holds a ready to emit call to "terminate ()". */ -static tree TerminateFunctionCall; - /* ====================================================================== */ - -/* data structures for my various quick and dirty stacks and queues - Eventually, most of this should go away, because I think it can be - integrated with stuff already built into the compiler. */ - -/* =================================================================== */ - -struct labelNode { - rtx label; - struct labelNode *chain; -}; - - -/* this is the most important structure here. Basically this is how I store - an exception table entry internally. */ -struct ehEntry { - rtx start_label; - rtx end_label; - rtx exception_handler_label; - - tree finalization; - tree context; -}; - -struct ehNode { - struct ehEntry *entry; - struct ehNode *chain; -}; - -struct ehStack { - struct ehNode *top; -}; - -struct ehQueue { - struct ehNode *head; - struct ehNode *tail; -}; /* ========================================================================= */ @@ -313,1182 +181,901 @@ struct ehQueue { ========================================================================= */ -/* Holds the pc for doing "throw" */ -tree saved_pc; -/* Holds the type of the thing being thrown. */ -tree saved_throw_type; -/* Holds the value being thrown. */ -tree saved_throw_value; - -int throw_used; +extern rtx catch_clauses; +extern tree const_ptr_type_node; -static rtx catch_clauses; -static first_catch_label; - -static struct ehStack ehstack; -static struct ehQueue ehqueue; -static struct ehQueue eh_table_output_queue; -static struct labelNode *false_label_stack = NULL; -static struct labelNode *caught_return_label_stack = NULL; /* ========================================================================= */ -/* function prototypes */ -static struct ehEntry *pop_eh_entry PROTO((struct ehStack *stack)); -static void enqueue_eh_entry PROTO((struct ehQueue *queue, struct ehEntry *entry)); -static rtx push_eh_entry PROTO((struct ehStack *stack)); -static struct ehEntry *dequeue_eh_entry PROTO((struct ehQueue *queue)); -static void new_eh_queue PROTO((struct ehQueue *queue)); -static void new_eh_stack PROTO((struct ehStack *stack)); -static void push_label_entry PROTO((struct labelNode **labelstack, rtx label)); -static rtx pop_label_entry PROTO((struct labelNode **labelstack)); -static rtx top_label_entry PROTO((struct labelNode **labelstack)); -static struct ehEntry *copy_eh_entry PROTO((struct ehEntry *entry)); +/* sets up all the global eh stuff that needs to be initialized at the + start of compilation. + This includes: + - Setting up all the function call trees. */ +void +init_exception_processing () +{ + /* void vtype () */ + tree vtype = build_function_type (void_type_node, void_list_node); + + if (flag_honor_std) + push_namespace (get_identifier ("std")); + Terminate = auto_function (get_identifier ("terminate"), + vtype, NOT_BUILT_IN); + TREE_THIS_VOLATILE (Terminate) = 1; + if (flag_honor_std) + pop_namespace (); -/* All my cheesy stack/queue/misc data structure handling routines + push_lang_context (lang_name_c); - ========================================================================= */ + set_exception_lang_code (EH_LANG_C_plus_plus); + set_exception_version_code (1); + + CatchMatch + = builtin_function (flag_rtti + ? "__throw_type_match_rtti" + : "__throw_type_match", + build_function_type (ptr_type_node, + tree_cons (NULL_TREE, const_ptr_type_node, + tree_cons (NULL_TREE, const_ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)))), + NOT_BUILT_IN, NULL_PTR); + FirstExceptionMatch + = builtin_function ("__find_first_exception_table_match", + build_function_type (ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)), + NOT_BUILT_IN, NULL_PTR); + Unwind + = builtin_function ("__unwind_function", + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)), + NOT_BUILT_IN, NULL_PTR); -static void -push_label_entry (labelstack, label) - struct labelNode **labelstack; - rtx label; -{ - struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode)); + pop_lang_context (); - newnode->label = label; - newnode->chain = *labelstack; - *labelstack = newnode; + /* If we use setjmp/longjmp EH, arrange for all cleanup actions to + be protected with __terminate. */ + protect_cleanup_actions_with_terminate = 1; } -static rtx -pop_label_entry (labelstack) - struct labelNode **labelstack; -{ - rtx label; - struct labelNode *tempnode; - - if (! *labelstack) return NULL_RTX; +/* Retrieve a pointer to the cp_eh_info node for the current exception. */ - tempnode = *labelstack; - label = tempnode->label; - *labelstack = (*labelstack)->chain; - free (tempnode); +static tree +call_eh_info () +{ + tree fn; - return label; + fn = get_identifier ("__cp_eh_info"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree t1, t, fields[7]; + + /* Declare cp_eh_info * __cp_eh_info (void), + as defined in exception.cc. */ + push_obstacks_nochange (); + end_temporary_allocation (); + + /* struct cp_eh_info. This must match exception.cc. Note that this + type is not pushed anywhere. */ + t1= make_lang_type (RECORD_TYPE); + fields[0] = build_lang_field_decl (FIELD_DECL, + get_identifier ("handler_label"), ptr_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, + get_identifier ("dynamic_handler_chain"), ptr_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, + get_identifier ("info"), 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); + t1 = build_pointer_type (t1); + + t1= make_lang_type (RECORD_TYPE); + fields[0] = build_lang_field_decl (FIELD_DECL, + get_identifier ("match_function"), ptr_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, + get_identifier ("language"), short_integer_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, + get_identifier ("version"), short_integer_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_info", fields, 2, ptr_type_node); + t = make_lang_type (RECORD_TYPE); + fields[0] = build_lang_field_decl (FIELD_DECL, + get_identifier ("eh_info"), t1); + fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"), + ptr_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), + ptr_type_node); + fields[3] = build_lang_field_decl + (FIELD_DECL, get_identifier ("cleanup"), + build_pointer_type (build_function_type + (ptr_type_node, tree_cons + (NULL_TREE, ptr_type_node, void_list_node)))); + fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"), + boolean_type_node); + fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"), + build_pointer_type (t)); + fields[6] = build_lang_field_decl + (FIELD_DECL, get_identifier ("handlers"), long_integer_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 (t, "cp_eh_info", fields, 6, ptr_type_node); + t = build_pointer_type (t); + + /* And now the function. */ + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (t, void_list_node)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + return build_function_call (fn, NULL_TREE); } -static rtx -top_label_entry (labelstack) - struct labelNode **labelstack; -{ - if (! *labelstack) return NULL_RTX; +/* Retrieve a pointer to the cp_eh_info node for the current exception + and save it in the current binding level. */ - return (*labelstack)->label; +static void +push_eh_info () +{ + tree decl, fn = call_eh_info (); + + /* Remember the pointer to the current exception info; it won't change + during this catch block. */ + decl = build_decl (VAR_DECL, get_identifier ("__exception_info"), + TREE_TYPE (fn)); + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = fn; + decl = pushdecl (decl); + cp_finish_decl (decl, fn, NULL_TREE, 0, 0); } -/* Push to permanent obstack for rtl generation. - One level only! */ -static struct obstack *saved_rtl_obstack; -void -push_rtl_perm () +/* Returns a reference to the cp_eh_info node for the current exception. */ + +static tree +get_eh_info () { - extern struct obstack permanent_obstack; - extern struct obstack *rtl_obstack; - - saved_rtl_obstack = rtl_obstack; - rtl_obstack = &permanent_obstack; + /* Look for the pointer pushed in push_eh_info. */ + tree t = lookup_name (get_identifier ("__exception_info"), 0); + return build_indirect_ref (t, NULL_PTR); } -/* Pop back to normal rtl handling. */ -static void -pop_rtl_from_perm () +/* Returns a reference to the current exception object. */ + +static tree +get_eh_value () { - extern struct obstack permanent_obstack; - extern struct obstack *rtl_obstack; - - rtl_obstack = saved_rtl_obstack; + return build_component_ref (get_eh_info (), get_identifier ("value"), + NULL_TREE, 0); } -static rtx -push_eh_entry (stack) - struct ehStack *stack; +/* Returns a reference to the current exception type. */ + +static tree +get_eh_type () { - struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode)); - struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry)); + return build_component_ref (get_eh_info (), get_identifier ("type"), + NULL_TREE, 0); +} - if (stack == NULL) { - free (node); - free (entry); - return NULL_RTX; - } +/* Returns a reference to whether or not the current exception + has been caught. */ - /* These are saved for the exception table. */ - push_rtl_perm (); - entry->start_label = gen_label_rtx (); - entry->end_label = gen_label_rtx (); - entry->exception_handler_label = gen_label_rtx (); - pop_rtl_from_perm (); +static tree +get_eh_caught () +{ + return build_component_ref (get_eh_info (), get_identifier ("caught"), + NULL_TREE, 0); +} - LABEL_PRESERVE_P (entry->start_label) = 1; - LABEL_PRESERVE_P (entry->end_label) = 1; - LABEL_PRESERVE_P (entry->exception_handler_label) = 1; +/* Returns a reference to whether or not the current exception + has been caught. */ - entry->finalization = NULL_TREE; - entry->context = current_function_decl; +static tree +get_eh_handlers () +{ + return build_component_ref (get_eh_info (), get_identifier ("handlers"), + NULL_TREE, 0); +} - node->entry = entry; - node->chain = stack->top; - stack->top = node; +/* Build a type value for use at runtime for a type that is matched + against by the exception handling system. */ - enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry)); +static tree +build_eh_type_type (type) + tree type; +{ + char *typestring; + tree exp; - return entry->start_label; -} + if (type == error_mark_node) + return error_mark_node; -static struct ehEntry * -pop_eh_entry (stack) - struct ehStack *stack; -{ - struct ehNode *tempnode; - struct ehEntry *tempentry; + /* peel back references, so they match. */ + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); - if (stack && (tempnode = stack->top)) { - tempentry = tempnode->entry; - stack->top = stack->top->chain; - free (tempnode); + /* Peel off cv qualifiers. */ + type = TYPE_MAIN_VARIANT (type); - return tempentry; - } + if (flag_rtti) + { + return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type)); + } - return NULL; + typestring = build_overload_name (type, 1, 1); + exp = combine_strings (build_string (strlen (typestring)+1, typestring)); + return build1 (ADDR_EXPR, ptr_type_node, exp); } -static struct ehEntry * -copy_eh_entry (entry) - struct ehEntry *entry; +/* Build the address of a runtime type for use in the runtime matching + field of the new exception model */ + +static tree +build_eh_type_type_ref (type) + tree type; { - struct ehEntry *newentry; + char *typestring; + tree exp; - newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry)); - memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry)); + if (type == error_mark_node) + return error_mark_node; - return newentry; -} + /* peel back references, so they match. */ + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); -static void -enqueue_eh_entry (queue, entry) - struct ehQueue *queue; - struct ehEntry *entry; -{ - struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode)); + /* Peel off cv qualifiers. */ + type = TYPE_MAIN_VARIANT (type); - node->entry = entry; - node->chain = NULL; + push_obstacks_nochange (); + end_temporary_allocation (); - if (queue->head == NULL) + if (flag_rtti) { - queue->head = node; + exp = get_tinfo_fn (type); + TREE_USED (exp) = 1; + mark_inline_for_output (exp); + exp = build1 (ADDR_EXPR, ptr_type_node, exp); } else { - queue->tail->chain = node; + typestring = build_overload_name (type, 1, 1); + exp = combine_strings (build_string (strlen (typestring)+1, typestring)); + exp = build1 (ADDR_EXPR, ptr_type_node, exp); } - queue->tail = node; + pop_obstacks (); + return (exp); } -static struct ehEntry * -dequeue_eh_entry (queue) - struct ehQueue *queue; -{ - struct ehNode *tempnode; - struct ehEntry *tempentry; - - if (queue->head == NULL) - return NULL; - tempnode = queue->head; - queue->head = queue->head->chain; - - tempentry = tempnode->entry; - free (tempnode); - - return tempentry; -} +/* Build a type value for use at runtime for a exp that is thrown or + matched against by the exception handling system. */ -static void -new_eh_queue (queue) - struct ehQueue *queue; +static tree +build_eh_type (exp) + tree exp; { - queue->head = queue->tail = NULL; + if (flag_rtti) + { + exp = build_typeid (exp); + return build1 (ADDR_EXPR, ptr_type_node, exp); + } + return build_eh_type_type (TREE_TYPE (exp)); } -static void -new_eh_stack (stack) - struct ehStack *stack; +/* This routine is called to mark all the symbols representing runtime + type functions in the exception table as haveing been referenced. + This will make sure code is emitted for them. Called from finish_file. */ +void +mark_all_runtime_matches () { - stack->top = NULL; + int x,num; + void **ptr; + tree exp; + + num = find_all_handler_type_matches (&ptr); + if (num == 0 || ptr == NULL) + return; + + for (x=0; x end_label); - /* Put in something that takes up space, as otherwise the end - address for the EH region could have the exact same address as - the outer region, causing us to miss the fact that resuming - exception handling with this PC value would be inside the outer - region. */ - emit_insn (gen_nop ()); - - entry->finalization = finalization; - - enqueue_eh_entry (&ehqueue, entry); -} + if (processing_template_decl) + { + if (declspecs) + { + decl = grokdeclarator (declarator, declspecs, CATCHPARM, + 1, NULL_TREE); + pushdecl (decl); + decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator), + copy_to_permanent (declspecs), + NULL_TREE); + add_tree (decl); + } + return; + } -/* call this on start of a try block. */ -void -expand_start_try_stmts () -{ if (! doing_eh (1)) return; - start_protect (); + if (flag_new_exceptions) + process_start_catch_block (declspecs, declarator); + else + process_start_catch_block_old (declspecs, declarator); } -void -expand_end_try_stmts () -{ - end_protect (integer_zero_node); -} +/* 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. */ -/* call this to start processing of all the catch blocks. */ -void -expand_start_all_catch () +static void +process_start_catch_block_old (declspecs, declarator) + tree declspecs, declarator; { - struct ehEntry *entry; - rtx label; + rtx false_label_rtx; + tree decl = NULL_TREE; + tree init; - if (! doing_eh (1)) - return; + /* 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); - label = gen_label_rtx (); - /* The label for the exception handling block we will save. This is - Lresume, in the documention. */ - emit_label (label); - - /* Put in something that takes up space, as otherwise the end - address for the EH region could have the exact same address as - the outer region, causing us to miss the fact that resuming - exception handling with this PC value would be inside the outer - region. */ - emit_insn (gen_nop ()); + push_eh_info (); - push_label_entry (&caught_return_label_stack, label); + if (declspecs) + { + decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE); - /* Start a new sequence for all the catch blocks. We will add this - to the gloabl sequence catch_clauses, when we have completed all - the handlers in this handler-seq. */ - start_sequence (); + if (decl == NULL_TREE) + error ("invalid catch parameter"); + } - while (1) + if (decl) { - entry = dequeue_eh_entry (&ehqueue); - emit_label (entry->exception_handler_label); - - expand_expr (entry->finalization, const0_rtx, VOIDmode, 0); - - /* When we get down to the matching entry, stop. */ - if (entry->finalization == integer_zero_node) - break; - - /* The below can be optimized away, and we could just fall into the - next EH handler, if we are certain they are nested. */ - /* Code to throw out to outer context, if we fall off end of the - handler. */ - expand_internal_throw (gen_rtx (LABEL_REF, - Pmode, - entry->end_label)); - free (entry); - } -} + tree exp; + rtx call_rtx, return_value_rtx; + tree init_type; -/* call this to end processing of all the catch blocks. */ -void -expand_end_all_catch () -{ - rtx new_catch_clause; + /* Make sure we mark the catch param as used, otherwise we'll get + a warning about an unused ((anonymous)). */ + TREE_USED (decl) = 1; - if (! doing_eh (1)) - return; + /* 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); - /* 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 - documentation. */ - expand_internal_throw (gen_rtx (LABEL_REF, - Pmode, - top_label_entry (&caught_return_label_stack))); + exp = get_eh_value (); - /* Now we have the complete catch sequence. */ - new_catch_clause = get_insns (); - end_sequence (); - - /* this level of catch blocks is done, so set up the successful catch jump - label for the next layer of catch blocks. */ - pop_label_entry (&caught_return_label_stack); + /* 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); - /* Add the new sequence of catchs to the main one for this - function. */ - push_to_sequence (catch_clauses); - emit_insns (new_catch_clause); - catch_clauses = get_insns (); - end_sequence (); - - /* Here we fall through into the continuation code. */ -} + 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); -/* Build a type value for use at runtime for a type that is matched - against by the exception handling system. */ -static tree -build_eh_type_type (type) - tree type; -{ - char *typestring; - tree exp; + return_value_rtx = hard_function_value (ptr_type_node, exp); - if (type == error_mark_node) - return error_mark_node; + /* 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); - /* peel back references, so they match. */ - if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); + /* if it returned FALSE, jump over the catch block, else fall into it */ + emit_jump_insn (gen_beq (false_label_rtx)); - /* Peel off cv qualifiers. */ - type = TYPE_MAIN_VARIANT (type); + push_eh_cleanup (); - if (flag_rtti) - { - return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type)); - } + /* Create a binding level for the parm. */ + pushlevel (0); + expand_start_bindings (0); - typestring = build_overload_name (type, 1, 1); - exp = combine_strings (build_string (strlen (typestring)+1, typestring)); - return build1 (ADDR_EXPR, ptr_type_node, exp); -} + init = convert_from_reference (make_tree (init_type, call_rtx)); -/* Build a type value for use at runtime for a exp that is thrown or - matched against by the exception handling system. */ -static tree -build_eh_type (exp) - tree exp; -{ - if (flag_rtti) + /* 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 { - exp = build_typeid (exp); - return build1 (ADDR_EXPR, ptr_type_node, exp); + push_eh_cleanup (); + + /* Create a binding level for the parm. */ + pushlevel (0); + expand_start_bindings (0); + + /* Fall into the catch all section. */ } - return build_eh_type_type (TREE_TYPE (exp)); + + 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 start a catch block. Typename is the typename, and identifier - is the variable to place the object in or NULL if the variable doesn't - matter. If typename is NULL, that means its a "catch (...)" or catch - everything. In that case we don't need to do any type checking. - (ie: it ends up as the "else" clause rather than an "else if" clause) */ -void -expand_start_catch_block (declspecs, declarator) +/* 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. */ + +static void +process_start_catch_block (declspecs, declarator) tree declspecs, declarator; { - rtx false_label_rtx; - rtx protect_label_rtx; tree decl = NULL_TREE; tree init; - if (! doing_eh (1)) - return; - - /* Create a binding level for the parm. */ + /* 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 (); - /* This is saved for the exception table. */ - push_rtl_perm (); - protect_label_rtx = gen_label_rtx (); - pop_rtl_from_perm (); - push_label_entry (&false_label_stack, false_label_rtx); - push_label_entry (&false_label_stack, protect_label_rtx); if (declspecs) { + decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE); + + if (decl == NULL_TREE) + error ("invalid catch parameter"); + } + + if (decl) + start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl))); + else + start_catch_handler (CATCH_ALL_TYPE); + + emit_line_note (input_filename, lineno); + + push_eh_info (); + + if (decl) + { tree exp; - rtx call_rtx, return_value_rtx; tree init_type; - decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, - NULL_TREE, NULL_TREE); + /* Make sure we mark the catch param as used, otherwise we'll get + a warning about an unused ((anonymous)). */ + TREE_USED (decl) = 1; - if (decl == NULL_TREE) - { - error ("invalid catch parameter"); - return; - } - - /* Figure out the type that the initializer is. */ + /* 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 = saved_throw_value; - exp = tree_cons (NULL_TREE, - build_eh_type_type (TREE_TYPE (decl)), - tree_cons (NULL_TREE, - saved_throw_type, - tree_cons (NULL_TREE, exp, NULL_TREE))); - exp = build_function_call (CatchMatch, exp); - call_rtx = expand_call (exp, NULL_RTX, 0); - assemble_external (TREE_OPERAND (CatchMatch, 0)); + exp = get_eh_value (); - return_value_rtx = hard_function_value (ptr_type_node, exp); + /* 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); - /* 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); + exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 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 (exp); - init = convert_from_reference (save_expr (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 ()); + } - /* Do we need the below two lines? */ /* Let `cp_finish_decl' know that this initializer is ok. */ DECL_INITIAL (decl) = init; decl = pushdecl (decl); + cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } else { - /* Fall into the catch all section. */ + push_eh_cleanup (); + + /* Create a binding level for the parm. */ + pushlevel (0); + expand_start_bindings (0); + + /* Fall into the catch all section. */ } - /* This is the starting of something to protect. */ - emit_label (protect_label_rtx); + 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 is called from expand_exception_blocks and - expand_end_catch_block to expand the toplevel finalizations for a - function. We return the first label emitted, if any, otherwise - return NULL_RTX. */ -static rtx -expand_leftover_cleanups () -{ - struct ehEntry *entry; - rtx first_label = NULL_RTX; - - while ((entry = dequeue_eh_entry (&ehqueue)) != 0) - { - if (! first_label) - first_label = entry->exception_handler_label; - emit_label (entry->exception_handler_label); - - expand_expr (entry->finalization, const0_rtx, VOIDmode, 0); - - /* The below can be optimized away, and we could just fall into the - next EH handler, if we are certain they are nested. */ - /* Code to throw out to outer context, if we fall off end of the - handler. */ - expand_internal_throw (gen_rtx (LABEL_REF, - Pmode, - entry->end_label)); - - /* leftover try block, opps. */ - if (entry->finalization == integer_zero_node) - abort (); - - free (entry); - } - - return first_label; -} /* 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. */ -void expand_end_catch_block () -{ - rtx start_protect_label_rtx; - rtx end_protect_label_rtx; - tree decls; - struct ehEntry entry; +void +expand_end_catch_block () +{ if (! doing_eh (1)) return; - /* fall to outside the try statement when done executing handler and + /* Cleanup the EH parameter. */ + expand_end_bindings (getdecls (), kept_level_p (), 0); + poplevel (kept_level_p (), 1, 0); + + /* Cleanup the EH object. */ + expand_end_bindings (getdecls (), kept_level_p (), 0); + poplevel (kept_level_p (), 1, 0); + + /* Fall to outside the try statement when done executing handler and we fall off end of handler. This is jump Lresume in the documentation. */ - emit_jump (top_label_entry (&caught_return_label_stack)); - - /* We end the rethrow protection region as soon as we hit a label. */ - end_protect_label_rtx = expand_leftover_cleanups (); - - /* Code to throw out to outer context, if we get a throw from within - our catch handler. */ - /* These are saved for the exception table. */ - push_rtl_perm (); - entry.exception_handler_label = gen_label_rtx (); - pop_rtl_from_perm (); - /* This label is Lhandler in the documentation. */ - emit_label (entry.exception_handler_label); - expand_internal_throw (gen_rtx (LABEL_REF, - Pmode, - top_label_entry (&caught_return_label_stack))); - - /* No associated finalization. */ - entry.finalization = NULL_TREE; - entry.context = current_function_decl; - - if (end_protect_label_rtx == NULL_RTX) - end_protect_label_rtx = entry.exception_handler_label; - - /* Because we are emitted out of line, we have to protect this. */ - /* label for the start of the protection region. */ - start_protect_label_rtx = pop_label_entry (&false_label_stack); + expand_goto (top_label_entry (&caught_return_label_stack)); - /* Cleanup the EH parameter. */ - decls = getdecls (); - expand_end_bindings (decls, decls != NULL_TREE, 0); - - /* label we emit to jump to if this catch block didn't match. */ + /* label we emit to jump to if this catch block didn't match. */ /* This the closing } in the `if (eq) {' of the documentation. */ - emit_label (pop_label_entry (&false_label_stack)); + if (! flag_new_exceptions) + emit_label (pop_label_entry (&false_label_stack)); +} + +/* An exception spec is implemented more or less like: - /* Because we are reordered out of line, we have to protect this. */ - entry.start_label = start_protect_label_rtx; - entry.end_label = end_protect_label_rtx; + try { + function body; + } catch (...) { + void *p[] = { typeid(raises) }; + __check_eh_spec (p, count); + } - LABEL_PRESERVE_P (entry.start_label) = 1; - LABEL_PRESERVE_P (entry.end_label) = 1; - LABEL_PRESERVE_P (entry.exception_handler_label) = 1; + __check_eh_spec in exception.cc handles all the details. */ - /* These set up a call to throw the caught exception into the outer - context. */ - enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry)); +void +expand_start_eh_spec () +{ + expand_start_try_stmts (); } -/* unwind the stack. */ static void -do_unwind (inner_throw_label) - rtx inner_throw_label; +expand_end_eh_spec (raises) + tree raises; { -#if defined(SPARC_STACK_ALIGN) /* was sparc */ - tree fcall; - tree params; - rtx return_val_rtx; - rtx temp; - - /* call to __builtin_return_address () */ - params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); - fcall = build_function_call (BuiltinReturnAddress, params); - return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); - /* In the return, the new pc is pc+8, as the value coming in is - really the address of the call insn, not the next insn. */ - temp = gen_reg_rtx (Pmode); - emit_move_insn (temp, inner_throw_label); - emit_move_insn (return_val_rtx, plus_constant (temp, -8)); - easy_expand_asm ("ret"); - easy_expand_asm ("restore"); - emit_barrier (); -#endif -#if defined(ARM_FRAME_RTX) /* was __arm */ - if (flag_omit_frame_pointer) - sorry ("this implementation of exception handling requires a frame pointer"); - - emit_move_insn (stack_pointer_rtx, - gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8))); - emit_move_insn (hard_frame_pointer_rtx, - gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12))); -#endif -#if defined(TARGET_88000) /* was m88k */ - rtx temp_frame = frame_pointer_rtx; + tree tmp, fn, decl, types = NULL_TREE; + int count = 0; - temp_frame = memory_address (Pmode, temp_frame); - temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame)); + expand_start_all_catch (); + expand_start_catch_block (NULL_TREE, NULL_TREE); - /* hopefully this will successfully pop the frame! */ - emit_move_insn (frame_pointer_rtx, temp_frame); - emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); - emit_move_insn (arg_pointer_rtx, frame_pointer_rtx); - emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode, - (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0)))); + /* Build up an array of type_infos. */ + for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises)) + { + types = expr_tree_cons + (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types); + ++count; + } -#if 0 - emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode, - -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0)))); + types = build_nt (CONSTRUCTOR, NULL_TREE, types); + TREE_HAS_CONSTRUCTOR (types) = 1; - emit_move_insn (stack_pointer_rtx, arg_pointer_rtx); + /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */ + tmp = build_array_type (const_ptr_type_node, NULL_TREE); + decl = build_decl (VAR_DECL, NULL_TREE, tmp); + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = types; + cp_finish_decl (decl, types, NULL_TREE, 0, 0); - emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode, - (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0)))); -#endif -#endif -#if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN) - tree fcall; - tree params; - rtx return_val_rtx; + decl = decay_conversion (decl); - /* call to __builtin_return_address () */ - params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); - fcall = build_function_call (BuiltinReturnAddress, params); - return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); -#if 0 - /* I would like to do this here, but doesn't seem to work. */ - emit_move_insn (return_val_rtx, inner_throw_label); - /* So, for now, just pass throw label to stack unwinder. */ -#endif - params = tree_cons (NULL_TREE, make_tree (ptr_type_node, - inner_throw_label), NULL_TREE); + fn = get_identifier ("__check_eh_spec"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + push_obstacks_nochange (); + end_temporary_allocation (); + + tmp = tree_cons + (NULL_TREE, integer_type_node, tree_cons + (NULL_TREE, TREE_TYPE (decl), void_list_node)); + tmp = build_function_type (void_type_node, tmp); - do_function_call (Unwind, params, NULL_TREE); - assemble_external (TREE_OPERAND (Unwind, 0)); - emit_barrier (); -#endif + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + TREE_THIS_VOLATILE (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + 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); + expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); + + expand_end_catch_block (); + expand_end_all_catch (); } +/* This is called to expand all the toplevel exception handling + finalization for a function. It should only be called once per + function. */ -/* is called from expand_exception_blocks () to generate the code in a function - to "throw" if anything in the function needs to perform a throw. +void +expand_exception_blocks () +{ + do_pending_stack_adjust (); + push_to_sequence (catch_clauses); + expand_leftover_cleanups (); + do_pending_stack_adjust (); + catch_clauses = get_insns (); + end_sequence (); - expands "throw" as the following pseudo code: + /* Do this after we expand leftover cleanups, so that the + expand_eh_region_end that expand_end_eh_spec does will match the + right expand_eh_region_start, and make sure it comes out before + the terminate protected region. */ + if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) + { + expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))); + do_pending_stack_adjust (); + push_to_sequence (catch_clauses); + expand_leftover_cleanups (); + do_pending_stack_adjust (); + catch_clauses = get_insns (); + end_sequence (); + } - throw: - eh = find_first_exception_match (saved_pc); - if (!eh) goto gotta_rethrow_it; - goto eh; + if (catch_clauses) + { + rtx funcend = gen_label_rtx (); + emit_jump (funcend); - gotta_rethrow_it: - saved_pc = __builtin_return_address (0); - pop_to_previous_level (); - goto throw; + /* We cannot protect n regions this way if we must flow into the + EH region through the top of the region, as we have to with + the setjmp/longjmp approach. */ + if (exceptions_via_longjmp == 0) + expand_eh_region_start (); - */ -void -expand_builtin_throw () + emit_insns (catch_clauses); + catch_clauses = NULL_RTX; + + if (exceptions_via_longjmp == 0) + expand_eh_region_end (build_terminate_handler ()); + + expand_leftover_cleanups (); + + emit_label (funcend); + } +} + +tree +start_anon_func () { - tree fcall; + static int counter = 0; + int old_interface_unknown = interface_unknown; + char name[32]; tree params; - rtx return_val_rtx; - rtx gotta_rethrow_it; - rtx gotta_call_terminate; - rtx unwind_and_throw; - rtx goto_unwind_and_throw; - rtx top_of_loop; - rtx unwind_first; tree t; - if (! doing_eh (0)) - return; + push_cp_function_context (NULL_TREE); + push_to_top_level (); - if (! throw_used) - return; + /* No need to mangle this. */ + push_lang_context (lang_name_c); + + interface_unknown = 1; params = void_list_node; - t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE); + /* tcf stands for throw clean function. */ + sprintf (name, "__tcf_%d", counter++); + t = make_call_declarator (get_identifier (name), params, NULL_TREE, + NULL_TREE); start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"), void_list_node), - t, NULL_TREE, NULL_TREE, 0); + t, NULL_TREE, 0); store_parm_decls (); pushlevel (0); clear_last_expr (); push_momentary (); expand_start_bindings (0); + emit_line_note (input_filename, lineno); - gotta_rethrow_it = gen_label_rtx (); - gotta_call_terminate = gen_label_rtx (); - unwind_and_throw = gen_label_rtx (); - goto_unwind_and_throw = gen_label_rtx (); - top_of_loop = gen_label_rtx (); - unwind_first = gen_label_rtx (); - - emit_jump (unwind_first); - - emit_label (top_of_loop); - - /* search for an exception handler for the saved_pc */ - return_val_rtx = do_function_call (FirstExceptionMatch, - tree_cons (NULL_TREE, saved_pc, NULL_TREE), - ptr_type_node); - assemble_external (TREE_OPERAND (FirstExceptionMatch, 0)); - - /* did we find one? */ - emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX, - GET_MODE (return_val_rtx), 0, 0); - - /* if not, jump to gotta_rethrow_it */ - emit_jump_insn (gen_beq (gotta_rethrow_it)); - - /* we found it, so jump to it */ - emit_indirect_jump (return_val_rtx); - - /* code to deal with unwinding and looking for it again */ - emit_label (gotta_rethrow_it); - - /* call to __builtin_return_address () */ -#if defined(ARM_FRAME_RTX) /* was __arm */ -/* This replaces a 'call' to __builtin_return_address */ - return_val_rtx = gen_reg_rtx (Pmode); - emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4))); -#else - params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); - fcall = build_function_call (BuiltinReturnAddress, params); - return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); -#endif - - /* did __builtin_return_address () return a valid address? */ - emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX, - GET_MODE (return_val_rtx), 0, 0); - - emit_jump_insn (gen_beq (gotta_call_terminate)); - -#if defined(ARM_FRAME_RTX) /* was __arm */ - /* On the ARM, '__builtin_return_address', must have 4 - subtracted from it. */ - emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4))); - - /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit - mode, the condition codes must be masked out of the return value, or else - they will confuse BuiltinReturnAddress. This does not apply to ARM6 and - later processors when running in 32 bit mode. */ - if (!TARGET_6) - emit_insn (gen_rtx (SET, Pmode, return_val_rtx, gen_rtx (AND, Pmode, return_val_rtx, GEN_INT (0x03fffffc)))); -#else -#if !defined(SPARC_STACK_ALIGN) /* was sparc */ - /* On the SPARC, __builtin_return_address is already -8, no need to - subtract any more from it. */ - return_val_rtx = plus_constant (return_val_rtx, -1); -#endif -#endif + interface_unknown = old_interface_unknown; - /* yes it did */ - t = build_modify_expr (saved_pc, NOP_EXPR, make_tree (ptr_type_node, return_val_rtx)); - expand_expr (t, const0_rtx, VOIDmode, 0); - - do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop)); - emit_jump (top_of_loop); - - /* no it didn't --> therefore we need to call terminate */ - emit_label (gotta_call_terminate); - do_function_call (Terminate, NULL_TREE, NULL_TREE); - assemble_external (TREE_OPERAND (Terminate, 0)); - - { - rtx ret_val, return_val_rtx; - emit_label (unwind_first); - ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, - 0, hard_frame_pointer_rtx); - - /* Set it up so that we continue inside, at the top of the loop. */ - emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop)); -#ifdef NORMAL_RETURN_ADDR_OFFSET - return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET); - if (return_val_rtx != ret_val) - emit_move_insn (ret_val, return_val_rtx); -#endif + pop_lang_context (); - /* Fall into epilogue to unwind prologue. */ - } + return current_function_decl; +} - expand_end_bindings (getdecls(), 1, 0); +void +end_anon_func () +{ + expand_end_bindings (getdecls (), 1, 0); poplevel (1, 0, 0); pop_momentary (); finish_function (lineno, 0, 0); -} - -void -expand_start_eh_spec () -{ - start_protect (); + pop_from_top_level (); + pop_cp_function_context (NULL_TREE); } -void -expand_end_eh_spec (raises) - tree raises; -{ - tree expr, second_try; - rtx check = gen_label_rtx (); - rtx cont; - rtx ret = gen_reg_rtx (Pmode); - rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node)); - rtx end = gen_label_rtx (); - - expr = make_node (RTL_EXPR); - TREE_TYPE (expr) = void_type_node; - RTL_EXPR_RTL (expr) = const0_rtx; - TREE_SIDE_EFFECTS (expr) = 1; - start_sequence_for_rtl_expr (expr); - cont = gen_label_rtx (); - emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont)); - emit_jump (check); - emit_label (cont); - jumpif (make_tree (integer_type_node, flag), end); - do_function_call (Terminate, NULL_TREE, NULL_TREE); - assemble_external (TREE_OPERAND (Terminate, 0)); - emit_barrier (); - RTL_EXPR_SEQUENCE (expr) = get_insns (); - end_sequence (); - - second_try = expr; - - expr = make_node (RTL_EXPR); - TREE_TYPE (expr) = void_type_node; - RTL_EXPR_RTL (expr) = const0_rtx; - TREE_SIDE_EFFECTS (expr) = 1; - start_sequence_for_rtl_expr (expr); - - cont = gen_label_rtx (); - emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont)); - emit_jump (check); - emit_label (cont); - jumpif (make_tree (integer_type_node, flag), end); - start_protect (); - do_function_call (Unexpected, NULL_TREE, NULL_TREE); - assemble_external (TREE_OPERAND (Unexpected, 0)); - emit_barrier (); - end_protect (second_try); - - emit_label (check); - emit_move_insn (flag, const1_rtx); - cont = gen_label_rtx (); - while (raises) - { - tree exp; - tree match_type = TREE_VALUE (raises); - - if (match_type) - { - /* check TREE_VALUE (raises) here */ - exp = saved_throw_value; - exp = tree_cons (NULL_TREE, - build_eh_type_type (match_type), - tree_cons (NULL_TREE, - saved_throw_type, - tree_cons (NULL_TREE, exp, NULL_TREE))); - exp = build_function_call (CatchMatch, exp); - assemble_external (TREE_OPERAND (CatchMatch, 0)); - - jumpif (exp, cont); - } - - raises = TREE_CHAIN (raises); - } - emit_move_insn (flag, const0_rtx); - emit_label (cont); - emit_indirect_jump (ret); - emit_label (end); - - RTL_EXPR_SEQUENCE (expr) = get_insns (); - end_sequence (); - - end_protect (expr); -} +/* Return a pointer to a buffer for an exception object of type TYPE. */ -/* This is called to expand all the toplevel exception handling - finalization for a function. It should only be called once per - function. */ -void -expand_exception_blocks () +static tree +alloc_eh_object (type) + tree type; { - static rtx funcend; - rtx insns; - - start_sequence (); - - funcend = gen_label_rtx (); - emit_jump (funcend); - /* expand_null_return (); */ - - start_sequence (); - - /* Add all the catch clauses here. */ - emit_insns (catch_clauses); - catch_clauses = NULL_RTX; + tree fn, exp; - expand_leftover_cleanups (); - - insns = get_insns (); - end_sequence (); - - /* Do this after we expand leftover cleanups, so that the end_protect - that expand_end_eh_spec does will match the right start_protect, - and make sure it comes out before the terminate protected region. */ - if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) - { - expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))); - push_to_sequence (insns); - - /* Now expand any new ones. */ - expand_leftover_cleanups (); - - insns = get_insns (); - end_sequence (); - } - - if (insns) + fn = get_identifier ("__eh_alloc"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else { - struct ehEntry entry; - - /* These are saved for the exception table. */ - push_rtl_perm (); - entry.start_label = gen_label_rtx (); - entry.end_label = gen_label_rtx (); - entry.exception_handler_label = gen_label_rtx (); - entry.finalization = TerminateFunctionCall; - entry.context = current_function_decl; - assemble_external (TREE_OPERAND (Terminate, 0)); - pop_rtl_from_perm (); - - LABEL_PRESERVE_P (entry.start_label) = 1; - LABEL_PRESERVE_P (entry.end_label) = 1; - LABEL_PRESERVE_P (entry.exception_handler_label) = 1; - - emit_label (entry.start_label); - emit_insns (insns); - - enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry)); - - emit_label (entry.exception_handler_label); - expand_expr (entry.finalization, const0_rtx, VOIDmode, 0); - emit_label (entry.end_label); - emit_barrier (); + /* Declare __eh_alloc (size_t), as defined in exception.cc. */ + tree tmp; + push_obstacks_nochange (); + end_temporary_allocation (); + tmp = tree_cons (NULL_TREE, sizetype, void_list_node); + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (ptr_type_node, tmp)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); } - { - /* Mark the end of the stack unwinder. */ - rtx unwind_insns; - start_sequence (); - end_eh_unwinder (funcend); - expand_leftover_cleanups (); - unwind_insns = get_insns (); - end_sequence (); - if (unwind_insns) - { - insns = unwind_insns; - emit_insns (insns); - } - } - - emit_label (funcend); - - /* Only if we had previous insns do we want to emit the jump around - them. If there weren't any, then insns will remain NULL_RTX. */ - if (insns) - insns = get_insns (); - end_sequence (); - - emit_insns (insns); + 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); + return exp; } - -/* call this to expand a throw statement. This follows the following +/* Expand a throw statement. This follows the following algorithm: 1. Allocate space to save the current PC onto the stack. @@ -1497,30 +1084,40 @@ expand_exception_blocks () 3. If this is the first call to throw in this function: generate a label for the throw block 4. jump to the throw block label. */ + void expand_throw (exp) tree exp; { - rtx label; + tree fn; + static tree cleanup_type; if (! doing_eh (1)) return; - /* This is the label that represents where in the code we were, when - we got an exception. This needs to be updated when we rethrow an - exception, so that the matching routine knows to search out. */ - label = gen_label_rtx (); - emit_label (label); - if (exp) { tree throw_type; - tree e; + tree cleanup = NULL_TREE, e; /* throw expression */ - /* First, decay it. */ + /* First, decay it. */ exp = decay_conversion (exp); + /* cleanup_type is void (*)(void *, int), + the internal type of a destructor. */ + if (cleanup_type == NULL_TREE) + { + push_obstacks_nochange (); + end_temporary_allocation (); + cleanup_type = build_pointer_type + (build_function_type + (void_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, integer_type_node, void_list_node)))); + pop_obstacks (); + } + if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE) { throw_type = build_eh_type (exp); @@ -1528,163 +1125,167 @@ expand_throw (exp) } else { - /* Make a copy of the thrown object. WP 15.1.5 */ - exp = build_new (NULL_TREE, TREE_TYPE (exp), - build_tree_list (NULL_TREE, exp), - 0); + tree object, ptr; - if (exp == error_mark_node) - error (" in thrown expression"); + /* OK, this is kind of wacky. The WP says that we call + terminate - throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR)); - } + when the exception handling mechanism, after completing + evaluation of the expression to be thrown but before the + exception is caught (_except.throw_), calls a user function + that exits via an uncaught exception. - e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type); - expand_expr (e, const0_rtx, VOIDmode, 0); - e = build_modify_expr (saved_throw_value, NOP_EXPR, exp); - e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e); - expand_expr (e, const0_rtx, VOIDmode, 0); - } - else - { - /* rethrow current exception */ - /* This part is easy, as we don't have to do anything else. */ - } + So we have to protect the actual initialization of the + exception object with terminate(), but evaluate the expression + first. We also expand the call to __eh_alloc + first. Since there could be temps in the expression, we need + to handle that, too. */ - expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label)); -} + expand_start_target_temps (); -void -end_protect_partials () { - while (protect_list) - { - end_protect (TREE_VALUE (protect_list)); - protect_list = TREE_CHAIN (protect_list); - } -} +#if 0 + /* Unfortunately, this doesn't work. */ + preexpand_calls (exp); +#else + /* Store the throw expression into a temp. This can be less + efficient than storing it into the allocated space directly, but + oh well. To do this efficiently we would need to insinuate + ourselves into expand_call. */ + if (TREE_SIDE_EFFECTS (exp)) + { + tree temp = build (VAR_DECL, 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)); + exp = temp; + } +#endif -int -might_have_exceptions_p () -{ - if (eh_table_output_queue.head) - return 1; - return 0; -} + /* Allocate the space for the exception. */ + ptr = save_expr (alloc_eh_object (TREE_TYPE (exp))); + expand_expr (ptr, const0_rtx, VOIDmode, 0); -/* Output the exception table. - Return the number of handlers. */ -void -emit_exception_table () -{ - int count = 0; - extern FILE *asm_out_file; - struct ehEntry *entry; - tree eh_node_decl; + expand_eh_region_start (); - if (! doing_eh (0)) - return; + object = build_indirect_ref (ptr, NULL_PTR); + exp = build_modify_expr (object, INIT_EXPR, exp); - exception_section (); + if (exp == error_mark_node) + error (" in thrown expression"); - /* Beginning marker for table. */ - assemble_align (GET_MODE_ALIGNMENT (Pmode)); - assemble_label ("__EXCEPTION_TABLE__"); - output_exception_table_entry (asm_out_file, - const0_rtx, const0_rtx, const0_rtx); + expand_expr (exp, const0_rtx, VOIDmode, 0); + expand_eh_region_end (build_terminate_handler ()); + expand_end_target_temps (); - while (entry = dequeue_eh_entry (&eh_table_output_queue)) - { - tree context = entry->context; + throw_type = build_eh_type (object); - if (context && ! TREE_ASM_WRITTEN (context)) - continue; + if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object))) + { + cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), + dtor_identifier, 0); + cleanup = TREE_VALUE (cleanup); + mark_used (cleanup); + mark_addressable (cleanup); + /* Pretend it's a normal function. */ + cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); + } - count++; - output_exception_table_entry (asm_out_file, - entry->start_label, entry->end_label, - entry->exception_handler_label); - } + exp = ptr; + } - /* Ending marker for table. */ - assemble_label ("__EXCEPTION_END__"); - output_exception_table_entry (asm_out_file, - constm1_rtx, constm1_rtx, constm1_rtx); -} + if (cleanup == NULL_TREE) + { + cleanup = build_int_2 (0, 0); + TREE_TYPE (cleanup) = cleanup_type; + } -void -register_exception_table () -{ - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0, - VOIDmode, 1, - gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"), - Pmode); -} + fn = get_identifier ("__cp_push_exception"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)), + as defined in exception.cc. */ + tree tmp; + push_obstacks_nochange (); + end_temporary_allocation (); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, cleanup_type, void_list_node))); + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (void_type_node, tmp)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } -/* Build a throw expression. */ -tree -build_throw (e) - tree e; -{ - if (e != error_mark_node) + e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons + (NULL_TREE, throw_type, expr_tree_cons + (NULL_TREE, cleanup, NULL_TREE))); + e = build_function_call (fn, e); + expand_expr (e, const0_rtx, VOIDmode, 0); + } + else { - e = build1 (THROW_EXPR, void_type_node, e); - TREE_SIDE_EFFECTS (e) = 1; - TREE_USED (e) = 1; + /* rethrow current exception; note that it's no longer caught. */ + + tree fn = get_identifier ("__uncatch_exception"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + /* Declare void __uncatch_exception (void) + as defined in exception.cc. */ + push_obstacks_nochange (); + end_temporary_allocation (); + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (void_type_node, + void_list_node)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + exp = build_function_call (fn, NULL_TREE); + expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL); } - return e; -} -start_eh_unwinder () -{ - start_protect (); + expand_internal_throw (); } -end_eh_unwinder (end) - rtx end; +/* Build a throw expression. */ + +tree +build_throw (e) + tree e; { - tree expr; - rtx return_val_rtx, ret_val, label; + if (e == error_mark_node) + return e; - if (! doing_eh (0)) - return; + if (processing_template_decl) + return build_min (THROW_EXPR, void_type_node, e); - expr = make_node (RTL_EXPR); - TREE_TYPE (expr) = void_type_node; - RTL_EXPR_RTL (expr) = const0_rtx; - TREE_SIDE_EFFECTS (expr) = 1; - start_sequence_for_rtl_expr (expr); - - ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, - 0, hard_frame_pointer_rtx); - return_val_rtx = copy_to_reg (ret_val); -#ifdef NORMAL_RETURN_ADDR_OFFSET - return_val_rtx = plus_constant (return_val_rtx, NORMAL_RETURN_ADDR_OFFSET-1); -#else - return_val_rtx = plus_constant (return_val_rtx, -1); -#endif - emit_move_insn (DECL_RTL (saved_pc), return_val_rtx); - -#ifdef JUMP_TO_THROW - emit_move_insn (ret_val, gen_rtx (SYMBOL_REF, Pmode, "__throw")); -#else - label = gen_label_rtx (); - emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, label)); -#endif + if (! flag_ansi && e == null_node) + { + cp_warning ("throwing NULL"); + e = integer_zero_node; + } -#ifdef NORMAL_RETURN_ADDR_OFFSET - return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET); - if (return_val_rtx != ret_val) - emit_move_insn (ret_val, return_val_rtx); -#endif - - emit_jump (end); + e = build1 (THROW_EXPR, void_type_node, e); + TREE_SIDE_EFFECTS (e) = 1; + TREE_USED (e) = 1; -#ifndef JUMP_TO_THROW - emit_label (label); - do_function_call (Throw, NULL_TREE, NULL_TREE); -#endif - - RTL_EXPR_SEQUENCE (expr) = get_insns (); - end_sequence (); - end_protect (expr); + return e; } diff --git a/contrib/gcc/cp/exception.cc b/contrib/gcc/cp/exception.cc new file mode 100644 index 0000000..4c10404 --- /dev/null +++ b/contrib/gcc/cp/exception.cc @@ -0,0 +1,324 @@ +// Functions for Exception Support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation + +// 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. + +// 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. + +#pragma implementation "exception" + +#include "typeinfo" +#include "exception" +#include +#include "eh-common.h" + +/* Define terminate, unexpected, set_terminate, set_unexpected as + well as the default terminate func and default unexpected func. */ + +extern std::terminate_handler __terminate_func __attribute__((__noreturn__)); +using std::terminate; + +void +std::terminate () +{ + __terminate_func (); +} + +void +__default_unexpected () +{ + terminate (); +} + +static std::unexpected_handler __unexpected_func __attribute__((__noreturn__)) + = __default_unexpected; + +std::terminate_handler +std::set_terminate (std::terminate_handler func) +{ + std::terminate_handler old = __terminate_func; + + __terminate_func = func; + return old; +} + +std::unexpected_handler +std::set_unexpected (std::unexpected_handler func) +{ + std::unexpected_handler old = __unexpected_func; + + __unexpected_func = func; + return old; +} + +void +std::unexpected () +{ + __unexpected_func (); +} + +/* C++-specific state about the current exception. + This must match init_exception_processing(). + + Note that handlers and caught are not redundant; when rethrown, an + exception can have multiple active handlers and still be considered + uncaught. */ + +struct cp_eh_info +{ + __eh_info eh_info; + void *value; + void *type; + void (*cleanup)(void *, int); + bool caught; + cp_eh_info *next; + long handlers; + void *original_value; +}; + +/* Language-specific EH info pointer, defined in libgcc2. */ + +extern "C" cp_eh_info **__get_eh_info (); // actually void ** + +/* Is P the type_info node for a pointer of some kind? */ + +extern bool __is_pointer (void *); + + +/* OLD Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). This fudges the actualy returned value to + point to the beginning of what USE to be the cp_eh_info structure. + THis is so that old code that dereferences this pointer will find + things where it expects it to be.*/ +extern "C" void * +__cp_exception_info (void) +{ + return &((*__get_eh_info ())->value); +} + +/* 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 (); +} + +/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE, + and return a pointer to the beginning of the object's space. */ + +extern "C" void * malloc (size_t); +extern "C" void * +__eh_alloc (size_t size) +{ + void *p = malloc (size); + if (p == 0) + terminate (); + return p; +} + +/* Free the memory for an cp_eh_info and associated exception, given + a pointer to the cp_eh_info. */ + +extern "C" void free (void *); +extern "C" void +__eh_free (void *p) +{ + free (p); +} + + +typedef void * (* rtimetype) (void); + +extern "C" void * +__cplus_type_matcher (cp_eh_info *info, rtimetype match_info, + exception_descriptor *exception_table) +{ + void *ret; + + if (exception_table->lang.language != EH_LANG_C_plus_plus) + return NULL; + + if (match_info == CATCH_ALL_TYPE) + return info->value; + + /* we don't worry about version info yet, there is only one version! */ + + void *match_type = match_info (); + ret = __throw_type_match_rtti (match_type, info->type, info->original_value); + /* change value of exception */ + if (ret) + info->value = ret; + return ret; +} + + +/* Compiler hook to push a new exception onto the stack. + Used by expand_throw(). */ + +extern "C" void +__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int)) +{ + cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info)); + + p->value = value; + p->type = type; + p->cleanup = cleanup; + p->handlers = 0; + p->caught = false; + p->original_value = value; + + p->eh_info.match_function = __cplus_type_matcher; + p->eh_info.language = EH_LANG_C_plus_plus; + p->eh_info.version = 1; + + cp_eh_info **q = __get_eh_info (); + + p->next = *q; + *q = p; +} + +/* Compiler hook to pop an exception that has been finalized. Used by + push_eh_cleanup(). P is the info for the exception caught by the + current catch block. */ + +extern "C" void +__cp_pop_exception (cp_eh_info *p) +{ + cp_eh_info **q = __get_eh_info (); + + --p->handlers; + + /* Don't really pop if there are still active handlers for our exception, + or if our exception is being rethrown (i.e. if the active exception is + our exception and it is uncaught). */ + if (p->handlers != 0 + || (p == *q && !p->caught)) + return; + + for (; *q; q = &((*q)->next)) + if (*q == p) + break; + + if (! *q) + terminate (); + + *q = p->next; + + if (p->cleanup) + /* 2 is a magic value for destructors; see build_delete(). */ + p->cleanup (p->value, 2); + + if (! __is_pointer (p->type)) + __eh_free (p->value); + + __eh_free (p); +} + +extern "C" void +__uncatch_exception (void) +{ + cp_eh_info *p = __cp_eh_info (); + if (p == 0) + terminate (); + p->caught = false; +} + +/* As per [except.unexpected]: + If an exception is thrown, we check it against the spec. If it doesn't + match, we call unexpected (). If unexpected () throws, we check that + exception against the spec. If it doesn't match, if the spec allows + bad_exception we throw that; otherwise we call terminate (). + + The compiler treats an exception spec as a try block with a generic + handler that just calls this function with a list of the allowed + exception types, so we have an active exception that can be rethrown. + + This function does not return. */ + +extern "C" void +__check_eh_spec (int n, const void **spec) +{ + cp_eh_info *p = __cp_eh_info (); + + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti (spec[i], p->type, p->value)) + throw; + } + + try + { + std::unexpected (); + } + catch (...) + { + // __exception_info is an artificial var pushed into each catch block. + if (p != __exception_info) + { + p = __exception_info; + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti (spec[i], p->type, p->value)) + throw; + } + } + + const std::type_info &bad_exc = typeid (std::bad_exception); + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti (spec[i], &bad_exc, p->value)) + throw std::bad_exception (); + } + + terminate (); + } +} + +extern "C" void +__throw_bad_cast (void) +{ + throw std::bad_cast (); +} + +extern "C" void +__throw_bad_typeid (void) +{ + throw std::bad_typeid (); +} + +/* Has the current exception been caught? */ + +bool +std::uncaught_exception () +{ + cp_eh_info *p = __cp_eh_info (); + return p && ! p->caught; +} + +const char * std::exception:: +what () const +{ + return typeid (*this).name (); +} diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c index 99a611e..4c3d8b6 100644 --- a/contrib/gcc/cp/expr.c +++ b/contrib/gcc/cp/expr.c @@ -21,18 +21,24 @@ Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "rtl.h" #include "tree.h" #include "flags.h" #include "expr.h" #include "cp-tree.h" +#include "toplev.h" -#undef NULL -#define NULL 0 +#if 0 +static tree extract_aggr_init PROTO((tree, tree)); +static tree extract_scalar_init PROTO((tree, tree)); +#endif +static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode, + enum expand_modifier)); /* Hook used by expand_expr to expand language-specific tree codes. */ -rtx +static rtx cplus_expand_expr (exp, target, tmode, modifier) tree exp; rtx target; @@ -42,11 +48,10 @@ cplus_expand_expr (exp, target, tmode, modifier) tree type = TREE_TYPE (exp); register enum machine_mode mode = TYPE_MODE (type); register enum tree_code code = TREE_CODE (exp); - rtx original_target = target; int ignore = target == const0_rtx; if (ignore) - target = 0, original_target = 0; + target = 0; /* No sense saving up arithmetic to be done if it's all in the wrong mode to form part of an address. @@ -57,7 +62,7 @@ cplus_expand_expr (exp, target, tmode, modifier) switch (code) { - case NEW_EXPR: + case AGGR_INIT_EXPR: { /* Something needs to be initialized, but we didn't know where that thing was when building the tree. For example, @@ -74,8 +79,6 @@ cplus_expand_expr (exp, target, tmode, modifier) tree func = TREE_OPERAND (exp, 0); tree args = TREE_OPERAND (exp, 1); tree type = TREE_TYPE (exp), slot; - tree fn_type = TREE_TYPE (TREE_TYPE (func)); - tree return_type = TREE_TYPE (fn_type); tree call_exp; rtx call_target, return_target; int pcc_struct_return = 0; @@ -84,14 +87,8 @@ cplus_expand_expr (exp, target, tmode, modifier) `target' represents. SLOT holds the slot for TARGET. */ slot = TREE_OPERAND (exp, 2); - if (target == 0) - { - /* Should always be called with a target in BLKmode case. */ - my_friendly_assert (mode != BLKmode, 205); - my_friendly_assert (DECL_RTL (slot) != 0, 206); - - target = gen_reg_rtx (mode); - } + /* Should always be called with a target. */ + my_friendly_assert (target != NULL_RTX, 205); /* The target the initializer will initialize (CALL_TARGET) must now be directed to initialize the target we are @@ -110,97 +107,58 @@ cplus_expand_expr (exp, target, tmode, modifier) parameter value. */ mark_addressable (slot); if (TREE_PERMANENT (args)) - args = tree_cons (0, build1 (ADDR_EXPR, type, slot), + args = expr_tree_cons (0, build1 (ADDR_EXPR, type, slot), TREE_CHAIN (args)); else TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot); call_target = 0; } - else if (TREE_CODE (return_type) == REFERENCE_TYPE) - { - type = return_type; - call_target = 0; - } else { -#ifdef PCC_STATIC_STRUCT_RETURN - pcc_struct_return = 1; - call_target = 0; -#else call_target = target; +#ifdef PCC_STATIC_STRUCT_RETURN + if (aggregate_value_p (type)) + { + pcc_struct_return = 1; + call_target = 0; + } #endif } - if (call_target) - { - /* Make this a valid memory address now. The code below assumes - that it can compare rtx and make assumptions based on the - result. The assumptions are true only if the address was - valid to begin with. */ - call_target = validize_mem (call_target); - } - call_exp = build (CALL_EXPR, type, func, args, 0); + call_exp = build (CALL_EXPR, type, func, args, NULL_TREE); TREE_SIDE_EFFECTS (call_exp) = 1; return_target = expand_call (call_exp, call_target, ignore); - if (call_target == 0) - { - if (pcc_struct_return) - { - extern int flag_access_control; - int old_ac = flag_access_control; - - tree init = build_decl (VAR_DECL, 0, type); - TREE_ADDRESSABLE (init) = 1; - DECL_RTL (init) = return_target; - - flag_access_control = 0; - expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING); - flag_access_control = old_ac; - - if (TYPE_NEEDS_DESTRUCTOR (type)) - { - init = build_decl (VAR_DECL, 0, - build_reference_type (type)); - DECL_RTL (init) = XEXP (return_target, 0); - - init = maybe_build_cleanup (convert_from_reference (init)); - if (init != NULL_TREE) - expand_expr (init, 0, 0, 0); - } - call_target = return_target = DECL_RTL (slot); - } - else - call_target = return_target; - } - - if (call_target != return_target) - { - my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317); - if (GET_MODE (return_target) == BLKmode) - emit_block_move (call_target, return_target, expr_size (exp), - TYPE_ALIGN (type) / BITS_PER_UNIT); - else - emit_move_insn (call_target, return_target); - } - if (TREE_CODE (return_type) == REFERENCE_TYPE) + if (call_target) + /* Trust that the right thing has been done; it's too hard to + verify. */ + return return_target; + + /* If we're suffering under the ancient PCC_STATIC_STRUCT_RETURN + calling convention, we need to copy the return value out of + the static return buffer into slot. */ + if (pcc_struct_return) { - tree init; - - if (GET_CODE (call_target) == REG - && REGNO (call_target) < FIRST_PSEUDO_REGISTER) - my_friendly_abort (39); + extern int flag_access_control; + int old_ac = flag_access_control; - type = TREE_TYPE (exp); + tree init = build_decl (VAR_DECL, NULL_TREE, + build_reference_type (type)); + DECL_RTL (init) = XEXP (return_target, 0); + init = convert_from_reference (init); - init = build (RTL_EXPR, return_type, 0, call_target); - /* We got back a reference to the type we want. Now initialize - target with that. */ + flag_access_control = 0; expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING); + flag_access_control = old_ac; + + if (TYPE_NEEDS_DESTRUCTOR (type)) + { + init = maybe_build_cleanup (init); + if (init != NULL_TREE) + expand_expr (init, const0_rtx, VOIDmode, 0); + } } - if (DECL_RTL (slot) != target) - emit_move_insn (DECL_RTL (slot), target); return DECL_RTL (slot); } @@ -226,13 +184,16 @@ cplus_expand_expr (exp, target, tmode, modifier) expand_throw (TREE_OPERAND (exp, 0)); return NULL; - case UNSAVE_EXPR: - { - rtx temp; - temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); - TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0)); - return temp; - } + case VEC_INIT_EXPR: + return expand_expr + (expand_vec_init + (NULL_TREE, TREE_OPERAND (exp, 0), + build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2), + integer_one_node, 1), + TREE_OPERAND (exp, 1), 0), target, tmode, modifier); + + case NEW_EXPR: + return expand_expr (build_new_1 (exp), target, tmode, modifier); default: break; @@ -278,19 +239,7 @@ fixup_result_decl (decl, result) } } -/* Return nonzero iff DECL is memory-based. The DECL_RTL of - certain const variables might be a CONST_INT, or a REG - in some cases. We cannot use `memory_operand' as a test - here because on most RISC machines, a variable's address - is not, by itself, a legitimate address. */ - -int -decl_in_memory_p (decl) - tree decl; -{ - return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM; -} - +#if 0 /* Expand this initialization inline and see if it's simple enough that it can be done at compile-time. */ @@ -333,8 +282,8 @@ extract_scalar_init (decl, init) to = XEXP (r, 0); - if (! (to == value || - (GET_CODE (to) == SUBREG && XEXP (to, 0) == value))) + if (! (to == value + || (GET_CODE (to) == SUBREG && XEXP (to, 0) == value))) return 0; r = XEXP (r, 1); @@ -351,6 +300,7 @@ extract_scalar_init (decl, init) return t; } +#endif int extract_init (decl, init) @@ -358,6 +308,7 @@ extract_init (decl, init) { return 0; +#if 0 if (IS_AGGR_TYPE (TREE_TYPE (decl)) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) init = extract_aggr_init (decl, init); @@ -369,4 +320,93 @@ extract_init (decl, init) DECL_INITIAL (decl) = init; return 1; +#endif +} + +void +do_case (start, end) + tree start, end; +{ + tree value1 = NULL_TREE, value2 = NULL_TREE, label; + + if (start != NULL_TREE && TREE_TYPE (start) != NULL_TREE + && POINTER_TYPE_P (TREE_TYPE (start))) + error ("pointers are not permitted as case values"); + + if (end && pedantic) + pedwarn ("ANSI C++ forbids range expressions in switch statement"); + + if (processing_template_decl) + { + add_tree (build_min_nt (CASE_LABEL, start, end)); + return; + } + + if (start) + value1 = check_cp_case_value (start); + if (end) + value2 = check_cp_case_value (end); + + label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + if (value1 != error_mark_node + && value2 != error_mark_node) + { + tree duplicate; + int success; + + if (end) + success = pushcase_range (value1, value2, convert_and_check, + label, &duplicate); + else if (start) + success = pushcase (value1, convert_and_check, label, &duplicate); + else + success = pushcase (NULL_TREE, 0, label, &duplicate); + + if (success == 1) + { + if (end) + error ("case label not within a switch statement"); + else if (start) + cp_error ("case label `%E' not within a switch statement", start); + else + error ("default label not within a switch statement"); + } + else if (success == 2) + { + if (end) + { + error ("duplicate (or overlapping) case value"); + cp_error_at ("this is the first entry overlapping that value", + duplicate); + } + else if (start) + { + cp_error ("duplicate case value `%E'", start); + cp_error_at ("previously used here", duplicate); + } + else + { + error ("multiple default labels in one switch"); + cp_error_at ("this is the first default label", duplicate); + } + } + else if (success == 3) + warning ("case value out of range"); + else if (success == 4) + warning ("empty range specified"); + else if (success == 5) + { + if (end) + error ("case label within scope of cleanup or variable array"); + else if (! start) + error ("`default' label within scope of cleanup or variable array"); + else + 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); } diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c new file mode 100644 index 0000000..58747ef --- /dev/null +++ b/contrib/gcc/cp/friend.c @@ -0,0 +1,484 @@ +/* Help friends in C++. + Copyright (C) 1997 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 "tree.h" +#include "rtl.h" +#include "cp-tree.h" +#include "flags.h" +#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. */ + +int +is_friend (type, supplicant) + tree type, supplicant; +{ + int declp; + register tree list; + tree context; + + if (supplicant == NULL_TREE || type == NULL_TREE) + return 0; + + declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd'); + + if (declp) + /* It's a function decl. */ + { + tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); + tree name = DECL_NAME (supplicant); + tree ctype; + + if (DECL_FUNCTION_MEMBER_P (supplicant)) + ctype = DECL_CLASS_CONTEXT (supplicant); + else + ctype = NULL_TREE; + + for (; list ; list = TREE_CHAIN (list)) + { + if (name == TREE_PURPOSE (list)) + { + tree friends = TREE_VALUE (list); + for (; friends ; friends = TREE_CHAIN (friends)) + { + if (comptypes (ctype, TREE_PURPOSE (friends), 1)) + 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)) + return 1; + } + break; + } + } + } + else + /* It's a type. */ + { + if (type == supplicant) + return 1; + + list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type))); + for (; list ; list = TREE_CHAIN (list)) + { + tree t = TREE_VALUE (list); + + if (TREE_CODE (t) == TEMPLATE_DECL ? + is_specialization_of (TYPE_MAIN_DECL (supplicant), t) : + comptypes (supplicant, t, 1)) + return 1; + } + } + + if (declp && DECL_FUNCTION_MEMBER_P (supplicant)) + context = DECL_CLASS_CONTEXT (supplicant); + else if (! declp) + /* Local classes have the same access as the enclosing function. */ + context = hack_decl_function_context (TYPE_MAIN_DECL (supplicant)); + else + context = NULL_TREE; + + /* A namespace is not friend to anybody. */ + if (context && TREE_CODE (context) == NAMESPACE_DECL) + context = NULL_TREE; + + if (context) + return is_friend (type, context); + + return 0; +} + +/* Add a new friend to the friends of the aggregate type TYPE. + DECL is the FUNCTION_DECL of the friend being added. */ + +static void +add_friend (type, decl) + tree type, decl; +{ + tree typedecl = TYPE_MAIN_DECL (type); + tree list = DECL_FRIENDLIST (typedecl); + tree name = DECL_NAME (decl); + + while (list) + { + if (name == TREE_PURPOSE (list)) + { + tree friends = TREE_VALUE (list); + for (; friends ; friends = TREE_CHAIN (friends)) + { + if (decl == TREE_VALUE (friends)) + { + cp_warning ("`%D' is already a friend of class `%T'", + decl, type); + cp_warning_at ("previous friend declaration of `%D'", + TREE_VALUE (friends)); + return; + } + } + TREE_VALUE (list) = tree_cons (error_mark_node, decl, + TREE_VALUE (list)); + return; + } + 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; + } + } +} + +/* Declare that every member function NAME in FRIEND_TYPE + (which may be NULL_TREE) is a friend of type TYPE. */ + +static void +add_friends (type, name, friend_type) + tree type, name, friend_type; +{ + tree typedecl = TYPE_MAIN_DECL (type); + tree list = DECL_FRIENDLIST (typedecl); + + while (list) + { + if (name == TREE_PURPOSE (list)) + { + tree friends = TREE_VALUE (list); + while (friends && TREE_PURPOSE (friends) != friend_type) + friends = TREE_CHAIN (friends); + if (friends) + { + if (friend_type) + warning ("method `%s::%s' is already a friend of class", + TYPE_NAME_STRING (friend_type), + IDENTIFIER_POINTER (name)); + else + warning ("function `%s' is already a friend of class `%s'", + IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (DECL_NAME (typedecl))); + } + else + TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE, + TREE_VALUE (list)); + return; + } + list = TREE_CHAIN (list); + } + DECL_FRIENDLIST (typedecl) + = 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 + been defined, we make all of its member functions friends of + TYPE. If not, we make it a pending friend, which can later be added + when its definition is seen. If a type is defined, then its TYPE_DECL's + DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend + classes that are not defined. If a type has not yet been defined, + then the DECL_WAITING_FRIENDS contains a list of types + waiting to make it their friend. Note that these two can both + be in use at the same time! */ + +void +make_friend_class (type, friend_type) + tree type, friend_type; +{ + tree classes; + int is_template_friend; + + if (IS_SIGNATURE (type)) + { + error ("`friend' declaration in signature definition"); + return; + } + if (IS_SIGNATURE (friend_type)) + { + error ("signature type `%s' declared `friend'", + IDENTIFIER_POINTER (TYPE_IDENTIFIER (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)) + { + pedwarn ("class `%s' is implicitly friends with itself", + TYPE_NAME_STRING (type)); + return; + } + else + is_template_friend = 0; + + GNU_xref_hier (type, friend_type, 0, 0, 1); + + if (is_template_friend) + friend_type = CLASSTYPE_TI_TEMPLATE (friend_type); + + classes = CLASSTYPE_FRIEND_CLASSES (type); + while (classes + /* 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))) + classes = TREE_CHAIN (classes); + if (classes) + cp_warning ("`%T' is already a friend of `%T'", + TREE_VALUE (classes), type); + else + { + CLASSTYPE_FRIEND_CLASSES (type) + = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); + } +} + +/* Main friend processor. This is large, and for modularity purposes, + has been removed from grokdeclarator. It returns `void_type_node' + to indicate that something happened, though a FIELD_DECL is + not returned. + + CTYPE is the class this friend belongs to. + + DECLARATOR is the name of the friend. + + DECL is the FUNCTION_DECL that the friend is. + + In case we are parsing a friend which is part of an inline + definition, we will need to store PARM_DECL chain that comes + with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL. + + FLAGS is just used for `grokclassfn'. + + QUALS say what special qualifies should apply to the object + pointed to by `this'. */ + +tree +do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) + tree ctype, declarator, decl, parmdecls; + enum overload_flags flags; + tree quals; + int funcdef_flag; +{ + int is_friend_template = 0; + + /* Every decl that gets here is a friend of something. */ + DECL_FRIEND_P (decl) = 1; + + if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + { + declarator = TREE_OPERAND (declarator, 0); + if (TREE_CODE (declarator) == LOOKUP_EXPR) + declarator = TREE_OPERAND (declarator, 0); + if (is_overloaded_fn (declarator)) + 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 (ctype) + { + tree cname = TYPE_NAME (ctype); + if (TREE_CODE (cname) == TYPE_DECL) + 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, 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); + } + } + 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; + } + /* A global friend. + @@ or possibly a friend from a base class ?!? */ + else if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* Friends must all go through the overload machinery, + even though they may not technically be overloaded. + + 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; + + 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); + } + else + decl = push_template_decl (decl); + + if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template + && current_template_parms && uses_template_parms (decl)) + { + static int explained; + cp_warning ("friend declaration `%#D'", decl); + warning (" declares a non-template function"); + if (! explained) + { + 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)"); + explained = 1; + } + } + } + + make_decl_rtl (decl, NULL_PTR, 1); + add_friend (current_class_type, + is_friend_template ? DECL_TI_TEMPLATE (decl) : decl); + DECL_FRIEND_P (decl) = 1; + } + 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); + } + + /* 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)); + } + + 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++.1 b/contrib/gcc/cp/g++.1 index ae016fa..5101d5f 100644 --- a/contrib/gcc/cp/g++.1 +++ b/contrib/gcc/cp/g++.1 @@ -430,38 +430,6 @@ differently depending on whether `\|\c testing both of these predefined macros you can distinguish four situations: GNU C, traditional GNU C, other ANSI C compilers, and other old C compilers. -.TP -\ \ \ \(bu -In the preprocessor, comments convert to nothing at all, rather than -to a space. This allows traditional token concatenation. -.TP -\ \ \ \(bu -In the preprocessor, macro arguments are recognized within string -constants in a macro definition (and their values are stringified, -though without additional quote marks, when they appear in such a -context). The preprocessor always considers a string constant to end -at a newline. -.TP -\ \ \ \(bu -The preprocessor does not predefine the macro \c -.B __STDC__\c -\& when you use -`\|\c -.B \-traditional\c -\&\|', but still predefines\c -.B __GNUC__\c -\& (since the GNU extensions indicated by -.B __GNUC__\c -\& are not affected by -`\|\c -.B \-traditional\c -\&\|'). If you need to write header files that work -differently depending on whether `\|\c -.B \-traditional\c -\&\|' is in use, by -testing both of these predefined macros you can distinguish four -situations: GNU C, traditional GNU C, other ANSI C compilers, and -other old C compilers. .PP .TP \ \ \ \(bu diff --git a/contrib/gcc/cp/g++spec.c b/contrib/gcc/cp/g++spec.c new file mode 100644 index 0000000..542ca06 --- /dev/null +++ b/contrib/gcc/cp/g++spec.c @@ -0,0 +1,269 @@ +/* Specific flags and argument handling of the C++ front-end. + Copyright (C) 1996, 1997 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 "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'. */ +#define MATHLIB (1<<2) +/* This bit is set if they did `-lc'. */ +#define WITHLIBC (1<<3) + +#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)); + +void +lang_specific_driver (fn, in_argc, in_argv, in_added_libraries) + void (*fn)(); + int *in_argc; + char ***in_argv; + int *in_added_libraries; +{ + int i, j; + + /* If non-zero, the user gave us the `-v' flag. */ + int saw_verbose_flag = 0; + + /* This will be 0 if we encounter a situation where we should not + link in libstdc++. */ + int library = 1; + + /* The number of arguments being added to what's in argv, other than + libraries. We use this to track the number of times we've inserted + -xc++/-xnone. */ + int added = 2; + + /* Used to track options that take arguments, so we don't go wrapping + those with -xc++/-xnone. */ + char *quote = NULL; + + /* The new argument list will be contained in this. */ + char **arglist; + + /* Non-zero if we saw a `-xfoo' language specification on the + command line. Used to avoid adding our own -xc++ if the user + already gave a language for the file. */ + int saw_speclang = 0; + + /* "-lm" or "-lmath" if it appears on the command line. */ + char *saw_math = 0; + + /* "-lc" if it appears on the command line. */ + char *saw_libc = 0; + + /* An array used to flag each argument that needs a bit set for + LANGSPEC, MATHLIB, or WITHLIBC. */ + int *args; + + /* By default, we throw on the math library. */ + int need_math = NEED_MATH_LIBRARY; + + /* The total number of arguments with the new stuff. */ + int argc; + + /* The argument list. */ + char **argv; + + /* The number of libraries added in. */ + int added_libraries; + + /* The total number of arguments with the new stuff. */ + int num_args = 1; + + argc = *in_argc; + argv = *in_argv; + added_libraries = *in_added_libraries; + + args = (int *) xmalloc (argc * sizeof (int)); + bzero ((char *) args, argc * sizeof (int)); + + for (i = 1; i < argc; i++) + { + /* If the previous option took an argument, we swallow it here. */ + if (quote) + { + quote = NULL; + continue; + } + + /* We don't do this anymore, since we don't get them with minus + signs on them. */ + if (argv[i][0] == '\0' || argv[i][1] == '\0') + continue; + + if (argv[i][0] == '-') + { + if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0 + || strcmp (argv[i], "-nodefaultlibs") == 0)) + { + library = 0; + } + else if (strcmp (argv[i], "-lm") == 0 + || strcmp (argv[i], "-lmath") == 0 +#ifdef ALT_LIBM + || strcmp (argv[i], ALT_LIBM) == 0 +#endif + ) + { + args[i] |= MATHLIB; + need_math = 0; + } + else if (strcmp (argv[i], "-lc") == 0) + args[i] |= WITHLIBC; + else if (strcmp (argv[i], "-v") == 0) + { + saw_verbose_flag = 1; + if (argc == 2) + { + /* If they only gave us `-v', don't try to link + in libg++. */ + library = 0; + } + } + else if (strncmp (argv[i], "-x", 2) == 0) + saw_speclang = 1; + else if (((argv[i][2] == '\0' + && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL) + || strcmp (argv[i], "-Tdata") == 0)) + quote = argv[i]; + else if (library != 0 && ((argv[i][2] == '\0' + && (char *) strchr ("cSEM", argv[i][1]) != NULL) + || strcmp (argv[i], "-MM") == 0)) + { + /* Don't specify libraries if we won't link, since that would + cause a warning. */ + library = 0; + added -= 2; + } + else + /* Pass other options through. */ + continue; + } + else + { + int len; + + if (saw_speclang) + { + saw_speclang = 0; + continue; + } + + /* If the filename ends in .c or .i, put options around it. + But not if a specified -x option is currently active. */ + len = strlen (argv[i]); + if (len > 2 + && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i') + && argv[i][len - 2] == '.') + { + args[i] |= LANGSPEC; + added += 2; + } + } + } + + if (quote) + (*fn) ("argument to `%s' missing\n", quote); + + /* If we know we don't have to do anything, bail now. */ + if (! added && ! library) + { + free (args); + return; + } + + num_args = argc + added + need_math; + arglist = (char **) xmalloc (num_args * sizeof (char *)); + + /* NOTE: We start at 1 now, not 0. */ + for (i = 0, j = 0; i < argc; i++, j++) + { + arglist[j] = argv[i]; + + /* Make sure -lstdc++ is before the math library, since libstdc++ + itself uses those math routines. */ + if (!saw_math && (args[i] & MATHLIB) && library) + { + --j; + saw_math = argv[i]; + } + + if (!saw_libc && (args[i] & WITHLIBC) && library) + { + --j; + saw_libc = argv[i]; + } + + /* Wrap foo.c and foo.i files in a language specification to + force the gcc compiler driver to run cc1plus on them. */ + if (args[i] & LANGSPEC) + { + int len = strlen (argv[i]); + if (argv[i][len - 1] == 'i') + arglist[j++] = "-xc++-cpp-output"; + else + arglist[j++] = "-xc++"; + arglist[j++] = argv[i]; + arglist[j] = "-xnone"; + } + } + + /* Add `-lstdc++' if we haven't already done so. */ + if (library) + { + arglist[j++] = "-lstdc++"; + added_libraries++; + } + if (saw_math) + arglist[j++] = saw_math; + else if (library && need_math) + { + arglist[j++] = MATH_LIBRARY; + added_libraries++; + } + if (saw_libc) + arglist[j++] = saw_libc; + + arglist[j] = NULL; + + *in_argc = j; + *in_argv = arglist; + *in_added_libraries = added_libraries; +} + +/* Called before linking. Returns 0 on success and -1 on failure. */ +int lang_specific_pre_link () /* Not used for C++. */ +{ + return 0; +} + +/* 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/cp/gxx.gperf b/contrib/gcc/cp/gxx.gperf index e5465e8..71538567 100644 --- a/contrib/gcc/cp/gxx.gperf +++ b/contrib/gcc/cp/gxx.gperf @@ -5,24 +5,31 @@ struct resword { char *name; short token; enum rid rid;}; %% __alignof, ALIGNOF, NORID __alignof__, ALIGNOF, NORID -__asm, GCC_ASM_KEYWORD, NORID -__asm__, GCC_ASM_KEYWORD, NORID +__asm, ASM_KEYWORD, NORID +__asm__, ASM_KEYWORD, NORID __attribute, ATTRIBUTE, NORID __attribute__, ATTRIBUTE, NORID -__const, TYPE_QUAL, RID_CONST -__const__, TYPE_QUAL, RID_CONST +__complex, TYPESPEC, RID_COMPLEX +__complex__, TYPESPEC, RID_COMPLEX +__const, CV_QUALIFIER, RID_CONST +__const__, CV_QUALIFIER, RID_CONST __extension__, EXTENSION, NORID +__imag, IMAGPART, NORID +__imag__, IMAGPART, NORID __inline, SCSPEC, RID_INLINE __inline__, SCSPEC, RID_INLINE __label__, LABEL, NORID +__null, CONSTANT, RID_NULL +__real, REALPART, NORID +__real__, REALPART, NORID __signature__, AGGR, RID_SIGNATURE /* Extension */, __signed, TYPESPEC, RID_SIGNED __signed__, TYPESPEC, RID_SIGNED __sigof__, SIGOF, NORID /* Extension */, __typeof, TYPEOF, NORID __typeof__, TYPEOF, NORID -__volatile, TYPE_QUAL, RID_VOLATILE -__volatile__, TYPE_QUAL, RID_VOLATILE +__volatile, CV_QUALIFIER, RID_VOLATILE +__volatile__, CV_QUALIFIER, RID_VOLATILE __wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */, asm, ASM_KEYWORD, NORID, and, ANDAND, NORID, @@ -37,7 +44,7 @@ catch, CATCH, NORID, char, TYPESPEC, RID_CHAR, class, AGGR, RID_CLASS, compl, '~', NORID, -const, TYPE_QUAL, RID_CONST, +const, CV_QUALIFIER, RID_CONST, const_cast, CONST_CAST, NORID, continue, CONTINUE, NORID, default, DEFAULT, NORID, @@ -66,7 +73,6 @@ not_eq, EQCOMPARE, NORID, operator, OPERATOR, NORID, or, OROR, NORID, or_eq, ASSIGN, NORID, -overload, OVERLOAD, NORID, private, VISSPEC, RID_PRIVATE, protected, VISSPEC, RID_PROTECTED, public, VISSPEC, RID_PUBLIC, @@ -96,7 +102,7 @@ unsigned, TYPESPEC, RID_UNSIGNED, using, USING, NORID, virtual, SCSPEC, RID_VIRTUAL, void, TYPESPEC, RID_VOID, -volatile, TYPE_QUAL, RID_VOLATILE, +volatile, CV_QUALIFIER, RID_VOLATILE, while, WHILE, NORID, xor, '^', NORID, xor_eq, ASSIGN, NORID, diff --git a/contrib/gcc/cp/gxxint.texi b/contrib/gcc/cp/gxxint.texi index 015a33c..7cb57f2 100644 --- a/contrib/gcc/cp/gxxint.texi +++ b/contrib/gcc/cp/gxxint.texi @@ -9,7 +9,7 @@ @chapter Internal Architecture of the Compiler This is meant to describe the C++ front-end for gcc in detail. -Questions and comments to mrs@@cygnus.com. +Questions and comments to Benjamin Kosnik @code{}. @menu * Limitations of g++:: @@ -26,6 +26,7 @@ Questions and comments to mrs@@cygnus.com. * Copying Objects:: * Exception Handling:: * Free Store:: +* Mangling:: Function name mangling for C++ and Java * Concept Index:: @end menu @@ -53,38 +54,6 @@ Access checking is unimplemented for nested types. @item @code{volatile} is not implemented in general. -@cindex pointers to members -@item -Pointers to members are only minimally supported, and there are places -where the grammar doesn't even properly accept them yet. - -@cindex multiple inheritance -@item -@code{this} will be wrong in virtual members functions defined in a -virtual base class, when they are overridden in a derived class, when -called via a non-left most object. - -An example would be: - -@example -extern "C" int printf(const char*, ...); -struct A @{ virtual void f() @{ @} @}; -struct B : virtual A @{ int b; B() : b(0) @{@} void f() @{ b++; @} @}; -struct C : B @{@}; -struct D : B @{@}; -struct E : C, D @{@}; -int main() -@{ - E e; - C& c = e; D& d = e; - c.f(); d.f(); - printf ("C::b = %d, D::b = %d\n", e.C::b, e.D::b); - return 0; -@} -@end example - -This will print out 2, 0, instead of 1,1. - @end itemize @node Routines, Implementation Specifics, Limitations of g++, Top @@ -269,6 +238,13 @@ The functions @code{convert_to_aggr} and @code{build_method_call} use 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} +to set the field @code{DECL_NONCONVERTING_P}. That value is used by +@code{build_method_call} and @code{build_user_type_conversion_1} to decide +if a particular constructor should be used as a candidate for conversions. + @end itemize @node Glossary, Macros, Implementation Specifics, Top @@ -310,9 +286,7 @@ vtables. See also vtable and vfield. This section describes some of the macros used on trees. The list should be alphabetical. Eventually all macros should be documented -here. There are some postscript drawings that can be used to better -understand from of the more complex data structures, contact Mike Stump -(@code{mrs@@cygnus.com}) for information about them. +here. @table @code @item BINFO_BASETYPES @@ -521,18 +495,6 @@ FIELD_DECLs @end display -@item DECL_NESTED_TYPENAME -Holds the fully qualified type name. Example, Base::Derived. - -Has values of: - - IDENTIFIER_NODEs - -What things can this be used on: - - TYPE_DECLs - - @item DECL_NAME Has values of: @@ -682,6 +644,15 @@ appear in cp-decl.c and cp-decl2.c, so the are a good candidate for proper fixing, and removal. +@item TREE_HAS_CONSTRUCTOR +A flag to indicate when a CALL_EXPR represents a call to a constructor. +If set, we know that the type of the object, is the complete type of the +object, and that the value returned is nonnull. When used in this +fashion, it is an optimization. Can also be used on SAVE_EXPRs to +indicate when they are of fixed type and nonnull. Can also be used on +INDIRECT_EXPRs on CALL_EXPRs that represent a call to a constructor. + + @item TREE_PRIVATE Set for FIELD_DECLs by finish_struct. But not uniformly set. @@ -859,7 +830,7 @@ get_binfo (VF_BASETYPE_VALUE (vfield), t, 0) @end example @noindent -will return the binfo for the the given vfield. +will return the binfo for the given vfield. May or may not be set at @code{modify_vtable_entries} time. Set at @code{finish_base_struct} time. @@ -871,7 +842,7 @@ What things can this be used on: @item VF_DERIVED_VALUE Identifies the type of the most derived class of the vfield, excluding -the the class this vfield is for. +the class this vfield is for. Set at @code{finish_base_struct} time. @@ -1217,24 +1188,32 @@ The below points out some things that work in g++'s exception handling. All completely constructed temps and local variables are cleaned up in all unwinded scopes. Completely constructed parts of partially constructed objects are cleaned up. This includes partially built -arrays. Exception specifications are now handled. +arrays. Exception specifications are now handled. Thrown objects are +now cleaned up all the time. We can now tell if we have an active +exception being thrown or not (__eh_type != 0). We use this to call +terminate if someone does a throw; without there being an active +exception object. uncaught_exception () works. Exception handling +should work right if you optimize. Exception handling should work with +-fpic or -fPIC. The below points out some flaws in g++'s exception handling, as it now stands. Only exact type matching or reference matching of throw types works when --fno-rtti is used. Only works on a SPARC (like Suns), i386, arm and -rs6000 machines. Partial support is in for all other machines, but a -stack unwinder called __unwind_function has to be written, and added to -libgcc2 for them. See below for details on __unwind_function. Don't -expect exception handling to work right if you optimize, in fact the -compiler will probably core dump. RTL_EXPRs for EH cond variables for -&& and || exprs should probably be wrapped in UNSAVE_EXPRs, and -RTL_EXPRs tweaked so that they can be unsaved, and the UNSAVE_EXPR code -should be in the backend, or alternatively, UNSAVE_EXPR should be ripped -out and exactly one finalization allowed to be expanded by the backend. -I talked with kenner about this, and we have to allow multiple -expansions. +-fno-rtti is used. Only works on a SPARC (like Suns) (both -mflat and +-mno-flat models work), SPARClite, Hitachi SH, i386, arm, rs6000, +PowerPC, Alpha, mips, VAX, m68k and z8k machines. SPARC v9 may not +work. HPPA is mostly done, but throwing between a shared library and +user code doesn't yet work. Some targets have support for data-driven +unwinding. Partial support is in for all other machines, but a stack +unwinder called __unwind_function has to be written, and added to +libgcc2 for them. The new EH code doesn't rely upon the +__unwind_function for C++ code, instead it creates per function +unwinders right inside the function, unfortunately, on many platforms +the definition of RETURN_ADDR_RTX in the tm.h file for the machine port +is wrong. See below for details on __unwind_function. RTL_EXPRs for EH +cond variables for && and || exprs should probably be wrapped in +UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be unsaved. We only do pointer conversions on exception matching a la 15.3 p2 case 3: `A handler with type T, const T, T&, or const T& is a match for a @@ -1266,12 +1245,13 @@ build_exception_variant should sort the incoming list, so that it implements set compares, not exact list equality. Type smashing should smash exception specifications using set union. -Thrown objects are usually allocated on the heap, in the usual way, but -they are never deleted. They should be deleted by the catch clauses. -If one runs out of heap space, throwing an object will probably never -work. This could be relaxed some by passing an __in_chrg parameter to -track who has control over the exception object. Thrown objects are not -allocated on the heap when they are pointer to object types. +Thrown objects are usually allocated on the heap, in the usual way. If +one runs out of heap space, throwing an object will probably never work. +This could be relaxed some by passing an __in_chrg parameter to track +who has control over the exception object. Thrown objects are not +allocated on the heap when they are pointer to object types. We should +extend it so that all small (<4*sizeof(void*)) objects are stored +directly, instead of allocated on the heap. When the backend returns a value, it can create new exception regions that need protecting. The new region should rethrow the object in @@ -1285,13 +1265,13 @@ Ln: throw value; copy value onto heap jump throw (Ln, id, address of copy of value on heap) - try { + try @{ +Lstart: the start of the main EH region |... ... +Lend: the end of the main EH region - } catch (T o) { + @} catch (T o) @{ ...1 - } + @} Lresume: nop used to make sure there is something before the next region ends, if there is one @@ -1312,7 +1292,7 @@ Lover: [ [ call throw_type_match - if (eq) { + if (eq) @{ ] these lines disappear when there is no catch condition +Lsregion2: | ...1 @@ -1320,7 +1300,7 @@ Lover: |Lhandler: handler for the region Lsregion2-Leregion2 | rethrow (Lresume, same id, same obj); +Leregion2 - } + @} ] there are zero or more of these sections, depending upon how many catch clauses there are ----------------------------- expand_end_all_catch -------------------------- @@ -1336,7 +1316,7 @@ Ldone: start_all_catch emits labels: Lresume, -#end example +@end example The __unwind_function takes a pointer to the throw handler, and is expected to pop the stack frame that was built to call it, as well as @@ -1346,7 +1326,7 @@ machine state as determined by the context in which we are unwinding into. The way I normally start is to compile: void *g; - foo(void* a) { g = a; } + foo(void* a) @{ g = a; @} with -S, and change the thing that alters the PC (return, or ret usually) to not alter the PC, making sure to leave all other semantics @@ -1423,6 +1403,33 @@ things: first, a way to figure out where the frame pointer was stored, and second, a functional @code{__builtin_return_address} implementation for except.c to be able to use it. +Or just support DWARF 2 unwind info. + +@subsection New Backend Exception Support + +This subsection discusses various aspects of the design of the +data-driven model being implemented for the exception handling backend. + +The goal is to generate enough data during the compilation of user code, +such that we can dynamically unwind through functions at run time with a +single routine (@code{__throw}) that lives in libgcc.a, built by the +compiler, and dispatch into associated exception handlers. + +This information is generated by the DWARF 2 debugging backend, and +includes all of the information __throw needs to unwind an arbitrary +frame. It specifies where all of the saved registers and the return +address can be found at any point in the function. + +Major disadvantages when enabling exceptions are: + +@itemize @bullet +@item +Code that uses caller saved registers, can't, when flow can be +transferred into that code from an exception handler. In high performance +code this should not usually be true, so the effects should be minimal. + +@end itemize + @subsection Backend Exception Support The backend must be extended to fully support exceptions. Right now @@ -1453,7 +1460,7 @@ descriptor that refers to fully contained code that has been eliminated should also be removed, although not doing this is harmless in terms of semantics. -#end itemize +@end itemize The above is not meant to be exhaustive, but does include all things I have thought of so far. I am sure other limitations exist. @@ -1469,9 +1476,9 @@ required to call them in pairs. When marking the end of a region, an argument can be passed to indicate the handler for the marked region. This can be passed in many ways, currently a tree is used. Another possibility would be insns for the handler, or a label that denotes a -handler. I have a feeling insns might be the the best way to pass it. +handler. I have a feeling insns might be the best way to pass it. Semantics are, if an exception is thrown inside the region, control is -transfered unconditionally to the handler. If control passes through +transferred unconditionally to the handler. If control passes through the handler, then the backend is to rethrow the exception, in the context of the end of the original region. The handler is protected by the conventional mechanisms; it is the frontend's responsibility to @@ -1490,21 +1497,6 @@ between a cleanup-rethrower, and a real handler, if would also have to have a way to know if a handler `matches' a thrown exception, and this is frontend specific. -The UNSAVE_EXPR tree code has to be migrated to the backend. Exprs such -as TARGET_EXPRs, WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs have to be -changed to support unsaving. This is meant to be a complete list. -SAVE_EXPRs can be unsaved already. expand_decl_cleanup should be -changed to unsave it's argument, if needed. See -cp/tree.c:cp_expand_decl_cleanup, unsave_expr_now, unsave_expr, and -cp/expr.c:cplus_expand_expr(case UNSAVE_EXPR:) for the UNSAVE_EXPR code. -Now, as to why... because kenner already tripped over the exact same -problem in Ada, we talked about it, he didn't like any of the solution, -but yet, didn't like no solution either. He was willing to live with -the drawbacks of this solution. The drawback is unsave_expr_now. It -should have a callback into the frontend, to allow the unsaveing of -frontend special codes. The callback goes in, inplace of the call to -my_friendly_abort. - The stack unwinder is one of the hardest parts to do. It is highly machine dependent. The form that kenner seems to like was a couple of macros, that would do the machine dependent grunt work. One preexisting @@ -1513,31 +1505,15 @@ macro he seemed to want was __builtin_return_address, and the other would do the hard work of fixing up the registers, adjusting the stack pointer, frame pointer, arg pointer and so on. -The eh archive (~mrs/eh) might be good reading for understanding the Ada -perspective, and some of kenners mindset, and a detailed explanation -(Message-Id: <9308301130.AA10543@vlsi1.ultra.nyu.edu>) of the concepts -involved. - -Here is a guide to existing backend type code. It is all in -cp/except.c. Check out do_unwind, and expand_builtin_throw for current -code on how to figure out what handler matches an exception, -emit_exception_table for code on emitting the PC range table that is -built during compilation, expand_exception_blocks for code that emits -all the handlers at the end of a functions, end_protect to mark the end -of an exception region, start_protect to mark the start of an exception -region, lang_interim_eh is the master hook used by the backend into the -EH backend that now exists in the frontend, and expand_internal_throw to -raise an exception. - -@node Free Store, Concept Index, Exception Handling, Top +@node Free Store, Mangling, Exception Handling, Top @section Free Store -operator new [] adds a magic cookie to the beginning of arrays for which -the number of elements will be needed by operator delete []. These are -arrays of objects with destructors and arrays of objects that define -operator delete [] with the optional size_t argument. This cookie can -be examined from a program as follows: +@code{operator new []} adds a magic cookie to the beginning of arrays +for which the number of elements will be needed by @code{operator delete +[]}. These are arrays of objects with destructors and arrays of objects +that define @code{operator delete []} with the optional size_t argument. +This cookie can be examined from a program as follows: @example typedef unsigned long size_t; @@ -1576,8 +1552,373 @@ The linkage code in g++ is horribly twisted in order to meet two design goals: To meet the first goal, we defer emission of inlines and vtables until the end of the translation unit, where we can decide whether or not they are needed, and how to emit them if they are. + +@node Mangling, Concept Index, Free Store, Top +@section Function name mangling for C++ and Java + +Both C++ and Jave provide overloaded function and methods, +which are methods with the same types but different parameter lists. +Selecting the correct version is done at compile time. +Though the overloaded functions have the same name in the source code, +they need to be translated into different assembler-level names, +since typical assemblers and linkers cannot handle overloading. +This process of encoding the parameter types with the method name +into a unique name is called @dfn{name mangling}. The inverse +process is called @dfn{demangling}. + +It is convenient that C++ and Java use compatible mangling schemes, +since the makes life easier for tools such as gdb, and it eases +integration between C++ and Java. + +Note there is also a standard "Jave Native Interface" (JNI) which +implements a different calling convention, and uses a different +mangling scheme. The JNI is a rather abstract ABI so Java can call methods +written in C or C++; +we are concerned here about a lower-level interface primarily +intended for methods written in Java, but that can also be used for C++ +(and less easily C). + +Note that on systems that follow BSD tradition, a C identifier @code{var} +would get "mangled" into the assembler name @samp{_var}. On such +systems, all other mangled names are also prefixed by a @samp{_} +which is not shown in the following examples. + +@subsection Method name mangling + +C++ mangles a method by emitting the function name, followed by @code{__}, +followed by encodings of any method qualifiers (such as @code{const}), +followed by the mangling of the method's class, +followed by the mangling of the parameters, in order. + +For example @code{Foo::bar(int, long) const} is mangled +as @samp{bar__C3Fooil}. + +For a constructor, the method name is left out. +That is @code{Foo::Foo(int, long) const} is mangled +as @samp{__C3Fooil}. + +GNU Java does the same. + +@subsection Primitive types + +The C++ types @code{int}, @code{long}, @code{short}, @code{char}, +and @code{long long} are mangled as @samp{i}, @samp{l}, +@samp{s}, @samp{c}, and @samp{x}, respectively. +The corresponding unsigned types have @samp{U} prefixed +to the mangling. The type @code{signed char} is mangled @samp{Sc}. + +The C++ and Java floating-point types @code{float} and @code{double} +are mangled as @samp{f} and @samp{d} respectively. + +The C++ @code{bool} type and the Java @code{boolean} type are +mangled as @samp{b}. + +The C++ @code{wchar_t} and the Java @code{char} types are +mangled as @samp{w}. + +The Java integral types @code{byte}, @code{short}, @code{int} +and @code{long} are mangled as @samp{c}, @samp{s}, @samp{i}, +and @samp{x}, respectively. + +C++ code that has included @code{javatypes.h} will mangle +the typedefs @code{jbyte}, @code{jshort}, @code{jint} +and @code{jlong} as respectively @samp{c}, @samp{s}, @samp{i}, +and @samp{x}. (This has not been implemented yet.) + +@subsection Mangling of simple names + +A simple class, package, template, or namespace name is +encoded as the number of characters in the name, followed by +the actual characters. Thus the class @code{Foo} +is encoded as @samp{3Foo}. + +If any of the characters in the name are not alphanumeric +(i.e not one of the standard ASCII letters, digits, or '_'), +or the initial character is a digit, then the name is +mangled as a sequence of encoded Unicode letters. +A Unicode encoding starts with a @samp{U} to indicate +that Unicode escapes are used, followed by the number of +bytes used by the Unicode encoding, followed by the bytes +representing the encoding. ASSCI letters and +non-initial digits are encoded without change. However, all +other characters (including underscore and initial digits) are +translated into a sequence starting with an underscore, +followed by the big-endian 4-hex-digit lower-case encoding of the character. + +If a method name contains Unicode-escaped characters, the +entire mangled method name is followed by a @samp{U}. + +For example, the method @code{X\u0319::M\u002B(int)} is encoded as +@samp{M_002b__U6X_0319iU}. + + +@subsection Pointer and reference types + +A C++ pointer type is mangled as @samp{P} followed by the +mangling of the type pointed to. + +A C++ reference type as mangled as @samp{R} followed by the +mangling of the type referenced. + +A Java object reference type is equivalent +to a C++ pointer parameter, so we mangle such an parameter type +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 +modifications to the type. + +For example: +@example +template class class1 @{ @}; + +template class class2 @{ @}; + +class class3 @{ @}; + +int f(class2 > a ,int b, const class1&c, class3 *d) @{ @} + + B0 -> class2 + B1 -> class1 + B2 -> class3 +@end example +Produces the mangled name @samp{f__FGt6class21Zt6class11Z6class3iRCB1PB2}. +The int parameter is a basic type, and does not receive a B encoding... + +@subsection Qualified names + +Both C++ and Java allow a class to be lexically nested inside another +class. C++ also supports namespaces (not yet implemented by G++). +Java also supports packages. + +These are all mangled the same way: First the letter @samp{Q} +indicates that we are emitting a qualified name. +That is followed by the number of parts in the qualified name. +If that number is 9 or less, it is emitted with no delimiters. +Otherwise, an underscore is written before and after the count. +Then follows each part of the qualified name, as described above. + +For example @code{Foo::\u0319::Bar} is encoded as +@samp{Q33FooU5_03193Bar}. + +Squangling utilizes the the letter @samp{K} to indicate a +remembered portion of a qualified name. As qualified names are processed +for an identifier, the names are numbered and remembered in a +manner similar to the @samp{B} type compression code. +Names are recognized left to right, and given increasing values, which are +appended to the code in the standard manner. ie, multiple digit numbers +are delimited by @samp{_} characters. + +For example +@example +class Andrew +@{ + class WasHere + @{ + class AndHereToo + @{ + @}; + @}; +@}; + +f(Andrew&r1, Andrew::WasHere& r2, Andrew::WasHere::AndHereToo& r3) @{ @} + + K0 -> Andrew + K1 -> Andrew::WasHere + K2 -> Andrew::WasHere::AndHereToo +@end example +Function @samp{f()} would be mangled as : +@samp{f__FR6AndrewRQ2K07WasHereRQ2K110AndHereToo} + +There are some occasions when either a @samp{B} or @samp{K} code could +be chosen, preference is always given to the @samp{B} code. Ie, the example +in the section on @samp{B} mangling could have used a @samp{K} code +instead of @samp{B2}. + +@subsection Templates + +A class template instantiation is encoded as the letter @samp{t}, +followed by the encoding of the template name, followed +the number of template parameters, followed by encoding of the template +parameters. If a template parameter is a type, it is written +as a @samp{Z} followed by the encoding of the type. + +A function template specialization (either an instantiation or an +explicit specialization) is encoded by an @samp{H} followed by the +encoding of the template parameters, as described above, followed by an +@samp{_}, the encoding of the argument types to the template function +(not the specialization), another @samp{_}, and the return type. (Like +the argument types, the return type is the return type of the function +template, not the specialization.) Template parameters in the argument +and return types are encoded by an @samp{X} for type parameters, or a +@samp{Y} for constant parameters, an index indicating their position +in the template parameter list declaration, and their template depth. + +@subsection Arrays + +C++ array types are mangled by emitting @samp{A}, followed by +the length of the array, followed by an @samp{_}, followed by +the mangling of the element type. Of course, normally +array parameter types decay into a pointer types, so you +don't see this. + +Java arrays are objects. A Java type @code{T[]} is mangled +as if it were the C++ type @code{JArray}. +For example @code{java.lang.String[]} is encoded as +@samp{Pt6JArray1ZPQ34java4lang6String}. + +@subsection Static fields + +Both C++ and Java classes can have static fields. +These are allocated statically, and are shared among all instances. + +The mangling starts with a prefix (@samp{_} in most systems), which is +followed by the mangling +of the class name, followed by the "joiner" and finally the field name. +The joiner (see @code{JOINER} in @code{cp-tree.h}) is a special +separator character. For historical reasons (and idiosyncracies +of assembler syntax) it can @samp{$} or @samp{.} (or even +@samp{_} on a few systems). If the joiner is @samp{_} then the prefix +is @samp{__static_} instead of just @samp{_}. + +For example @code{Foo::Bar::var} (or @code{Foo.Bar.var} in Java syntax) +would be encoded as @samp{_Q23Foo3Bar$var} or @samp{_Q23Foo3Bar.var} +(or rarely @samp{__static_Q23Foo3Bar_var}). + +If the name of a static variable needs Unicode escapes, +the Unicode indicator @samp{U} comes before the "joiner". +This @code{\u1234Foo::var\u3445} becomes @code{_U8_1234FooU.var_3445}. + +@subsection Table of demangling code characters + +The following special characters are used in mangling: + +@table @samp +@item A +Indicates a C++ array type. + +@item b +Encodes the C++ @code{bool} type, +and the Java @code{boolean} type. + +@item B +Used for squangling. Similar in concept to the 'T' non-squangled code. + +@item c +Encodes the C++ @code{char} type, and the Java @code{byte} type. + +@item C +A modifier to indicate a @code{const} type. +Also used to indicate a @code{const} member function +(in which cases it precedes the encoding of the method's class). + +@item d +Encodes the C++ and Java @code{double} types. + +@item e +Indicates extra unknown arguments @code{...}. + +@item E +Indicates the opening parenthesis of an expression. + +@item f +Encodes the C++ and Java @code{float} types. + +@item F +Used to indicate a function type. + +@item H +Used to indicate a template function. + +@item i +Encodes the C++ and Java @code{int} types. + +@item J +Indicates a complex type. + +@item K +Used by squangling to compress qualified names. + +@item l +Encodes the C++ @code{long} type. + +@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 (?). +In Java used to mangle package-qualified names, and inner classes. + +@item r +Encodes the GNU C++ @code{long double} type. + +@item R +Indicates a reference type. Followed by the referenced type. + +@item s +Encodes the C++ and java @code{short} types. + +@item S +A modifier that indicates that the following integer type is signed. +Only used with @code{char}. + +Also used as a modifier to indicate a static member function. + +@item t +Indicates a template instantiation. + +@item T +A back reference to a previously seen type. + +@item U +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 v +Encodes the C++ and Java @code{void} types. + +@item V +A modified for a @code{const} type or method. + +@item w +Encodes the C++ @code{wchar_t} type, and the Java @code{char} types. + +@item W +Indicates the closing parenthesis of an expression. + +@item x +Encodes the GNU C++ @code{long long} type, and the Java @code{long} type. + +@item X +Encodes a template type parameter, when part of a function type. + +@item Y +Encodes a template constant parameter, when part of a function type. + +@item Z +Used for template type parameters. + +@end table + +The letters @samp{G}, @samp{M}, @samp{O}, and @samp{p} +also seem to be used for obscure purposes ... + +@node Concept Index, , Mangling, Top -@node Concept Index, , Free Store, Top @section Concept Index @printindex cp diff --git a/contrib/gcc/cp/inc/exception b/contrib/gcc/cp/inc/exception new file mode 100644 index 0000000..9954146 --- /dev/null +++ b/contrib/gcc/cp/inc/exception @@ -0,0 +1,43 @@ +// Exception Handling support header for -*- C++ -*- +// Copyright (C) 1995, 1996 Free Software Foundation + +#ifndef __EXCEPTION__ +#define __EXCEPTION__ + +#pragma interface "exception" + +extern "C++" { + +#ifdef __HONOR_STD +namespace std { +#endif + +class exception { +public: + exception () { } + virtual ~exception () { } + virtual const char* what () const; +}; + +class bad_exception : public exception { +public: + bad_exception () { } + virtual ~bad_exception () { } +}; + +typedef void (*terminate_handler) (); +typedef void (*unexpected_handler) (); + +terminate_handler set_terminate (terminate_handler); +void terminate () __attribute__ ((__noreturn__)); +unexpected_handler set_unexpected (unexpected_handler); +void unexpected () __attribute__ ((__noreturn__)); +bool uncaught_exception (); + +#ifdef __HONOR_STD +} // namespace std +#endif + +} // extern "C++" + +#endif diff --git a/contrib/gcc/cp/inc/new b/contrib/gcc/cp/inc/new new file mode 100644 index 0000000..0f25a5c --- /dev/null +++ b/contrib/gcc/cp/inc/new @@ -0,0 +1,46 @@ +// The -*- C++ -*- dynamic memory management header. +// Copyright (C) 1994, 1996 Free Software Foundation + +#ifndef __NEW__ +#define __NEW__ + +#pragma interface "new" +#include +#include + +extern "C++" { + +#ifdef __HONOR_STD +namespace std { +#endif + + class bad_alloc : public exception { + public: + virtual const char* what() const throw() { return "bad_alloc"; } + }; + + struct nothrow_t {}; + extern const nothrow_t nothrow; + 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); +void *operator new[] (size_t) throw (std::bad_alloc); +void operator delete (void *) throw(); +void operator delete[] (void *) throw(); +void *operator new (size_t, const std::nothrow_t&) throw(); +void *operator new[] (size_t, const std::nothrow_t&) throw(); +void operator delete (void *, const std::nothrow_t&) throw(); +void operator delete[] (void *, const std::nothrow_t&) throw(); + +// default placement versions of operator new +inline void *operator new(size_t, void *place) throw() { return place; } +inline void *operator new[](size_t, void *place) throw() { return place; } +} // extern "C++" + +#endif diff --git a/contrib/gcc/cp/inc/new.h b/contrib/gcc/cp/inc/new.h new file mode 100644 index 0000000..799db7e --- /dev/null +++ b/contrib/gcc/cp/inc/new.h @@ -0,0 +1,13 @@ +// -*- C++ -*- forwarding header. + +#ifndef __NEW_H__ +#define __NEW_H__ + +#include + +#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 new file mode 100644 index 0000000..e46acb9 --- /dev/null +++ b/contrib/gcc/cp/inc/typeinfo @@ -0,0 +1,62 @@ +// RTTI support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996 Free Software Foundation + +#ifndef __TYPEINFO__ +#define __TYPEINFO__ + +#pragma interface "typeinfo" + +#include + +extern "C++" { + +#ifdef __HONOR_STD +namespace std { +#endif + +class type_info { +private: + // assigning type_info is not supported. made private. + type_info& operator= (const type_info&); + type_info (const type_info&); + +protected: + type_info (const char *n): _name (n) { } + + const char *_name; + +public: + // destructor + virtual ~type_info (); + + bool before (const type_info& arg) const; + const char* name () const + { return _name; } + bool operator== (const type_info& arg) const; + bool operator!= (const type_info& arg) const; +}; + +inline bool type_info:: +operator!= (const type_info& arg) const +{ + return !operator== (arg); +} + +class bad_cast : public exception { +public: + bad_cast() { } + virtual ~bad_cast() { } +}; + +class bad_typeid : public exception { + public: + bad_typeid () { } + 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 9752a9b..931d033 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, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -19,18 +19,20 @@ 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. */ - -/* High-level class interface. */ +/* High-level class interface. */ #include "config.h" +#include "system.h" #include "tree.h" #include "rtl.h" #include "cp-tree.h" #include "flags.h" #include "output.h" +#include "except.h" +#include "expr.h" +#include "toplev.h" -#undef NULL -#define NULL 0 +extern void compiler_error (); /* In C++, structures with well-defined constructors are initialized by those constructors, unasked. CURRENT_BASE_INIT_LIST @@ -43,35 +45,36 @@ Boston, MA 02111-1307, USA. */ line. Perhaps this was not intended. */ tree current_base_init_list, current_member_init_list; -void emit_base_init (); -void check_base_init (); -static void expand_aggr_vbase_init (); -void expand_member_init (); -void expand_aggr_init (); - -static void expand_aggr_init_1 (); -static void expand_recursive_init_1 (); -static void expand_recursive_init (); +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 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 void expand_virtual_init PROTO((tree, tree)); -tree expand_vec_init (); - -static void add_friend (), add_friends (); +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; -/* Cache the identifier nodes for the two magic field of a new cookie. */ +/* Cache the identifier nodes for the magic field of a new cookie. */ static tree nc_nelts_field_id; -#if 0 -static tree nc_ptr_2comp_field_id; -#endif static tree minus_one; /* Set up local variable for this file. MUST BE CALLED AFTER INIT_DECL_PROCESSING. */ -tree BI_header_type, BI_header_size; +static tree BI_header_type, BI_header_size; void init_init_processing () { @@ -119,6 +122,7 @@ void init_init_processing () Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE (addr))). */ + void expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) tree real_binfo, binfo, addr; @@ -132,8 +136,8 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) { tree real_base_binfo = TREE_VEC_ELT (real_binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i); - int is_not_base_vtable = - i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo)); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo)); if (! TREE_VIA_VIRTUAL (real_base_binfo)) expand_direct_vtbls_init (real_base_binfo, base_binfo, is_not_base_vtable, can_elide, addr); @@ -153,23 +157,26 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) /* 348 - 351 */ /* Subroutine of emit_base_init. */ + static void -perform_member_init (member, name, init, explicit, protect_list) - tree member, name, init, *protect_list; +perform_member_init (member, name, init, explicit) + tree member, name, init; int explicit; { tree decl; tree type = TREE_TYPE (member); + expand_start_target_temps (); + if (TYPE_NEEDS_CONSTRUCTING (type) || (init && TYPE_HAS_CONSTRUCTOR (type))) { /* Since `init' is already a TREE_LIST on the current_member_init_list, only build it into one if we aren't already a list. */ if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST) - init = build_tree_list (NULL_TREE, init); + init = build_expr_list (NULL_TREE, init); - decl = build_component_ref (C_C_D, name, 0, explicit); + decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit); if (explicit && TREE_CODE (type) == ARRAY_TYPE @@ -190,9 +197,17 @@ perform_member_init (member, name, init, explicit, protect_list) { if (explicit) { - cp_error ("incomplete initializer for member `%D' of class `%T' which has no constructor", - member, current_class_type); - init = error_mark_node; + /* default-initialization. */ + if (AGGREGATE_TYPE_P (type)) + init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + cp_error ("default-initialization of `%#D', which has reference type", + member); + init = error_mark_node; + } + else + init = integer_zero_node; } /* member traversal: note it leaves init NULL */ else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE) @@ -215,38 +230,47 @@ perform_member_init (member, name, init, explicit, protect_list) current_member_init_list. */ if (init || explicit) { - decl = build_component_ref (C_C_D, name, 0, explicit); + decl = build_component_ref (current_class_ref, name, NULL_TREE, + explicit); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); } } - expand_cleanups_to (NULL_TREE); + + expand_end_target_temps (); + free_temp_slots (); if (TYPE_NEEDS_DESTRUCTOR (type)) { - tree expr = build_component_ref (C_C_D, name, 0, explicit); + tree expr; + + /* All cleanups must be on the function_obstack. */ + push_obstacks_nochange (); + resume_temporary_allocation (); + + expr = build_component_ref (current_class_ref, name, NULL_TREE, + explicit); expr = build_delete (type, expr, integer_zero_node, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); if (expr != error_mark_node) - { - start_protect (); - *protect_list = tree_cons (NULL_TREE, expr, *protect_list); - } + add_partial_entry (expr); + + pop_obstacks (); } } extern int warn_reorder; /* Subroutine of emit_member_init. */ + static tree sort_member_init (t) tree t; { - tree x, member, name, field, init; + tree x, member, name, field; tree init_list = NULL_TREE; - tree fields_to_unmark = NULL_TREE; int last_pos = 0; - tree last_field; + tree last_field = NULL_TREE; for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member)) { @@ -266,6 +290,8 @@ sort_member_init (t) name = TREE_PURPOSE (x); #if 0 + /* This happens in templates, since the IDENTIFIER is replaced + with the COMPONENT_REF in tsubst_expr. */ field = (TREE_CODE (name) == COMPONENT_REF ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name)); #else @@ -353,10 +379,10 @@ sort_base_init (t, rbase_ptr, vbase_ptr) last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list); for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x)) { - tree basename = TREE_PURPOSE (x); - tree binfo; + tree basetype = TREE_PURPOSE (x); + tree binfo = NULL_TREE; - if (basename == NULL_TREE) + if (basetype == NULL_TREE) { /* Initializer for single base class. Must not use multiple inheritance or this is ambiguous. */ @@ -375,9 +401,9 @@ sort_base_init (t, rbase_ptr, vbase_ptr) } binfo = TREE_VEC_ELT (binfos, 0); } - else if (is_aggr_typedef (basename, 1)) + else if (is_aggr_type (basetype, 1)) { - binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t); + binfo = binfo_or_else (basetype, t); if (binfo == NULL_TREE) continue; @@ -402,8 +428,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr) if (i < 0) { cp_error ("`%T' is not an immediate base class of `%T'", - IDENTIFIER_TYPE_VALUE (basename), - current_class_type); + basetype, current_class_type); continue; } } @@ -468,17 +493,14 @@ sort_base_init (t, rbase_ptr, vbase_ptr) } /* Perform partial cleanups for a base for exception handling. */ + static tree build_partial_cleanup_for (binfo) tree binfo; { - tree expr = convert_pointer_to_real (binfo, - build_unary_op (ADDR_EXPR, C_C_D, 0)); - - return build_delete (TREE_TYPE (expr), - expr, - integer_zero_node, - LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); + 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 @@ -506,9 +528,7 @@ emit_base_init (t, immediately) tree t; int immediately; { - extern tree in_charge_identifier; - - tree member, x; + tree member; tree mem_init_list; tree rbase_init_list, vbase_init_list; tree t_binfo = TYPE_BINFO (t); @@ -516,8 +536,6 @@ emit_base_init (t, immediately) int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; tree expr = NULL_TREE; - my_friendly_assert (protect_list == NULL_TREE, 999); - if (! immediately) { int momentary; @@ -549,7 +567,7 @@ emit_base_init (t, immediately) tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); expand_start_cond (first_arg, 0); - expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl, + expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr, vbase_init_list); expand_end_cond (); } @@ -557,7 +575,6 @@ emit_base_init (t, immediately) /* Now, perform initialization of non-virtual base classes. */ for (i = 0; i < n_baseclasses; i++) { - tree base = current_class_decl; tree base_binfo = TREE_VEC_ELT (binfos, i); tree init = void_list_node; @@ -565,7 +582,7 @@ emit_base_init (t, immediately) continue; #if 0 /* Once unsharing happens soon enough. */ - my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo); + my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999); #else BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo; #endif @@ -573,36 +590,49 @@ emit_base_init (t, immediately) if (TREE_PURPOSE (rbase_init_list)) init = TREE_VALUE (rbase_init_list); else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo))) - init = NULL_TREE; + { + init = NULL_TREE; + if (extra_warnings && copy_args_p (current_function_decl)) + cp_warning ("base class `%#T' should be explicitly initialized in the copy constructor", + BINFO_TYPE (base_binfo)); + } if (init != void_list_node) { - member = convert_pointer_to_real (base_binfo, current_class_decl); - expand_aggr_init_1 (base_binfo, 0, + expand_start_target_temps (); + + 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); - expand_cleanups_to (NULL_TREE); + + expand_end_target_temps (); + free_temp_slots (); } if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))) { - start_protect (); - protect_list = tree_cons (NULL_TREE, - build_partial_cleanup_for (base_binfo), - protect_list); + 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); } rbase_init_list = TREE_CHAIN (rbase_init_list); } /* Initialize all the virtual function table fields that - do come from virtual base classes. */ + do come from virtual base classes. */ if (TYPE_USES_VIRTUAL_BASECLASSES (t)) - expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0); + expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr); /* Initialize all the virtual function table fields that do not come from virtual base classes. */ - expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl); + expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr); for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) { @@ -622,10 +652,15 @@ emit_base_init (t, immediately) init = TREE_VALUE (mem_init_list); from_init_list = 1; +#if 0 + if (TREE_CODE (name) == COMPONENT_REF) + name = DECL_NAME (TREE_OPERAND (name, 1)); +#else /* Also see if it's ever a COMPONENT_REF here. If it is, we need to do `expand_assignment (name, init, 0, 0);' and a continue. */ my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349); +#endif } else { @@ -633,9 +668,15 @@ emit_base_init (t, immediately) init = DECL_INITIAL (member); from_init_list = 0; + + /* Effective C++ rule 12. */ + if (warn_ecpp && init == NULL_TREE + && !DECL_ARTIFICIAL (member) + && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE) + cp_warning ("`%D' should be initialized in the member initialization list", member); } - perform_member_init (member, name, init, from_init_list, &protect_list); + perform_member_init (member, name, init, from_init_list); mem_init_list = TREE_CHAIN (mem_init_list); } @@ -673,7 +714,7 @@ emit_base_init (t, immediately) my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351); #endif - perform_member_init (field, name, init, 1, &protect_list); + perform_member_init (field, name, init, 1); } mem_init_list = TREE_CHAIN (mem_init_list); } @@ -697,6 +738,7 @@ emit_base_init (t, immediately) /* Check that all fields are properly initialized after an assignment to `this'. */ + void check_base_init (t) tree t; @@ -713,6 +755,7 @@ check_base_init (t) BINFO is the exact type that DECL is supposed to be. In multiple inheritance, this might mean "C's A" if C : A, B. */ + static void expand_virtual_init (binfo, decl) tree binfo, decl; @@ -743,23 +786,30 @@ expand_virtual_init (binfo, decl) /* 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. */ + static void expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) tree binfo, exp, addr, init_list; { tree init = purpose_member (binfo, init_list); tree ref = build_indirect_ref (addr, NULL_PTR); + + expand_start_target_temps (); + 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_cleanups_to (NULL_TREE); + + 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. */ + static void expand_aggr_vbase_init (binfo, exp, addr, init_list) tree binfo; @@ -788,38 +838,25 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list) } } -/* Subroutine to perform parser actions for member initialization. - S_ID is the scoped identifier. - NAME is the name of the member. - INIT is the initializer, or `void_type_node' if none. */ -void -do_member_init (s_id, name, init) - tree s_id, name, init; -{ - tree binfo, base; +/* Find the context in which this FIELD can be initialized. */ - if (current_class_type == NULL_TREE - || ! is_aggr_typedef (s_id, 1)) - return; - binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id), - current_class_type, 1); - if (binfo == error_mark_node) - return; - if (binfo == 0) - { - error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type); - return; - } +static tree +initializing_context (field) + tree field; +{ + tree t = DECL_CONTEXT (field); - base = convert_pointer_to (binfo, current_class_decl); - expand_member_init (build_indirect_ref (base, NULL_PTR), name, init); + /* Anonymous union members can be initialized in the first enclosing + non-anonymous union context. */ + while (t && ANON_UNION_TYPE_P (t)) + t = TYPE_CONTEXT (t); + return t; } /* Function to give error message if member initialization specification is erroneous. FIELD is the member we decided to initialize. TYPE is the type for which the initialization is being performed. - FIELD must be a member of TYPE, or the base type from which FIELD - comes must not need a constructor. + FIELD must be a member of TYPE. MEMBER_NAME is the name of the member. */ @@ -831,23 +868,12 @@ member_init_ok_or_else (field, type, member_name) { if (field == error_mark_node) return 0; - if (field == NULL_TREE) + if (field == NULL_TREE || initializing_context (field) != type) { cp_error ("class `%T' does not have any field named `%s'", type, member_name); return 0; } - if (DECL_CONTEXT (field) != type - && TYPE_NEEDS_CONSTRUCTING (DECL_CONTEXT (field))) - { - if (current_function_decl && DECL_CONSTRUCTOR_P (current_function_decl)) - cp_error ("initialization of `%D' inside constructor for `%T'", - field, type); - else - cp_error ("member `%D' comes from base class needing constructor", - field); - return 0; - } if (TREE_STATIC (field)) { cp_error ("field `%#D' is static; only point of initialization is its declaration", @@ -873,22 +899,25 @@ member_init_ok_or_else (field, type, member_name) If INIT is non-NULL, then it the initialization should be placed in `current_base_init_list', where it will be processed by `emit_base_init'. */ + void expand_member_init (exp, name, init) tree exp, name, init; { - extern tree ptr_type_node; /* should be in tree.h */ - tree basetype = NULL_TREE, field; - tree parm; - tree rval, type; - tree actual_name; + tree type; if (exp == NULL_TREE) return; /* complain about this later */ type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + if (name && TREE_CODE (name) == TYPE_DECL) + { + basetype = TREE_TYPE (name); + name = DECL_NAME (name); + } + if (name == NULL_TREE && IS_AGGR_TYPE (type)) switch (CLASSTYPE_N_BASECLASSES (type)) { @@ -904,169 +933,84 @@ expand_member_init (exp, name, init) return; } - if (init) - { - /* The grammar should not allow fields which have names - that are TYPENAMEs. Therefore, if the field has - a non-NULL TREE_TYPE, we may assume that this is an - attempt to initialize a base class member of the current - type. Otherwise, it is an attempt to initialize a - member field. */ - - if (init == void_type_node) - init = NULL_TREE; + my_friendly_assert (init != NULL_TREE, 0); - if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name)) - { - tree base_init; + /* The grammar should not allow fields which have names that are + TYPENAMEs. Therefore, if the field has a non-NULL TREE_TYPE, we + may assume that this is an attempt to initialize a base class + member of the current type. Otherwise, it is an attempt to + initialize a member field. */ - if (name == NULL_TREE) - { -/* - if (basetype) - name = TYPE_IDENTIFIER (basetype); - else - { - error ("no base class to initialize"); - return; - } -*/ - } - else - { - basetype = IDENTIFIER_TYPE_VALUE (name); - if (basetype != type - && ! binfo_member (basetype, TYPE_BINFO (type)) - && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type))) - { - if (IDENTIFIER_CLASS_VALUE (name)) - goto try_member; - if (TYPE_USES_VIRTUAL_BASECLASSES (type)) - error ("type `%s' is not an immediate or virtual basetype for `%s'", - IDENTIFIER_POINTER (name), - TYPE_NAME_STRING (type)); - else - error ("type `%s' is not an immediate basetype for `%s'", - IDENTIFIER_POINTER (name), - TYPE_NAME_STRING (type)); - return; - } - } + if (init == void_type_node) + init = NULL_TREE; - if (purpose_member (name, current_base_init_list)) - { - error ("base class `%s' already initialized", - IDENTIFIER_POINTER (name)); - return; - } + if (name == NULL_TREE || basetype) + { + tree base_init; - base_init = build_tree_list (name, init); - TREE_TYPE (base_init) = basetype; - current_base_init_list = chainon (current_base_init_list, base_init); - } - else + if (name == NULL_TREE) { - tree member_init; - - try_member: - field = lookup_field (type, name, 1, 0); - - if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) - return; - - if (purpose_member (name, current_member_init_list)) +#if 0 + if (basetype) + name = TYPE_IDENTIFIER (basetype); + else { - error ("field `%s' already initialized", IDENTIFIER_POINTER (name)); + error ("no base class to initialize"); return; } - - member_init = build_tree_list (name, init); - TREE_TYPE (member_init) = TREE_TYPE (field); - current_member_init_list = chainon (current_member_init_list, member_init); +#endif } - return; - } - else if (name == NULL_TREE) - { - compiler_error ("expand_member_init: name == NULL_TREE"); - return; - } - - basetype = type; - field = lookup_field (basetype, name, 0, 0); - - if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name))) - return; - - /* now see if there is a constructor for this type - which will take these args. */ - - if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field))) - { - tree parmtypes, fndecl; - - if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL) - { - /* just know that we've seen something for this node */ - DECL_INITIAL (exp) = error_mark_node; - TREE_USED (exp) = 1; + else if (basetype != type + && ! current_template_parms + && ! vec_binfo_member (basetype, + TYPE_BINFO_BASETYPES (type)) + && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type))) + { + if (IDENTIFIER_CLASS_VALUE (name)) + goto try_member; + if (TYPE_USES_VIRTUAL_BASECLASSES (type)) + cp_error ("type `%T' is not an immediate or virtual basetype for `%T'", + basetype, type); + else + cp_error ("type `%T' is not an immediate basetype for `%T'", + basetype, type); + return; } - type = TYPE_MAIN_VARIANT (TREE_TYPE (field)); - actual_name = TYPE_IDENTIFIER (type); - parm = build_component_ref (exp, name, 0, 0); - - /* Now get to the constructor. */ - fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0); - /* Get past destructor, if any. */ - if (TYPE_HAS_DESTRUCTOR (type)) - fndecl = DECL_CHAIN (fndecl); - - if (fndecl) - my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209); - - /* If the field is unique, we can use the parameter - types to guide possible type instantiation. */ - if (DECL_CHAIN (fndecl) == NULL_TREE) + + if (purpose_member (basetype, current_base_init_list)) { - /* There was a confusion here between - FIELD and FNDECL. The following code - should be correct, but abort is here - to make sure. */ - my_friendly_abort (48); - parmtypes = FUNCTION_ARG_CHAIN (fndecl); + cp_error ("base class `%T' already initialized", basetype); + return; } - else + + if (warn_reorder && current_member_init_list) { - parmtypes = NULL_TREE; - fndecl = NULL_TREE; + cp_warning ("base initializer for `%T'", basetype); + warning (" will be re-ordered to precede member initializations"); } - init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL); - if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node) - rval = build_method_call (NULL_TREE, actual_name, init, NULL_TREE, LOOKUP_NORMAL); - else + base_init = build_tree_list (basetype, init); + current_base_init_list = chainon (current_base_init_list, base_init); + } + else + { + tree member_init; + + try_member: + field = lookup_field (type, name, 1, 0); + + if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) return; - if (rval != error_mark_node) + if (purpose_member (name, current_member_init_list)) { - /* Now, fill in the first parm with our guy */ - TREE_VALUE (TREE_OPERAND (rval, 1)) - = build_unary_op (ADDR_EXPR, parm, 0); - TREE_TYPE (rval) = ptr_type_node; - TREE_SIDE_EFFECTS (rval) = 1; + cp_error ("field `%D' already initialized", field); + return; } - } - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) - { - parm = build_component_ref (exp, name, 0, 0); - expand_aggr_init (parm, NULL_TREE, 0, 0); - rval = error_mark_node; - } - /* Now initialize the member. It does not have to - be of aggregate type to receive initialization. */ - if (rval != error_mark_node) - expand_expr_stmt (rval); + member_init = build_tree_list (name, init); + current_member_init_list = chainon (current_member_init_list, member_init); + } } /* This is like `expand_member_init', only it stores one aggregate @@ -1083,8 +1027,9 @@ expand_member_init (exp, name, init) explaining that such initializations are invalid. ALIAS_THIS is nonzero iff we are initializing something which is - essentially an alias for C_C_D. In this case, the base constructor - may move it on us, and we must keep track of such deviations. + essentially an alias for current_class_ref. In this case, the base + constructor may move it on us, and we must keep track of such + deviations. If INIT resolves to a CALL_EXPR which happens to return something of the type we are looking for, then we know @@ -1104,8 +1049,7 @@ expand_member_init (exp, name, init) initialization. A constructor or a conversion operator may have to be used to - perform the initialization, but not both, as it would be ambiguous. - */ + perform the initialization, but not both, as it would be ambiguous. */ void expand_aggr_init (exp, init, alias_this, flags) @@ -1186,14 +1130,15 @@ expand_aggr_init (exp, init, alias_this, flags) } static void -expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) +expand_default_init (binfo, true_exp, exp, init, alias_this, flags) tree binfo; tree true_exp, exp; - tree type; tree init; int alias_this; int flags; { + tree type = TREE_TYPE (exp); + /* It fails because there may not be a constructor which takes its own type as the first (or only parameter), but which does take other types via a conversion. So, if the thing initializing @@ -1203,6 +1148,37 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) tree rval; tree parms; + if (init && TREE_CODE (init) != TREE_LIST + && (flags & LOOKUP_ONLYCONVERTING)) + { + /* Base subobjects should only get direct-initialization. */ + 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)) + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + + if (TREE_CODE (init) == TRY_CATCH_EXPR) + /* We need to protect the initialization of a catch parm + with a call to terminate(), which shows up as a TRY_CATCH_EXPR + around the TARGET_EXPR for the copy constructor. See + expand_start_catch_block. */ + TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp, + TREE_OPERAND (init, 0)); + else + init = build (INIT_EXPR, TREE_TYPE (exp), exp, init); + TREE_SIDE_EFFECTS (init) = 1; + expand_expr_stmt (init); + return; + } + if (init == NULL_TREE || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) { @@ -1210,64 +1186,22 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) if (parms) init = TREE_VALUE (parms); } - else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init) - && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init))) - { - rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0); - TREE_USED (rval) = 1; - expand_expr_stmt (rval); - return; - } else - parms = build_tree_list (NULL_TREE, init); + parms = build_expr_list (NULL_TREE, init); if (TYPE_USES_VIRTUAL_BASECLASSES (type)) { if (true_exp == exp) - parms = tree_cons (NULL_TREE, integer_one_node, parms); + parms = expr_tree_cons (NULL_TREE, integer_one_node, parms); else - parms = tree_cons (NULL_TREE, integer_zero_node, parms); + parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms); flags |= LOOKUP_HAS_IN_CHARGE; } - if (init && TREE_CHAIN (parms) == NULL_TREE - && TYPE_HAS_TRIVIAL_INIT_REF (type) - && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init))) - { - rval = build (INIT_EXPR, type, exp, init); - TREE_SIDE_EFFECTS (rval) = 1; - expand_expr_stmt (rval); - } - else - { - if (flags & LOOKUP_ONLYCONVERTING) - flags |= LOOKUP_NO_CONVERSION; - rval = build_method_call (exp, constructor_name_full (type), - parms, binfo, flags); - - /* Private, protected, or otherwise unavailable. */ - if (rval == error_mark_node) - { - if (flags & LOOKUP_COMPLAIN) - cp_error ("in base initialization for %sclass `%T'", - TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "", - binfo); - } - else if (rval == NULL_TREE) - my_friendly_abort (361); - else - { - /* p. 222: if the base class assigns to `this', then that - value is used in the derived class. */ - if ((flag_this_is_variable & 1) && alias_this) - { - TREE_TYPE (rval) = TREE_TYPE (current_class_decl); - expand_assignment (current_class_decl, rval, 0, 0); - } - else - expand_expr_stmt (rval); - } - } + rval = build_method_call (exp, ctor_identifier, + parms, binfo, flags); + if (TREE_SIDE_EFFECTS (rval)) + expand_expr_stmt (rval); } /* This function is responsible for initializing EXP with INIT @@ -1301,7 +1235,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) int flags; { tree type = TREE_TYPE (exp); - tree init_type = NULL_TREE; my_friendly_assert (init != error_mark_node && type != error_mark_node, 211); @@ -1310,378 +1243,75 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) NULL_TREE, know that it was meant for us--just slide exp on in and expand the constructor. Constructors now come as TARGET_EXPRs. */ - if (init) - { - tree init_list = NULL_TREE; - - if (TREE_CODE (init) == TREE_LIST) - { - init_list = init; - if (TREE_CHAIN (init) == NULL_TREE) - init = TREE_VALUE (init); - } - - init_type = TREE_TYPE (init); - - if (TREE_CODE (init) != TREE_LIST) - { - if (TREE_CODE (init_type) == ERROR_MARK) - return; - -#if 0 - /* These lines are found troublesome 5/11/89. */ - if (TREE_CODE (init_type) == REFERENCE_TYPE) - init_type = TREE_TYPE (init_type); -#endif - - /* This happens when we use C++'s functional cast notation. - If the types match, then just use the TARGET_EXPR - directly. Otherwise, we need to create the initializer - separately from the object being initialized. */ - if (TREE_CODE (init) == TARGET_EXPR) - { - if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)) - { - if (TREE_CODE (exp) == VAR_DECL - || TREE_CODE (exp) == RESULT_DECL) - /* Unify the initialization targets. */ - DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp); - else - DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, 0, 0); - - expand_expr_stmt (init); - return; - } - else - { - init = TREE_OPERAND (init, 1); - init = build (CALL_EXPR, init_type, - TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0); - TREE_SIDE_EFFECTS (init) = 1; - if (init_list) - TREE_VALUE (init_list) = init; - } - } - - if (init_type == type && TREE_CODE (init) == CALL_EXPR -#if 0 - /* It is valid to directly initialize from a CALL_EXPR - without going through X(X&), apparently. */ - && ! TYPE_GETS_INIT_REF (type) -#endif - ) - { - /* A CALL_EXPR is a legitimate form of initialization, so - we should not print this warning message. */ -#if 0 - /* Should have gone away due to 5/11/89 change. */ - if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE) - init = convert_from_reference (init); -#endif - expand_assignment (exp, init, 0, 0); - if (exp == DECL_RESULT (current_function_decl)) - { - /* Failing this assertion means that the return value - from receives multiple initializations. */ - my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE - || DECL_INITIAL (exp) == error_mark_node, - 212); - DECL_INITIAL (exp) = init; - } - return; - } - else if (init_type == type - && TREE_CODE (init) == COND_EXPR) - { - /* Push value to be initialized into the cond, where possible. - Avoid spurious warning messages when initializing the - result of this function. */ - TREE_OPERAND (init, 1) - = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1)); - if (exp == DECL_RESULT (current_function_decl)) - DECL_INITIAL (exp) = NULL_TREE; - TREE_OPERAND (init, 2) - = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2)); - if (exp == DECL_RESULT (current_function_decl)) - DECL_INITIAL (exp) = init; - TREE_SIDE_EFFECTS (init) = 1; - expand_expr (init, const0_rtx, VOIDmode, 0); - free_temp_slots (); - return; - } - } - - /* We did not know what we were initializing before. Now we do. */ - if (TREE_CODE (init) == TARGET_EXPR) - { - tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1); - - if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR - && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node) - { - /* In order for this to work for RESULT_DECLs, if their - type has a constructor, then they must be BLKmode - so that they will be meaningfully addressable. */ - tree arg = build_unary_op (ADDR_EXPR, exp, 0); - init = TREE_OPERAND (init, 1); - init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)), - TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0); - TREE_SIDE_EFFECTS (init) = 1; - TREE_VALUE (TREE_OPERAND (init, 1)) - = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg); - - if (alias_this) - { - expand_assignment (current_function_decl, init, 0, 0); - return; - } - if (exp == DECL_RESULT (current_function_decl)) - { - if (DECL_INITIAL (DECL_RESULT (current_function_decl))) - fatal ("return value from function receives multiple initializations"); - DECL_INITIAL (exp) = init; - } - expand_expr_stmt (init); - return; - } - } - if (TREE_CODE (exp) == VAR_DECL - && TREE_CODE (init) == CONSTRUCTOR - && TREE_HAS_CONSTRUCTOR (init)) + if (init && TREE_CODE (exp) == VAR_DECL + && TREE_CODE (init) == CONSTRUCTOR + && TREE_HAS_CONSTRUCTOR (init)) + { + tree t = store_init_value (exp, init); + if (!t) { - tree t = store_init_value (exp, init); - if (!t) - { - expand_decl_init (exp); - return; - } - t = build (INIT_EXPR, type, exp, init); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr_stmt (t); + expand_decl_init (exp); return; } + t = build (INIT_EXPR, type, exp, init); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr_stmt (t); + return; + } - /* Handle this case: when calling a constructor: xyzzy foo(bar); - which really means: xyzzy foo = bar; Ugh! - - More useful for this case: xyzzy *foo = new xyzzy (bar); */ - - if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type)) - { - if (init_list && TREE_CHAIN (init_list)) - { - warning ("initializer list being treated as compound expression"); - init = convert (type, build_compound_expr (init_list)); - if (init == error_mark_node) - return; - } + /* 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_assignment (exp, init, 0, 0); +/* Report an error if NAME is not the name of a user-defined, + aggregate type. If OR_ELSE is nonzero, give an error message. */ - return; - } - /* See whether we can go through a type conversion operator. - This wins over going through a non-existent constructor. If - there is a constructor, it is ambiguous. */ - if (TREE_CODE (init) != TREE_LIST) - { - tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE - ? TREE_TYPE (init_type) : init_type; +int +is_aggr_typedef (name, or_else) + tree name; + int or_else; +{ + tree type; - if (ttype != type && IS_AGGR_TYPE (ttype)) - { - tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0); + if (name == error_mark_node) + return 0; - if (rval) - { - /* See if there is a constructor for``type'' that takes a - ``ttype''-typed object. */ - tree parms = build_tree_list (NULL_TREE, init); - tree as_cons = NULL_TREE; - if (TYPE_HAS_CONSTRUCTOR (type)) - as_cons = build_method_call (exp, constructor_name_full (type), - parms, binfo, - LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION); - if (as_cons != NULL_TREE && as_cons != error_mark_node) - /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */ - cp_error ("ambiguity between conversion to `%T' and constructor", - type); - else - expand_assignment (exp, rval, 0, 0); - return; - } - } - } + if (IDENTIFIER_HAS_TYPE_VALUE (name)) + type = IDENTIFIER_TYPE_VALUE (name); + else + { + if (or_else) + cp_error ("`%T' is not an aggregate typedef", name); + return 0; } - /* Handle default copy constructors here, does not matter if there is - a constructor or not. */ - if (type == init_type && IS_AGGR_TYPE (type) - && init && TREE_CODE (init) != TREE_LIST) - expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags); - /* Not sure why this is here... */ - else if (TYPE_HAS_CONSTRUCTOR (type)) - expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags); - else if (TREE_CODE (type) == ARRAY_TYPE) + if (! IS_AGGR_TYPE (type) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM + && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM) { - if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) - expand_vec_init (exp, exp, array_type_nelts (type), init, 0); - else if (TYPE_VIRTUAL_P (TREE_TYPE (type))) - sorry ("arrays of objects with virtual functions but no constructors"); + if (or_else) + cp_error ("`%T' is not an aggregate type", type); + return 0; } - else - expand_recursive_init (binfo, true_exp, exp, init, - CLASSTYPE_BASE_INIT_LIST (type), alias_this); + return 1; } -/* A pointer which holds the initializer. First call to - expand_aggr_init gets this value pointed to, and sets it to init_null. */ -static tree *init_ptr, init_null; +/* Report an error if TYPE is not a user-defined, aggregate type. If + OR_ELSE is nonzero, give an error message. */ -/* Subroutine of expand_recursive_init: - - ADDR is the address of the expression being initialized. - INIT_LIST is the cons-list of initializations to be performed. - ALIAS_THIS is its same, lovable self. */ -static void -expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this) - tree binfo, true_exp, addr; - tree init_list; - int alias_this; +int +is_aggr_type (type, or_else) + tree type; + int or_else; { - while (init_list) - { - if (TREE_PURPOSE (init_list)) - { - if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL) - { - tree member = TREE_PURPOSE (init_list); - tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR); - tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member); - if (IS_AGGR_TYPE (TREE_TYPE (member))) - expand_aggr_init (member_base, DECL_INITIAL (member), 0, 0); - else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE - && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member))) - { - member_base = save_expr (default_conversion (member_base)); - expand_vec_init (member, member_base, - array_type_nelts (TREE_TYPE (member)), - DECL_INITIAL (member), 0); - } - else - expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member))); - } - else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST) - { - expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this); - expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this); - } - else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK) - { - /* Only initialize the virtual function tables if we - are initializing the ultimate users of those vtables. */ - if (TREE_VALUE (init_list)) - { - /* We have to ensure that the first argment to - expand_virtual_init is in binfo's hierarchy. */ - /* Is it the case that this is exactly the right binfo? */ - /* If it is ok, then fixup expand_virtual_init, to make - it much simpler. */ - expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0), - addr); - if (TREE_VALUE (init_list) == binfo - && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) - expand_indirect_vtbls_init (binfo, true_exp, addr, 1); - } - } - else - my_friendly_abort (49); - } - else if (TREE_VALUE (init_list) - && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC) - { - tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR); - expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr, - alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)), - LOOKUP_COMPLAIN); - - /* INIT_PTR is used up. */ - init_ptr = &init_null; - } - else - my_friendly_abort (50); - init_list = TREE_CHAIN (init_list); - } -} - -/* Initialize EXP with INIT. Type EXP does not have a constructor, - but it has a baseclass with a constructor or a virtual function - table which needs initializing. - - INIT_LIST is a cons-list describing what parts of EXP actually - need to be initialized. INIT is given to the *unique*, first - constructor within INIT_LIST. If there are multiple first - constructors, such as with multiple inheritance, INIT must - be zero or an ambiguity error is reported. - - ALIAS_THIS is passed from `expand_aggr_init'. See comments - there. */ - -static void -expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this) - tree binfo, true_exp, exp, init; - tree init_list; - int alias_this; -{ - tree *old_init_ptr = init_ptr; - tree addr = build_unary_op (ADDR_EXPR, exp, 0); - init_ptr = &init; - - if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) - { - expand_aggr_vbase_init (binfo, exp, addr, init_list); - expand_indirect_vtbls_init (binfo, true_exp, addr, 1); - } - expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this); - - if (*init_ptr) - { - tree type = TREE_TYPE (exp); - - if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - if (IS_AGGR_TYPE (type)) - cp_error ("unexpected argument to constructor `%T'", type); - else - error ("unexpected argument to constructor"); - } - init_ptr = old_init_ptr; -} - -/* Report an error if NAME is not the name of a user-defined, - aggregate type. If OR_ELSE is nonzero, give an error message. */ -int -is_aggr_typedef (name, or_else) - tree name; - int or_else; -{ - tree type; - - if (name == error_mark_node) - return 0; - - if (IDENTIFIER_HAS_TYPE_VALUE (name)) - type = IDENTIFIER_TYPE_VALUE (name); - else - { - if (or_else) - cp_error ("`%T' is not an aggregate typedef", name); - return 0; - } - - if (! IS_AGGR_TYPE (type) - && TREE_CODE (type) != TEMPLATE_TYPE_PARM) + if (type == error_mark_node) + return 0; + + if (! IS_AGGR_TYPE (type) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM + && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM) { if (or_else) cp_error ("`%T' is not an aggregate type", type); @@ -1691,6 +1321,7 @@ is_aggr_typedef (name, or_else) } /* Like is_aggr_typedef, but returns typedef if successful. */ + tree get_aggr_from_typedef (name, or_else) tree name; @@ -1711,7 +1342,8 @@ get_aggr_from_typedef (name, or_else) } if (! IS_AGGR_TYPE (type) - && TREE_CODE (type) != TEMPLATE_TYPE_PARM) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM + && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM) { if (or_else) cp_error ("type `%T' is of non-aggregate type", type); @@ -1737,40 +1369,59 @@ get_type_value (name) /* This code could just as well go in `class.c', but is placed here for modularity. */ -/* For an expression of the form CNAME :: NAME (PARMLIST), build +/* For an expression of the form TYPE :: NAME (PARMLIST), build the appropriate function call. */ + tree -build_member_call (cname, name, parmlist) - tree cname, name, parmlist; +build_member_call (type, name, parmlist) + tree type, name, parmlist; { - tree type, t; - tree method_name = name; + tree t; + tree method_name; int dtor = 0; int dont_use_this = 0; tree basetype_path, decl; + if (TREE_CODE (name) == TEMPLATE_ID_EXPR + && TREE_CODE (type) == NAMESPACE_DECL) + { + /* '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); + return build_x_function_call (name, parmlist, current_class_ref); + } + + if (type == std_node) + return build_x_function_call (do_scoped_id (name, 0), parmlist, + current_class_ref); + if (TREE_CODE (type) == NAMESPACE_DECL) + return build_x_function_call (lookup_namespace_name (type, name), + parmlist, current_class_ref); + + if (TREE_CODE (name) != TEMPLATE_ID_EXPR) + method_name = name; + else + method_name = TREE_OPERAND (name, 0); + if (TREE_CODE (method_name) == BIT_NOT_EXPR) { method_name = TREE_OPERAND (method_name, 0); dtor = 1; } - if (TREE_CODE (cname) == SCOPE_REF) - cname = resolve_scope_to_name (NULL_TREE, cname); - /* This shouldn't be here, and build_member_call shouldn't appear in parse.y! (mrs) */ - if (cname && get_aggr_from_typedef (cname, 0) == 0 - && TREE_CODE (cname) == IDENTIFIER_NODE) + if (type && TREE_CODE (type) == IDENTIFIER_NODE + && get_aggr_from_typedef (type, 0) == 0) { - tree ns = lookup_name (cname, 0); + tree ns = lookup_name (type, 0); if (ns && TREE_CODE (ns) == NAMESPACE_DECL) { - return build_x_function_call (build_offset_ref (cname, name), parmlist, current_class_decl); + return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref); } } - if (cname == NULL_TREE || ! (type = get_aggr_from_typedef (cname, 1))) + if (type == NULL_TREE || ! is_aggr_type (type, 1)) return error_mark_node; /* An operator we did not like. */ @@ -1779,12 +1430,6 @@ build_member_call (cname, name, parmlist) if (dtor) { -#if 0 - /* Everything can explicitly call a destructor; see 12.4 */ - if (! TYPE_HAS_DESTRUCTOR (type)) - cp_error ("type `%#T' does not have a destructor", type); - else -#endif cp_error ("cannot call destructor `%T::~%T' without object", type, method_name); return error_mark_node; @@ -1801,14 +1446,14 @@ build_member_call (cname, name, parmlist) basetype_path = TYPE_BINFO (type); decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node); } - else if (current_class_decl == 0) + else if (current_class_ptr == 0) { dont_use_this = 1; decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node); } else { - tree olddecl = current_class_decl; + tree olddecl = current_class_ptr; tree oldtype = TREE_TYPE (TREE_TYPE (olddecl)); if (oldtype != type) { @@ -1825,8 +1470,11 @@ build_member_call (cname, name, parmlist) 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)) - return build_method_call (decl, method_name, parmlist, basetype_path, + if ((t = lookup_fnfields (basetype_path, method_name, 0))) + return build_method_call (decl, + TREE_CODE (name) == TEMPLATE_ID_EXPR + ? name : method_name, + parmlist, basetype_path, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); if (TREE_CODE (name) == IDENTIFIER_NODE && ((t = lookup_field (TYPE_BINFO (type), name, 1, 0)))) @@ -1849,9 +1497,9 @@ build_member_call (cname, name, parmlist) cp_error ("invalid use of member `%D'", t); return error_mark_node; } - if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)) - && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl))) - return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist, NULL_TREE); + if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))) + return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, + parmlist, NULL_TREE); return build_function_call (decl, parmlist); } else @@ -1863,54 +1511,77 @@ build_member_call (cname, name, parmlist) /* Build a reference to a member of an aggregate. This is not a C++ `&', but really something which can have its address taken, - and then act as a pointer to member, for example CNAME :: FIELD - can have its address taken by saying & CNAME :: FIELD. + and then act as a pointer to member, for example TYPE :: FIELD + can have its address taken by saying & TYPE :: FIELD. @@ Prints out lousy diagnostics for operator @@ fields. @@ This function should be rewritten and placed in search.c. */ + tree -build_offset_ref (cname, name) - tree cname, name; +build_offset_ref (type, name) + tree type, name; { - tree decl, type, fnfields, fields, t = error_mark_node; - tree basetypes = NULL_TREE; - int dtor = 0; + tree decl, fnfields, fields, t = error_mark_node; + tree basebinfo = NULL_TREE; + tree orig_name = name; + + /* class templates can come in as TEMPLATE_DECLs here. */ + if (TREE_CODE (name) == TEMPLATE_DECL) + return name; - if (TREE_CODE (cname) == SCOPE_REF) - cname = resolve_scope_to_name (NULL_TREE, cname); + if (type == std_node) + return do_scoped_id (name, 0); + + if (processing_template_decl || uses_template_parms (type)) + return build_min_nt (SCOPE_REF, type, name); /* Handle namespace names fully here. */ - if (TREE_CODE (cname) == IDENTIFIER_NODE - && get_aggr_from_typedef (cname, 0) == 0) + if (TREE_CODE (type) == NAMESPACE_DECL) { - tree ns = lookup_name (cname, 0); - tree val; - if (ns && TREE_CODE (ns) == NAMESPACE_DECL) + t = lookup_namespace_name (type, name); + if (! type_unknown_p (t)) { - val = lookup_namespace_name (ns, name); - if (val) - return val; - cp_error ("namespace `%D' has no member named `%D'", ns, name); - return error_mark_node; + mark_used (t); + t = convert_from_reference (t); } + return t; } - if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1)) + if (type == NULL_TREE || ! is_aggr_type (type, 1)) return error_mark_node; - type = IDENTIFIER_TYPE_VALUE (cname); + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at + something like `a.template f' or the like. For the most + part, we treat this just like a.f. We do remember, however, + the template-id that was used. */ + name = TREE_OPERAND (orig_name, 0); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0); + } if (TREE_CODE (name) == BIT_NOT_EXPR) { - dtor = 1; - name = TREE_OPERAND (name, 0); + if (! check_dtor_name (type, name)) + cp_error ("qualified type `%T' does not match destructor name `~%T'", + type, TREE_OPERAND (name, 0)); + name = dtor_identifier; } +#if 0 + /* I think this is wrong, but the draft is unclear. --jason 6/15/98 */ + else if (name == constructor_name_full (type) + || name == constructor_name (type)) + name = ctor_identifier; +#endif - if (TYPE_SIZE (type) == 0) + if (TYPE_SIZE (complete_type (type)) == 0) { - t = IDENTIFIER_CLASS_VALUE (name); + 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, @@ -1920,7 +1591,7 @@ build_offset_ref (cname, name) if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) { - TREE_USED (t) = 1; + mark_used (t); return t; } if (TREE_CODE (t) == FIELD_DECL) @@ -1932,125 +1603,104 @@ build_offset_ref (cname, name) return error_mark_node; } -#if 0 - if (TREE_CODE (name) == TYPE_EXPR) - /* Pass a TYPE_DECL to build_component_type_expr. */ - return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)), - name, NULL_TREE, 1); -#endif - if (current_class_type == 0 - || get_base_distance (type, current_class_type, 0, &basetypes) == -1) + || get_base_distance (type, current_class_type, 0, &basebinfo) == -1) { - basetypes = TYPE_BINFO (type); - decl = build1 (NOP_EXPR, - IDENTIFIER_TYPE_VALUE (cname), - error_mark_node); + basebinfo = TYPE_BINFO (type); + decl = build1 (NOP_EXPR, type, error_mark_node); } - else if (current_class_decl == 0) - decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname), - error_mark_node); + else if (current_class_ptr == 0) + decl = build1 (NOP_EXPR, type, error_mark_node); else - decl = C_C_D; + decl = current_class_ref; - fnfields = lookup_fnfields (basetypes, name, 1); - fields = lookup_field (basetypes, name, 0, 0); + fnfields = lookup_fnfields (basebinfo, name, 1); + fields = lookup_field (basebinfo, name, 0, 0); if (fields == error_mark_node || fnfields == error_mark_node) return error_mark_node; /* A lot of this logic is now handled in lookup_field and - lookup_fnfield. */ + lookup_fnfield. */ if (fnfields) { - basetypes = TREE_PURPOSE (fnfields); + extern int flag_save_memoized_contexts; /* Go from the TREE_BASELINK to the member function info. */ t = TREE_VALUE (fnfields); - if (fields) + if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR) { - if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t)) + /* The FNFIELDS are going to contain functions that aren't + necessarily templates, and templates that don't + necessarily match the explicit template parameters. We + save all the functions, and the explicit parameters, and + then figure out exactly what to instantiate with what + arguments in instantiate_type. */ + + if (TREE_CODE (t) != OVERLOAD) + /* The code in instantiate_type which will process this + expects to encounter OVERLOADs, not raw functions. */ + t = ovl_cons (t, NULL_TREE); + + return build (OFFSET_REF, + build_offset_type (type, unknown_type_node), + decl, + build (TEMPLATE_ID_EXPR, + TREE_TYPE (t), + t, + TREE_OPERAND (orig_name, 1))); + } + + 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) { - error ("ambiguous member reference: member `%s' defined as both field and function", - IDENTIFIER_POINTER (name)); + cp_error_at ("member function `%#D' is protected", t); + error ("in this context"); return error_mark_node; } - if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t))) - ; - else if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields))) - t = fields; - else + if (access == access_private_node) { - error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice"); + cp_error_at ("member function `%#D' is private", t); + error ("in this context"); return error_mark_node; } + mark_used (t); + return build (OFFSET_REF, TREE_TYPE (t), decl, t); } - if (t == TREE_VALUE (fnfields)) - { - extern int flag_save_memoized_contexts; + /* 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. - if (DECL_CHAIN (t) == NULL_TREE || dtor) - { - enum access_type access; + ??? 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 ())) + fnfields = copy_list (fnfields); - /* unique functions are handled easily. */ - unique: - access = compute_access (basetypes, t); - if (access == access_protected) - { - cp_error_at ("member function `%#D' is protected", t); - error ("in this context"); - return error_mark_node; - } - if (access == access_private) - { - cp_error_at ("member function `%#D' is private", t); - error ("in this context"); - return error_mark_node; - } - assemble_external (t); - return build (OFFSET_REF, TREE_TYPE (t), decl, t); - } - - /* overloaded functions may need more work. */ - if (cname == name) - { - if (TYPE_HAS_DESTRUCTOR (type) - && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE) - { - t = DECL_CHAIN (t); - goto unique; - } - } - /* 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. - - ??? 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 && global_bindings_p ()) - || ! allocation_temporary_p ())) - fnfields = copy_list (fnfields); - - for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t)) - assemble_external (t); - - t = build_tree_list (error_mark_node, fnfields); - TREE_TYPE (t) = build_offset_type (type, unknown_type_node); - return t; - } + t = build_tree_list (error_mark_node, fnfields); + TREE_TYPE (t) = build_offset_type (type, unknown_type_node); + return t; } /* 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 (basetypes, name, 1, 0); + t = lookup_field (basebinfo, name, 1, 0); if (t == error_mark_node) return error_mark_node; @@ -2070,9 +1720,8 @@ build_offset_ref (cname, name) values can be returned without further ado. */ if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) { - assemble_external (t); - TREE_USED (t) = 1; - return t; + mark_used (t); + return convert_from_reference (t); } if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t)) @@ -2082,80 +1731,16 @@ build_offset_ref (cname, name) } /* static class functions too. */ - if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) + if (TREE_CODE (t) == FUNCTION_DECL + && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) my_friendly_abort (53); - /* In member functions, the form `cname::name' is no longer - equivalent to `this->cname::name'. */ + /* In member functions, the form `type::name' is no longer + equivalent to `this->type::name', at least not until + resolve_offset_ref. */ return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t); } -/* Given an object EXP and a member function reference MEMBER, - return the address of the actual member function. */ -tree -get_member_function (exp_addr_ptr, exp, member) - tree *exp_addr_ptr; - tree exp, member; -{ - tree ctype = TREE_TYPE (exp); - tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0)); - - if (TYPE_VIRTUAL_P (ctype) - || (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype))) - { - tree e0, e1, e3; - tree exp_addr; - - /* Save away the unadulterated `this' pointer. */ - exp_addr = save_expr (*exp_addr_ptr); - - /* Cast function to signed integer. */ - e0 = build1 (NOP_EXPR, integer_type_node, function); - - /* There is a hack here that takes advantage of - twos complement arithmetic, and the fact that - there are more than one UNITS to the WORD. - If the high bit is set for the `function', - then we pretend it is a virtual function, - and the array indexing will knock this bit - out the top, leaving a valid index. */ - if (UNITS_PER_WORD <= 1) - my_friendly_abort (54); - - e1 = build (GT_EXPR, boolean_type_node, e0, integer_zero_node); - e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr, - build_tree_list (NULL_TREE, e1))); - e1 = save_expr (e1); - - if (TREE_SIDE_EFFECTS (*exp_addr_ptr)) - { - exp = build_indirect_ref (exp_addr, NULL_PTR); - *exp_addr_ptr = exp_addr; - } - - /* This is really hairy: if the function pointer is a pointer - to a non-virtual member function, then we can't go mucking - with the `this' pointer (any more than we already have to - this point). If it is a pointer to a virtual member function, - then we have to adjust the `this' pointer according to - what the virtual function table tells us. */ - - e3 = build_vfn_ref (exp_addr_ptr, exp, e0); - my_friendly_assert (e3 != error_mark_node, 213); - - /* Change this pointer type from `void *' to the - type it is really supposed to be. */ - TREE_TYPE (e3) = TREE_TYPE (function); - - /* If non-virtual, use what we had originally. Otherwise, - use the value we get from the virtual function table. */ - *exp_addr_ptr = build_conditional_expr (e1, exp_addr, *exp_addr_ptr); - - function = build_conditional_expr (e1, function, e3); - } - return build_indirect_ref (function, NULL_PTR); -} - /* If a OFFSET_REF made it through to here, then it did not have its address taken. */ @@ -2169,9 +1754,17 @@ resolve_offset_ref (exp) tree basetype, addr; if (TREE_CODE (exp) == TREE_LIST) - return build_unary_op (ADDR_EXPR, exp, 0); + { + cp_pedwarn ("assuming & on overloaded member function"); + return build_unary_op (ADDR_EXPR, exp, 0); + } - if (TREE_CODE (exp) != OFFSET_REF) + if (TREE_CODE (exp) == OFFSET_REF) + { + member = TREE_OPERAND (exp, 1); + base = TREE_OPERAND (exp, 0); + } + else { my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214); if (TYPE_OFFSET_BASETYPE (type) != current_class_type) @@ -2181,17 +1774,13 @@ resolve_offset_ref (exp) } member = exp; type = TREE_TYPE (type); - base = C_C_D; - } - else - { - member = TREE_OPERAND (exp, 1); - base = TREE_OPERAND (exp, 0); + base = current_class_ref; } if ((TREE_CODE (member) == VAR_DECL && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) - || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE) + || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE) { /* These were static members. */ if (mark_addressable (member) == 0) @@ -2199,9 +1788,13 @@ resolve_offset_ref (exp) return member; } + if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE) + return member; + /* Syntax error can cause a member which should have been seen as static to be grok'd as non-static. */ - if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE) + if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE) { if (TREE_ADDRESSABLE (member) == 0) { @@ -2215,37 +1808,38 @@ resolve_offset_ref (exp) /* The first case is really just a reference to a member of `this'. */ if (TREE_CODE (member) == FIELD_DECL - && (base == C_C_D + && (base == current_class_ref || (TREE_CODE (base) == NOP_EXPR && TREE_OPERAND (base, 0) == error_mark_node))) { - tree basetype_path; - enum access_type access; + tree basetype_path, access; if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) basetype = TYPE_OFFSET_BASETYPE (type); else basetype = DECL_CONTEXT (member); - base = current_class_decl; + base = current_class_ptr; if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0) { error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base))); return error_mark_node; } - addr = convert_pointer_to (basetype, base); + /* Kludge: we need to use basetype_path now, because + convert_pointer_to will bash it. */ access = compute_access (basetype_path, member); - if (access == access_public) + 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) + 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) + if (access == access_private_node) { cp_error_at ("member `%D' is private", member); error ("in this context"); @@ -2254,24 +1848,39 @@ resolve_offset_ref (exp) my_friendly_abort (55); } - /* 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)) == METHOD_TYPE) + /* Ensure that we have an object. */ + if (TREE_CODE (base) == NOP_EXPR + && TREE_OPERAND (base, 0) == error_mark_node) + addr = error_mark_node; + else { - basetype = DECL_CLASS_CONTEXT (member); - addr = convert_pointer_to (basetype, addr); - return build_unary_op (ADDR_EXPR, get_member_function (&addr, build_indirect_ref (addr, NULL_PTR), member), 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); } - else if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE) + + if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE) { + if (addr == error_mark_node) + { + cp_error ("object missing in `%E'", exp); + return error_mark_node; + } + basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member)); addr = convert_pointer_to (basetype, addr); - member = convert (ptrdiff_type_node, - build_unary_op (ADDR_EXPR, member, 0)); + member = cp_convert (ptrdiff_type_node, + build_unary_op (ADDR_EXPR, member, 0)); + + /* 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); + return build1 (INDIRECT_REF, type, build (PLUS_EXPR, build_pointer_type (type), addr, member)); @@ -2300,7 +1909,7 @@ decl_constant_value (decl) && ! pedantic #endif /* 0 */ && DECL_INITIAL (decl) != 0 - && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK + && 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. */ @@ -2318,499 +1927,18 @@ decl_constant_value (decl) return decl; } -/* Friend handling routines. */ -/* Friend data structures: - - Lists of friend functions come from TYPE_DECL nodes. Since all - aggregate types are automatically typedef'd, these nodes are guaranteed - to exist. - - The TREE_PURPOSE of a friend list is the name of the friend, - and its TREE_VALUE is another list. - - For each element of that list, either the TREE_VALUE or the TREE_PURPOSE - will be filled in, but not both. The TREE_VALUE of that list is an - individual function which is a friend. The TREE_PURPOSE of that list - indicates a type in which all functions by that name are friends. - - Lists of friend classes come from _TYPE nodes. Love that consistency - thang. */ - -int -is_friend_type (type1, type2) - tree type1, type2; -{ - return is_friend (type1, type2); -} - -int -is_friend (type, supplicant) - tree type, supplicant; -{ - int declp; - register tree list; - - if (supplicant == NULL_TREE || type == NULL_TREE) - return 0; - - declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd'); - - if (declp) - /* It's a function decl. */ - { - tree list = DECL_FRIENDLIST (TYPE_NAME (type)); - tree name = DECL_NAME (supplicant); - tree ctype; - - if (DECL_FUNCTION_MEMBER_P (supplicant)) - ctype = DECL_CLASS_CONTEXT (supplicant); - else - ctype = NULL_TREE; - - for (; list ; list = TREE_CHAIN (list)) - { - if (name == TREE_PURPOSE (list)) - { - tree friends = TREE_VALUE (list); - name = DECL_ASSEMBLER_NAME (supplicant); - for (; friends ; friends = TREE_CHAIN (friends)) - { - if (ctype == TREE_PURPOSE (friends)) - return 1; - if (name == DECL_ASSEMBLER_NAME (TREE_VALUE (friends))) - return 1; - } - break; - } - } - } - else - /* It's a type. */ - { - if (type == supplicant) - return 1; - - list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_NAME (type))); - for (; list ; list = TREE_CHAIN (list)) - if (supplicant == TREE_VALUE (list)) - return 1; - } - - { - tree context; - - if (! declp) - context = DECL_CONTEXT (TYPE_NAME (supplicant)); - else if (DECL_FUNCTION_MEMBER_P (supplicant)) - context = DECL_CLASS_CONTEXT (supplicant); - else - context = NULL_TREE; - - if (context) - return is_friend (type, context); - } - - return 0; -} - -/* Add a new friend to the friends of the aggregate type TYPE. - DECL is the FUNCTION_DECL of the friend being added. */ -static void -add_friend (type, decl) - tree type, decl; -{ - tree typedecl = TYPE_NAME (type); - tree list = DECL_FRIENDLIST (typedecl); - tree name = DECL_NAME (decl); - - while (list) - { - if (name == TREE_PURPOSE (list)) - { - tree friends = TREE_VALUE (list); - for (; friends ; friends = TREE_CHAIN (friends)) - { - if (decl == TREE_VALUE (friends)) - { - cp_warning ("`%D' is already a friend of class `%T'", - decl, type); - cp_warning_at ("previous friend declaration of `%D'", - TREE_VALUE (friends)); - return; - } - } - TREE_VALUE (list) = tree_cons (error_mark_node, decl, - TREE_VALUE (list)); - return; - } - 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; - } - } -} - -/* Declare that every member function NAME in FRIEND_TYPE - (which may be NULL_TREE) is a friend of type TYPE. */ -static void -add_friends (type, name, friend_type) - tree type, name, friend_type; -{ - tree typedecl = TYPE_NAME (type); - tree list = DECL_FRIENDLIST (typedecl); - - while (list) - { - if (name == TREE_PURPOSE (list)) - { - tree friends = TREE_VALUE (list); - while (friends && TREE_PURPOSE (friends) != friend_type) - friends = TREE_CHAIN (friends); - if (friends) - if (friend_type) - warning ("method `%s::%s' is already a friend of class", - TYPE_NAME_STRING (friend_type), - IDENTIFIER_POINTER (name)); - else - warning ("function `%s' is already a friend of class `%s'", - IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (DECL_NAME (typedecl))); - else - TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE, - TREE_VALUE (list)); - return; - } - list = TREE_CHAIN (list); - } - DECL_FRIENDLIST (typedecl) = - 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"); - } -} - -/* Set up a cross reference so that type TYPE will make member function - CTYPE::DECL a friend when CTYPE is finally defined. For more than - one, set up a cross reference so that functions with the name DECL - and type CTYPE know that they are friends of TYPE. */ -static void -xref_friend (type, decl, ctype) - tree type, decl, ctype; -{ - tree friend_decl = TYPE_NAME (ctype); -#if 0 - tree typedecl = TYPE_NAME (type); - tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl)); - - DECL_UNDEFINED_FRIENDS (typedecl) = t; -#else - tree t = 0; -#endif - SET_DECL_WAITING_FRIENDS (friend_decl, - tree_cons (type, t, - DECL_WAITING_FRIENDS (friend_decl))); - TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = decl; -} - -/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already - been defined, we make all of its member functions friends of - TYPE. If not, we make it a pending friend, which can later be added - when its definition is seen. If a type is defined, then its TYPE_DECL's - DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend - classes that are not defined. If a type has not yet been defined, - then the DECL_WAITING_FRIENDS contains a list of types - waiting to make it their friend. Note that these two can both - be in use at the same time! */ -void -make_friend_class (type, friend_type) - tree type, friend_type; -{ - tree classes; - - if (IS_SIGNATURE (type)) - { - error ("`friend' declaration in signature definition"); - return; - } - if (IS_SIGNATURE (friend_type)) - { - error ("signature type `%s' declared `friend'", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (friend_type)))); - return; - } - if (type == friend_type) - { - pedwarn ("class `%s' is implicitly friends with itself", - TYPE_NAME_STRING (type)); - return; - } - - GNU_xref_hier (TYPE_NAME_STRING (type), - TYPE_NAME_STRING (friend_type), 0, 0, 1); - - classes = CLASSTYPE_FRIEND_CLASSES (type); - while (classes && TREE_VALUE (classes) != friend_type) - classes = TREE_CHAIN (classes); - if (classes) - warning ("class `%s' is already friends with class `%s'", - TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type)); - else - { - CLASSTYPE_FRIEND_CLASSES (type) - = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); - } -} - -/* Main friend processor. This is large, and for modularity purposes, - has been removed from grokdeclarator. It returns `void_type_node' - to indicate that something happened, though a FIELD_DECL is - not returned. - - CTYPE is the class this friend belongs to. - - DECLARATOR is the name of the friend. - - DECL is the FUNCTION_DECL that the friend is. - - In case we are parsing a friend which is part of an inline - definition, we will need to store PARM_DECL chain that comes - with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL. - - FLAGS is just used for `grokclassfn'. - - QUALS say what special qualifies should apply to the object - pointed to by `this'. */ -tree -do_friend (ctype, declarator, decl, parmdecls, flags, quals) - tree ctype, declarator, decl, parmdecls; - enum overload_flags flags; - tree quals; -{ - /* Every decl that gets here is a friend of something. */ - DECL_FRIEND_P (decl) = 1; - - if (ctype) - { - tree cname = TYPE_NAME (ctype); - if (TREE_CODE (cname) == TYPE_DECL) - 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, cname, decl, flags, quals); - if (TYPE_SIZE (ctype) != 0) - check_classfn (ctype, cname, decl); - - if (TREE_TYPE (decl) != error_mark_node) - { - if (TYPE_SIZE (ctype)) - { - /* We don't call pushdecl here yet, or ever on this - actual FUNCTION_DECL. We must preserve its TREE_CHAIN - until the end. */ - make_decl_rtl (decl, NULL_PTR, 1); - add_friend (current_class_type, decl); - } - else - { - register char *classname - = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (ctype))); - - error ("member declared as friend before type `%s' defined", - classname); - } - } - } - else - { - /* Possibly a bunch of method friends. */ - - /* Get the class they belong to. */ - tree ctype = IDENTIFIER_TYPE_VALUE (cname); - - /* This class is defined, use its methods now. */ - if (TYPE_SIZE (ctype)) - { - tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0); - if (fields) - add_friends (current_class_type, declarator, ctype); - else - error ("method `%s' is not a member of class `%s'", - IDENTIFIER_POINTER (declarator), - IDENTIFIER_POINTER (cname)); - } - else - /* Note: DECLARATOR actually has more than one; in this - case, we're making sure that fns with the name DECLARATOR - and type CTYPE know they are friends of the current - class type. */ - xref_friend (current_class_type, declarator, ctype); - decl = void_type_node; - } - } - else if (TREE_CODE (decl) == FUNCTION_DECL - && ((IDENTIFIER_LENGTH (declarator) == 4 - && IDENTIFIER_POINTER (declarator)[0] == 'm' - && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) - || (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; - } - /* A global friend. - @@ or possibly a friend from a base class ?!? */ - else if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* Friends must all go through the overload machinery, - even though they may not technically be overloaded. - - 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; - DECL_CLASS_CONTEXT (decl) = current_class_type; - - /* We can call pushdecl here, because the TREE_CHAIN of this - FUNCTION_DECL is not needed for other purposes. */ - decl = pushdecl (decl); - - make_decl_rtl (decl, NULL_PTR, 1); - add_friend (current_class_type, decl); - - DECL_FRIEND_P (decl) = 1; -#if 0 - TREE_OVERLOADED (declarator) = 1; -#endif - } - else - { - /* @@ Should be able to ingest later definitions of this function - before use. */ - tree decl = lookup_name_nonclass (declarator); - if (decl == NULL_TREE) - { - warning ("implicitly declaring `%s' as struct", - IDENTIFIER_POINTER (declarator)); - decl = xref_tag (record_type_node, declarator, NULL_TREE, 1); - decl = TYPE_NAME (decl); - } - - /* 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))) - { - warning ("`friend %s' archaic, use `friend class %s' instead", - IDENTIFIER_POINTER (declarator), - IDENTIFIER_POINTER (declarator)); - decl = TREE_TYPE (TREE_PURPOSE (decl)); - } - - 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; -} - -/* TYPE has now been defined. It may, however, have a number of things - waiting make make it their friend. We resolve these references - here. */ -void -embrace_waiting_friends (type) - tree type; -{ - tree decl = TYPE_NAME (type); - tree waiters; - - if (TREE_CODE (decl) != TYPE_DECL) - return; - - for (waiters = DECL_WAITING_FRIENDS (decl); waiters; - waiters = TREE_CHAIN (waiters)) - { - tree waiter = TREE_PURPOSE (waiters); -#if 0 - tree waiter_prev = TREE_VALUE (waiters); -#endif - tree decl = TREE_TYPE (waiters); - tree name = decl ? (TREE_CODE (decl) == IDENTIFIER_NODE - ? decl : DECL_NAME (decl)) : NULL_TREE; - if (name) - { - /* @@ There may be work to be done since we have not verified - @@ consistency between original and friend declarations - @@ of the functions waiting to become friends. */ - tree field = lookup_fnfields (TYPE_BINFO (type), name, 0); - if (field) - if (decl == name) - add_friends (waiter, name, type); - else - add_friend (waiter, decl); - else - error_with_file_and_line (DECL_SOURCE_FILE (TYPE_NAME (waiter)), - DECL_SOURCE_LINE (TYPE_NAME (waiter)), - "no method `%s' defined in class `%s' to be friend", - IDENTIFIER_POINTER (DECL_NAME (TREE_TYPE (waiters))), - TYPE_NAME_STRING (type)); - } - else - make_friend_class (type, waiter); - -#if 0 - if (TREE_CHAIN (waiter_prev)) - TREE_CHAIN (waiter_prev) = TREE_CHAIN (TREE_CHAIN (waiter_prev)); - else - DECL_UNDEFINED_FRIENDS (TYPE_NAME (waiter)) = NULL_TREE; -#endif - } -} - /* Common subroutines of build_new and build_vec_delete. */ /* Common interface for calling "builtin" functions that are not really builtin. */ -tree +static tree build_builtin_call (type, node, arglist) tree type; tree node; tree arglist; { - tree rval = build (CALL_EXPR, type, node, arglist, 0); + 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; @@ -2851,11 +1979,9 @@ build_new (placement, decl, init, use_global_new) tree decl, init; int use_global_new; { - tree type, true_type, size, rval; - tree nelts; - tree alloc_expr, alloc_temp; + tree type, rval; + tree nelts = NULL_TREE, t; int has_array = 0; - enum tree_code code = NEW_EXPR; tree pending_sizes = NULL_TREE; @@ -2866,7 +1992,7 @@ build_new (placement, decl, init, use_global_new) { tree absdcl = TREE_VALUE (decl); tree last_absdcl = NULL_TREE; - int old_immediate_size_expand; + int old_immediate_size_expand = 0; if (current_function_decl && DECL_CONSTRUCTOR_P (current_function_decl)) @@ -2903,9 +2029,14 @@ build_new (placement, decl, init, use_global_new) { if (this_nelts == NULL_TREE) error ("new of array type fails to specify size"); + else if (processing_template_decl) + { + nelts = this_nelts; + absdcl = TREE_OPERAND (absdcl, 0); + } else { - this_nelts = save_expr (convert (sizetype, this_nelts)); + this_nelts = save_expr (cp_convert (sizetype, this_nelts)); absdcl = TREE_OPERAND (absdcl, 0); if (this_nelts == integer_zero_node) { @@ -2925,7 +2056,7 @@ build_new (placement, decl, init, use_global_new) else TREE_VALUE (decl) = absdcl; - type = true_type = groktypename (decl); + type = groktypename (decl); if (! type || type == error_mark_node) { immediate_size_expand = old_immediate_size_expand; @@ -2945,7 +2076,7 @@ build_new (placement, decl, init, use_global_new) { /* An aggregate type. */ type = IDENTIFIER_TYPE_VALUE (decl); - decl = TYPE_NAME (type); + decl = TYPE_MAIN_DECL (type); } else { @@ -2954,18 +2085,29 @@ build_new (placement, decl, init, use_global_new) my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215); type = TREE_TYPE (decl); } - true_type = type; } else if (TREE_CODE (decl) == TYPE_DECL) { type = TREE_TYPE (decl); - true_type = type; } else { type = decl; - true_type = type; - decl = TYPE_NAME (type); + decl = TYPE_MAIN_DECL (type); + } + + if (processing_template_decl) + { + if (has_array) + t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE), + build_min_nt (ARRAY_REF, NULL_TREE, nelts), + NULL_TREE); + else + t = type; + + rval = build_min_nt (NEW_EXPR, placement, t, init); + NEW_EXPR_USE_GLOBAL (rval) = use_global_new; + return rval; } /* ``A reference cannot be created by the new operator. A reference @@ -2974,7 +2116,7 @@ build_new (placement, decl, init, use_global_new) if (TREE_CODE (type) == REFERENCE_TYPE) { error ("new cannot be applied to a reference type"); - type = true_type = TREE_TYPE (type); + type = TREE_TYPE (type); } if (TREE_CODE (type) == FUNCTION_TYPE) @@ -2990,8 +2132,57 @@ build_new (placement, decl, init, use_global_new) { nelts = array_type_nelts_top (type); has_array = 1; - type = true_type = TREE_TYPE (type); + type = TREE_TYPE (type); + } + + if (has_array) + t = build_nt (ARRAY_REF, type, nelts); + else + t = type; + + rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init); + NEW_EXPR_USE_GLOBAL (rval) = use_global_new; + TREE_SIDE_EFFECTS (rval) = 1; + + /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ + rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); + TREE_NO_UNUSED_WARNING (rval) = 1; + + if (pending_sizes) + rval = build_compound_expr (chainon (pending_sizes, + build_expr_list (NULL_TREE, rval))); + + return rval; +} + +/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return + value is immediately handed to expand_expr. */ + +tree +build_new_1 (exp) + tree exp; +{ + tree placement, init; + tree type, true_type, size, rval; + tree nelts = NULL_TREE; + tree alloc_expr, alloc_node = NULL_TREE; + int has_array = 0; + enum tree_code code = NEW_EXPR; + int use_cookie, nothrow, check_new; + int use_global_new; + + placement = TREE_OPERAND (exp, 0); + type = TREE_OPERAND (exp, 1); + init = TREE_OPERAND (exp, 2); + use_global_new = NEW_EXPR_USE_GLOBAL (exp); + + if (TREE_CODE (type) == ARRAY_REF) + { + has_array = 1; + nelts = TREE_OPERAND (type, 1); + type = TREE_OPERAND (type, 0); } + true_type = type; if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) type = TYPE_MAIN_VARIANT (type); @@ -3004,24 +2195,22 @@ build_new (placement, decl, init, use_global_new) nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1); true_type = TREE_TYPE (true_type); } + + if (!complete_type_or_else (true_type)) + return error_mark_node; + if (has_array) size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type), nelts, 1)); else size = size_in_bytes (type); - if (true_type == void_type_node) + if (TREE_CODE (true_type) == VOID_TYPE) { error ("invalid type `void' for new"); return error_mark_node; } - if (TYPE_SIZE (true_type) == 0) - { - incomplete_type_error (0, true_type); - return error_mark_node; - } - if (TYPE_LANG_SPECIFIC (true_type) && CLASSTYPE_ABSTRACT_VIRTUALS (true_type)) { @@ -3035,9 +2224,22 @@ build_new (placement, decl, init, use_global_new) return error_mark_node; } +#if 1 /* Get a little extra space to store a couple of things before the new'ed - array. */ - if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)) + array, if this isn't the default placement new. */ + + 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) { tree extra = BI_header_size; @@ -3045,21 +2247,17 @@ build_new (placement, decl, init, use_global_new) } if (has_array) - code = VEC_NEW_EXPR; - - /* Allocate the object. */ - if (! use_global_new && TYPE_LANG_SPECIFIC (true_type) - && (TYPE_GETS_NEW (true_type) & (1 << has_array))) - rval = build_opfncall (code, LOOKUP_NORMAL, - build_pointer_type (true_type), size, placement); - else if (placement) { - rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, - ptr_type_node, size, placement); - rval = convert (build_pointer_type (true_type), rval); + code = VEC_NEW_EXPR; + + if (init && pedantic) + cp_pedwarn ("initialization in array new"); } - else if (! has_array && flag_this_is_variable > 0 - && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node) + + /* Allocate the object. */ + + if (! has_array && ! placement && flag_this_is_variable > 0 + && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node) { if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) rval = NULL_TREE; @@ -3071,33 +2269,50 @@ build_new (placement, decl, init, use_global_new) } else { - rval = build_builtin_call (build_pointer_type (true_type), - has_array ? BIVN : BIN, - build_tree_list (NULL_TREE, size)); -#if 0 - /* See comment above as to why this is disabled. */ - if (alignment) - { - rval = build (PLUS_EXPR, build_pointer_type (true_type), rval, - alignment); - rval = build (BIT_AND_EXPR, build_pointer_type (true_type), - rval, build1 (BIT_NOT_EXPR, integer_type_node, - alignment)); - } -#endif - TREE_CALLS_NEW (rval) = 1; + int susp; + + if (flag_exceptions) + /* We will use RVAL when generating an exception handler for + this new-expression, so we must save it. */ + susp = suspend_momentary (); + + rval = build_op_new_call + (code, true_type, expr_tree_cons (NULL_TREE, size, placement), + LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL)); + rval = cp_convert (build_pointer_type (true_type), rval); + + if (flag_exceptions) + resume_momentary (susp); + } + + /* unless an allocation function is declared with an empty excep- + tion-specification (_except.spec_), throw(), it indicates failure to + allocate storage by throwing a bad_alloc exception (clause _except_, + _lib.bad.alloc_); it returns a non-null pointer otherwise If the allo- + cation function is declared with an empty exception-specification, + throw(), it returns null to indicate failure to allocate storage and a + non-null pointer otherwise. + + So check for a null exception spec on the op new we just called. */ + + nothrow = 0; + if (rval) + { + /* The CALL_EXPR. */ + 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; } + check_new = flag_check_new || nothrow; - if (flag_check_new && rval) + if ((check_new || flag_exceptions) && rval) { - /* For array new, we need to make sure that the call to new is - not expanded as part of the RTL_EXPR for the initialization, - so we can't just use save_expr here. */ - - alloc_temp = get_temp_name (TREE_TYPE (rval), 0); - alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval); - TREE_SIDE_EFFECTS (alloc_expr) = 1; - rval = alloc_temp; + alloc_expr = get_target_expr (rval); + alloc_node = rval = TREE_OPERAND (alloc_expr, 0); } else alloc_expr = NULL_TREE; @@ -3106,25 +2321,25 @@ build_new (placement, decl, init, use_global_new) sure we have some extra bytes in that case for the BI_header_size cookies? And how does that interact with the code below? (mrs) */ /* Finish up some magic for new'ed arrays */ - if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) && rval != NULL_TREE) + if (use_cookie && rval != NULL_TREE) { tree extra = BI_header_size; tree cookie, exp1; - rval = convert (ptr_type_node, rval); /* convert to void * first */ - rval = convert (string_type_node, rval); /* lets not add void* and ints */ + rval = convert (string_type_node, rval); /* for ptr arithmetic */ rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1)); /* Store header info. */ - cookie = build_indirect_ref (build (MINUS_EXPR, build_pointer_type (BI_header_type), + cookie = build_indirect_ref (build (MINUS_EXPR, + build_pointer_type (BI_header_type), rval, extra), NULL_PTR); exp1 = build (MODIFY_EXPR, void_type_node, - build_component_ref (cookie, nc_nelts_field_id, 0, 0), + build_component_ref (cookie, nc_nelts_field_id, + NULL_TREE, 0), nelts); TREE_SIDE_EFFECTS (exp1) = 1; - rval = convert (build_pointer_type (true_type), rval); - TREE_CALLS_NEW (rval) = 1; - TREE_SIDE_EFFECTS (rval) = 1; - rval = build_compound_expr (tree_cons (NULL_TREE, exp1, - build_tree_list (NULL_TREE, rval))); + rval = cp_convert (build_pointer_type (true_type), rval); + rval = build_compound_expr + (expr_tree_cons (NULL_TREE, exp1, + build_expr_list (NULL_TREE, rval))); } if (rval == error_mark_node) @@ -3163,7 +2378,6 @@ build_new (placement, decl, init, use_global_new) rval); TREE_NO_UNUSED_WARNING (rval) = 1; TREE_SIDE_EFFECTS (rval) = 1; - TREE_CALLS_NEW (rval) = 1; } else if (! has_array) { @@ -3175,7 +2389,7 @@ build_new (placement, decl, init, use_global_new) if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) { - init = tree_cons (NULL_TREE, integer_one_node, init); + init = expr_tree_cons (NULL_TREE, integer_one_node, init); flags |= LOOKUP_HAS_IN_CHARGE; } @@ -3184,96 +2398,90 @@ build_new (placement, decl, init, use_global_new) if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE) newrval = build_indirect_ref (newrval, NULL_PTR); - newrval = build_method_call (newrval, constructor_name_full (true_type), - init, NULL_TREE, flags); + newrval = build_method_call (newrval, ctor_identifier, + init, TYPE_BINFO (true_type), flags); - if (newrval) - { - rval = newrval; - TREE_HAS_CONSTRUCTOR (rval) = 1; - } - else - rval = error_mark_node; - } - else if (current_function_decl == NULL_TREE) - { - extern tree static_aggregates; + if (newrval == NULL_TREE || newrval == error_mark_node) + return error_mark_node; - /* In case of static initialization, SAVE_EXPR is good enough. */ - rval = save_expr (rval); - rval = copy_to_permanent (rval); - init = copy_to_permanent (init); - init = expand_vec_init (decl, rval, - build_binary_op (MINUS_EXPR, nelts, - integer_one_node, 1), - init, 0); - init = copy_to_permanent (init); - static_aggregates = perm_tree_cons (init, rval, static_aggregates); + rval = newrval; + TREE_HAS_CONSTRUCTOR (rval) = 1; } else + 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) { - /* Have to wrap this in RTL_EXPR for two cases: - in base or member initialization and if we - are a branch of a ?: operator. Since we - can't easily know the latter, just do it always. */ - tree xval = make_node (RTL_EXPR); - - /* If we want to check the value of the allocation expression, - and the number of elements in the array is not a constant, we - *must* expand the SAVE_EXPR for nelts in alloc_expr before we - expand it in the actual initialization. So we need to build up - an RTL_EXPR for alloc_expr. Sigh. */ - if (alloc_expr && ! TREE_CONSTANT (nelts)) + enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR; + tree cleanup, fn = NULL_TREE; + int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL); + + /* All cleanups must last longer than normal. */ + int yes = suspend_momentary (); + + if (placement) { - tree xval = make_node (RTL_EXPR); - rtx rtxval; - TREE_TYPE (xval) = TREE_TYPE (alloc_expr); - do_pending_stack_adjust (); - start_sequence_for_rtl_expr (xval); - emit_note (0, -1); - rtxval = expand_expr (alloc_expr, NULL, VOIDmode, 0); - do_pending_stack_adjust (); - TREE_SIDE_EFFECTS (xval) = 1; - RTL_EXPR_SEQUENCE (xval) = get_insns (); - end_sequence (); - RTL_EXPR_RTL (xval) = rtxval; - TREE_TYPE (xval) = TREE_TYPE (alloc_expr); - alloc_expr = xval; - } + flags |= LOOKUP_SPECULATIVELY; - TREE_TYPE (xval) = TREE_TYPE (rval); - do_pending_stack_adjust (); - start_sequence_for_rtl_expr (xval); + /* We expect alloc_expr to look like a TARGET_EXPR around + a NOP_EXPR around the CALL_EXPR we want. */ + fn = TREE_OPERAND (alloc_expr, 1); + fn = TREE_OPERAND (fn, 0); + } - /* As a matter of principle, `start_sequence' should do this. */ - emit_note (0, -1); + /* Copy size to the saveable obstack. */ + size = copy_node (size); - rval = save_expr (rval); - rval = expand_vec_init (decl, rval, - build_binary_op (MINUS_EXPR, nelts, - integer_one_node, 1), - init, 0); + cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn); - do_pending_stack_adjust (); + resume_momentary (yes); - TREE_SIDE_EFFECTS (xval) = 1; - TREE_CALLS_NEW (xval) = 1; - RTL_EXPR_SEQUENCE (xval) = get_insns (); - end_sequence (); + /* Ack! First we allocate the memory. Then we set our sentry + variable to true, and expand a cleanup that deletes the memory + if sentry is true. Then we run the constructor and store the + returned pointer in buf. Then we clear sentry and return buf. */ - if (TREE_CODE (rval) == SAVE_EXPR) - { - /* Errors may cause this to not get evaluated. */ - if (SAVE_EXPR_RTL (rval) == 0) - SAVE_EXPR_RTL (rval) = const0_rtx; - RTL_EXPR_RTL (xval) = SAVE_EXPR_RTL (rval); - } - else + if (cleanup) { - my_friendly_assert (TREE_CODE (rval) == VAR_DECL, 217); - RTL_EXPR_RTL (xval) = DECL_RTL (rval); +#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); + sentry = TREE_OPERAND (begin, 0); + + yes = suspend_momentary (); + TREE_OPERAND (begin, 2) + = build (COND_EXPR, void_type_node, sentry, + cleanup, void_zero_node); + resume_momentary (yes); + + rval = get_target_expr (rval); + + end = build (MODIFY_EXPR, TREE_TYPE (sentry), + sentry, boolean_false_node); + TREE_SIDE_EFFECTS (end) = 1; + + buf = TREE_OPERAND (rval, 0); + + 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 } - rval = xval; } } else if (TYPE_READONLY (true_type)) @@ -3281,45 +2489,27 @@ build_new (placement, decl, init, use_global_new) done: - if (alloc_expr) + if (alloc_expr && rval == alloc_node) { - /* Did we modify the storage? */ - if (rval != alloc_temp) - { - tree ifexp = build_binary_op (NE_EXPR, alloc_expr, - integer_zero_node, 1); - rval = build_conditional_expr (ifexp, rval, alloc_temp); - } - else - rval = alloc_expr; + rval = TREE_OPERAND (alloc_expr, 1); + alloc_expr = NULL_TREE; } - if (rval && TREE_TYPE (rval) != build_pointer_type (type)) + if (check_new && alloc_expr) { - /* The type of new int [3][3] is not int *, but int [3] * */ - rval = build_c_cast (build_pointer_type (type), rval, 0); + /* Did we modify the storage? */ + tree ifexp = build_binary_op (NE_EXPR, alloc_node, + integer_zero_node, 1); + rval = build_conditional_expr (ifexp, rval, alloc_node); } - if (pending_sizes) - rval = build_compound_expr (chainon (pending_sizes, - build_tree_list (NULL_TREE, rval))); + if (alloc_expr) + rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); - if (flag_gc) + if (rval && TREE_TYPE (rval) != build_pointer_type (type)) { - extern tree gc_visible; - tree objbits; - tree update_expr; - - rval = save_expr (rval); - /* We don't need a `headof' operation to do this because - we know where the object starts. */ - objbits = build1 (INDIRECT_REF, unsigned_type_node, - build (MINUS_EXPR, ptr_type_node, - rval, c_sizeof_nowarn (unsigned_type_node))); - update_expr = build_modify_expr (objbits, BIT_IOR_EXPR, gc_visible); - rval = build_compound_expr (tree_cons (NULL_TREE, rval, - tree_cons (NULL_TREE, update_expr, - build_tree_list (NULL_TREE, rval)))); + /* The type of new int [3][3] is not int *, but int [3] * */ + rval = build_c_cast (build_pointer_type (type), rval); } return rval; @@ -3333,7 +2523,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, int use_global_delete; { tree virtual_size; - tree ptype = build_pointer_type (type); + tree ptype = build_pointer_type (type = complete_type (type)); tree size_exp = size_in_bytes (type); /* Temporary variables used by the loop. */ @@ -3355,9 +2545,6 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, This is also the containing expression returned by this function. */ tree controller = NULL_TREE; - /* This is the BLOCK to record the symbol binding for debugging. */ - tree block; - if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type)) { loop = integer_zero_node; @@ -3373,22 +2560,20 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, base, virtual_size))); DECL_REGISTER (tbase) = 1; - controller = build (BIND_EXPR, void_type_node, tbase, 0, 0); + controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; - block = build_block (tbase, 0, 0, 0, 0); - add_block_current_level (block); if (auto_delete != integer_zero_node && auto_delete != integer_two_node) { - tree base_tbd = convert (ptype, - build_binary_op (MINUS_EXPR, - convert (ptr_type_node, base), - BI_header_size, - 1)); + tree base_tbd = cp_convert (ptype, + build_binary_op (MINUS_EXPR, + cp_convert (ptr_type_node, base), + BI_header_size, + 1)); /* This is the real size */ virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); - body = build_tree_list (NULL_TREE, + body = build_expr_list (NULL_TREE, build_x_delete (ptype, base_tbd, 2 | use_global_delete, virtual_size)); @@ -3400,24 +2585,24 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, else body = NULL_TREE; - body = tree_cons (NULL_TREE, + body = expr_tree_cons (NULL_TREE, build_delete (ptype, tbase, auto_delete, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1), body); - body = tree_cons (NULL_TREE, + body = expr_tree_cons (NULL_TREE, build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)), body); - body = tree_cons (NULL_TREE, + body = expr_tree_cons (NULL_TREE, build (EXIT_EXPR, void_type_node, build (EQ_EXPR, boolean_type_node, base, tbase)), body); loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body)); - loop = tree_cons (NULL_TREE, tbase_init, - tree_cons (NULL_TREE, loop, NULL_TREE)); + loop = expr_tree_cons (NULL_TREE, tbase_init, + expr_tree_cons (NULL_TREE, loop, NULL_TREE)); loop = build_compound_expr (loop); no_destructor: @@ -3438,12 +2623,12 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, base_tbd = base; else { - base_tbd = convert (ptype, - build_binary_op (MINUS_EXPR, - convert (string_type_node, base), - BI_header_size, - 1)); - /* True size with header. */ + base_tbd = cp_convert (ptype, + build_binary_op (MINUS_EXPR, + cp_convert (string_type_node, base), + BI_header_size, + 1)); + /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); } deallocate_expr = build_x_delete (ptype, base_tbd, @@ -3458,8 +2643,8 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, if (loop && deallocate_expr != integer_zero_node) { - body = tree_cons (NULL_TREE, loop, - tree_cons (NULL_TREE, deallocate_expr, NULL_TREE)); + body = expr_tree_cons (NULL_TREE, loop, + expr_tree_cons (NULL_TREE, deallocate_expr, NULL_TREE)); body = build_compound_expr (body); } else @@ -3477,13 +2662,14 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, return controller; } else - return convert (void_type_node, body); + 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. */ + static tree build_array_eh_cleanup (base, count, type) tree base, count, type; @@ -3520,7 +2706,7 @@ expand_vec_init (decl, base, maxindex, init, from_array) tree type = TREE_TYPE (TREE_TYPE (base)); tree size; - maxindex = convert (integer_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex); if (maxindex == error_mark_node) return error_mark_node; @@ -3538,15 +2724,15 @@ expand_vec_init (decl, base, maxindex, init, from_array) /* 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), - convert (build_pointer_type (type), null_pointer_node)); + cp_convert (build_pointer_type (type), null_pointer_node)); base = default_conversion (base); - base = convert (build_pointer_type (type), base); + base = cp_convert (build_pointer_type (type), base); expand_assignment (rval, base, 0, 0); base = get_temp_regvar (build_pointer_type (type), base); if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR - && TREE_TYPE (init) == TREE_TYPE (decl)) + && (! decl || TREE_TYPE (init) == TREE_TYPE (decl))) { /* Initialization of array from {...}. */ tree elts = CONSTRUCTOR_ELTS (init); @@ -3574,7 +2760,7 @@ expand_vec_init (decl, base, maxindex, init, from_array) goto done_init; } - iterator = get_temp_regvar (integer_type_node, + iterator = get_temp_regvar (ptrdiff_type_node, build_int_2 (host_i, 0)); init = NULL_TREE; goto init_by_default; @@ -3596,9 +2782,10 @@ expand_vec_init (decl, base, maxindex, init, from_array) { tree itype; - iterator = get_temp_regvar (integer_type_node, maxindex); + iterator = get_temp_regvar (ptrdiff_type_node, maxindex); init_by_default: + itype = NULL_TREE; /* If initializing one array from another, initialize element by element. */ @@ -3629,9 +2816,12 @@ expand_vec_init (decl, base, maxindex, init, from_array) expand_start_cond (build (GE_EXPR, boolean_type_node, iterator, integer_zero_node), 0); if (TYPE_NEEDS_DESTRUCTOR (type)) - start_protect (); + expand_eh_region_start (); expand_start_loop_continue_elsewhere (1); + /* The initialization of each array element is a full-expression. */ + expand_start_target_temps (); + if (from_array) { tree to = build1 (INDIRECT_REF, type, base); @@ -3667,9 +2857,13 @@ expand_vec_init (decl, base, maxindex, init, from_array) if (base2) expand_assignment (base2, 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, integer_type_node, iterator, integer_one_node), minus_one)); + build (PREDECREMENT_EXPR, ptrdiff_type_node, iterator, integer_one_node), minus_one)); if (obey_regdecls) { @@ -3678,13 +2872,35 @@ expand_vec_init (decl, base, maxindex, init, from_array) use_variable (DECL_RTL (base2)); } expand_end_loop (); - if (TYPE_NEEDS_DESTRUCTOR (type)) - end_protect (build_array_eh_cleanup (rval, - build_binary_op (MINUS_EXPR, - maxindex, - iterator, - 1), - type)); + 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)); @@ -3709,6 +2925,7 @@ expand_vec_init (decl, base, maxindex, init, from_array) static object, see Free Store 12.5 ANSI C++ WP. This does not call any destructors. */ + tree build_x_delete (type, addr, which_delete, virtual_size) tree type, addr; @@ -3717,16 +2934,10 @@ build_x_delete (type, addr, which_delete, virtual_size) { int use_global_delete = which_delete & 1; int use_vec_delete = !!(which_delete & 2); - tree rval; enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR; + int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL); - if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) - && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete))) - rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE); - else - rval = build_builtin_call (void_type_node, use_vec_delete ? BIVD : BID, - build_tree_list (NULL_TREE, addr)); - return rval; + return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE); } /* Generate a call to a destructor. TYPE is the type to cast ADDR to. @@ -3740,6 +2951,7 @@ build_x_delete (type, addr, which_delete, virtual_size) flags. See cp-tree.h for more info. This function does not delete an object's virtual base classes. */ + tree build_delete (type, addr, auto_delete, flags, use_global_delete) tree type, addr; @@ -3747,11 +2959,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) int flags; int use_global_delete; { - tree function, parms; tree member; tree expr; tree ref; - int ptr; if (addr == error_mark_node) return error_mark_node; @@ -3766,18 +2976,15 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) if (TREE_CODE (type) == POINTER_TYPE) { type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - if (TYPE_SIZE (type) == 0) - { - incomplete_type_error (0, type); - return error_mark_node; - } + if (!complete_type_or_else (type)) + 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_tree_list (NULL_TREE, addr)); + build_expr_list (NULL_TREE, addr)); } if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); @@ -3785,7 +2992,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) /* throw away const and volatile on target type of addr */ addr = convert_force (build_pointer_type (type), addr, 0); ref = build_indirect_ref (addr, NULL_PTR); - ptr = 1; } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3798,7 +3004,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) return error_mark_node; } return build_vec_delete (addr, array_type_nelts (type), - c_sizeof_nowarn (TREE_TYPE (type)), auto_delete, integer_two_node, use_global_delete); } @@ -3816,12 +3021,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) else addr = convert_force (build_pointer_type (type), addr, 0); - if (TREE_CODE (addr) == NOP_EXPR - && TREE_OPERAND (addr, 0) == current_class_decl) - ref = C_C_D; - else - ref = build_indirect_ref (addr, NULL_PTR); - ptr = 0; + ref = build_indirect_ref (addr, NULL_PTR); } my_friendly_assert (IS_AGGR_TYPE (type), 220); @@ -3831,37 +3031,27 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) if (auto_delete == integer_zero_node) return void_zero_node; - /* Pass the size of the object down to the operator delete() in - addition to the ADDR. */ - if (TYPE_GETS_REG_DELETE (type) && !use_global_delete) - { - tree virtual_size = c_sizeof_nowarn (type); - return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, - virtual_size, NULL_TREE); - } - - /* Call the builtin operator delete. */ - return build_builtin_call (void_type_node, BID, - build_tree_list (NULL_TREE, addr)); + return build_op_delete_call + (DELETE_EXPR, addr, c_sizeof_nowarn (type), + LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL), + NULL_TREE); } - parms = build_tree_list (NULL_TREE, addr); /* Below, we will reverse the order in which these calls are made. If we have a destructor, then that destructor will take care of the base classes; otherwise, we must do that here. */ if (TYPE_HAS_DESTRUCTOR (type)) { - tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0)); - tree basetypes = TYPE_BINFO (type); tree passed_auto_delete; tree do_delete = NULL_TREE; + tree ifexp; if (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_tree_list (NULL_TREE, addr)); + (void_type_node, BID, build_expr_list (NULL_TREE, addr)); cond = fold (build (COND_EXPR, void_type_node, cond, call, void_zero_node)); @@ -3874,106 +3064,29 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) else passed_auto_delete = auto_delete; - if (flags & LOOKUP_PROTECT) - { - enum access_type access = compute_access (basetypes, dtor); - - if (access == access_private) - { - if (flags & LOOKUP_COMPLAIN) - cp_error ("destructor for type `%T' is private in this scope", type); - return error_mark_node; - } - else if (access == access_protected) - { - if (flags & LOOKUP_COMPLAIN) - cp_error ("destructor for type `%T' is protected in this scope", type); - return error_mark_node; - } - } + expr = build_method_call + (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete), + NULL_TREE, flags); - /* Once we are in a destructor, try not going through - the virtual function table to find the next destructor. */ - if (DECL_VINDEX (dtor) - && ! (flags & LOOKUP_NONVIRTUAL) - && TREE_CODE (auto_delete) != PARM_DECL - && (ptr == 1 || ! resolves_to_fixed_type_p (ref, 0))) - { - tree binfo, basetype; - /* The code below is probably all broken. See call.c for the - complete right way to do this. this offsets may not be right - in the below. (mrs) */ - /* This destructor must be called via virtual function table. */ - dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (DECL_CONTEXT (dtor)), 0); - basetype = DECL_CLASS_CONTEXT (dtor); - binfo = get_binfo (basetype, - TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))), - 0); - expr = convert_pointer_to_real (binfo, TREE_VALUE (parms)); - if (expr != TREE_VALUE (parms)) - { - expr = fold (expr); - ref = build_indirect_ref (expr, NULL_PTR); - TREE_VALUE (parms) = expr; - } - function = build_vfn_ref (&TREE_VALUE (parms), ref, DECL_VINDEX (dtor)); - if (function == error_mark_node) - return error_mark_node; - TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor)); - TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete); - expr = build_function_call (function, parms); - if (do_delete) - expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); - if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0) - { - /* Handle the case where a virtual destructor is - being called on an item that is 0. + if (do_delete) + expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); - @@ Does this really need to be done? */ - tree ifexp = build_binary_op(NE_EXPR, addr, integer_zero_node,1); -#if 0 - if (TREE_CODE (ref) == VAR_DECL - || TREE_CODE (ref) == COMPONENT_REF) - warning ("losing in build_delete"); -#endif - expr = build (COND_EXPR, void_type_node, - ifexp, expr, void_zero_node); - } - } + if (flags & LOOKUP_DESTRUCTOR) + /* Explicit destructor call; don't check for null pointer. */ + ifexp = integer_one_node; else - { - tree ifexp; - - if ((flags & LOOKUP_DESTRUCTOR) - || TREE_CODE (ref) == VAR_DECL - || TREE_CODE (ref) == PARM_DECL - || TREE_CODE (ref) == COMPONENT_REF - || TREE_CODE (ref) == ARRAY_REF) - /* These can't be 0. */ - ifexp = integer_one_node; - else - /* Handle the case where a non-virtual destructor is - being called on an item that is 0. */ - ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node, 1); - - /* Used to mean that this destructor was known to be empty, - but that's now obsolete. */ - my_friendly_assert (DECL_INITIAL (dtor) != void_type_node, 221); - - TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete); - expr = build_function_call (dtor, parms); - if (do_delete) - expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); - - if (ifexp != integer_one_node) - expr = build (COND_EXPR, void_type_node, - ifexp, expr, void_zero_node); - } + /* Handle deleting a null pointer. */ + ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node, 1)); + + if (ifexp != integer_one_node) + expr = build (COND_EXPR, void_type_node, + ifexp, expr, void_zero_node); + return expr; } else { - /* This can get visibilities wrong. */ + /* We only get here from finish_function for a destructor. */ tree binfos = BINFO_BASETYPES (TYPE_BINFO (type)); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE; @@ -3981,57 +3094,24 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) tree parent_auto_delete = auto_delete; tree cond; - /* If this type does not have a destructor, but does have - operator delete, call the parent parent destructor (if any), - but let this node do the deleting. Otherwise, it is ok - to let the parent destructor do the deleting. */ - if (TYPE_GETS_REG_DELETE (type) && !use_global_delete) - { - parent_auto_delete = integer_zero_node; - if (auto_delete == integer_zero_node) - cond = NULL_TREE; - else - { - tree virtual_size; - - /* This is probably wrong. It should be the size of the - virtual object being deleted. */ - virtual_size = c_sizeof_nowarn (type); - - expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, - virtual_size, NULL_TREE); - if (expr == error_mark_node) - return error_mark_node; - if (auto_delete != integer_one_node) - cond = build (COND_EXPR, void_type_node, - build (BIT_AND_EXPR, integer_type_node, - auto_delete, integer_one_node), - expr, void_zero_node); - else - cond = expr; - } - } + /* If we have member delete or vbases, we call delete in + finish_function. */ + if (auto_delete == integer_zero_node) + cond = NULL_TREE; else if (base_binfo == NULL_TREE - || (TREE_VIA_VIRTUAL (base_binfo) == 0 - && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))) + || ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))) { - tree virtual_size; - - /* This is probably wrong. It should be the size of the virtual - object being deleted. */ - virtual_size = c_sizeof_nowarn (type); - 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_tree_list (NULL_TREE, addr)), + build_expr_list (NULL_TREE, addr)), void_zero_node); } else cond = NULL_TREE; if (cond) - exprstmt = build_tree_list (NULL_TREE, cond); + exprstmt = build_expr_list (NULL_TREE, cond); if (base_binfo && ! TREE_VIA_VIRTUAL (base_binfo) @@ -4044,9 +3124,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) else this_auto_delete = integer_zero_node; - expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), addr, - this_auto_delete, flags, 0); - exprstmt = tree_cons (NULL_TREE, expr, exprstmt); + expr = build_scoped_method_call + (ref, base_binfo, dtor_identifier, + build_expr_list (NULL_TREE, this_auto_delete)); + exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } /* Take care of the remaining baseclasses. */ @@ -4057,15 +3138,11 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) || TREE_VIA_VIRTUAL (base_binfo)) continue; - /* May be zero offset if other baseclasses are virtual. */ - expr = fold (build (PLUS_EXPR, build_pointer_type (BINFO_TYPE (base_binfo)), - addr, BINFO_OFFSET (base_binfo))); - - expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr, - integer_zero_node, - flags, 0); + expr = build_scoped_method_call + (ref, base_binfo, dtor_identifier, + build_expr_list (NULL_TREE, integer_zero_node)); - exprstmt = tree_cons (NULL_TREE, expr, exprstmt); + exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) @@ -4074,10 +3151,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) continue; if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member))) { - tree this_member = build_component_ref (ref, DECL_NAME (member), 0, 0); + tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0); tree this_type = TREE_TYPE (member); expr = build_delete (this_type, this_member, integer_two_node, flags, 0); - exprstmt = tree_cons (NULL_TREE, expr, exprstmt); + exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } } @@ -4104,7 +3181,7 @@ build_vbase_delete (type, decl) { tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)), addr, 0); - result = tree_cons (NULL_TREE, + result = expr_tree_cons (NULL_TREE, build_delete (TREE_TYPE (this_addr), this_addr, integer_zero_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0), @@ -4130,10 +3207,11 @@ build_vbase_delete (type, decl) values we'd have to extract. (We could use MAXINDEX with pointers to confirm the size, and trap if the numbers differ; not clear that it'd be worth bothering.) */ + tree -build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, +build_vec_delete (base, maxindex, auto_delete_vec, auto_delete, use_global_delete) - tree base, maxindex, elt_size; + tree base, maxindex; tree auto_delete_vec, auto_delete; int use_global_delete; { @@ -4146,7 +3224,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, base = stabilize_reference (base); - /* Since we can use base many times, save_expr it. */ + /* Since we can use base many times, save_expr it. */ if (TREE_SIDE_EFFECTS (base)) base = save_expr (base); @@ -4156,7 +3234,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type), base, BI_header_size); tree cookie = build_indirect_ref (cookie_addr, NULL_PTR); - maxindex = build_component_ref (cookie, nc_nelts_field_id, 0, 0); + maxindex = build_component_ref (cookie, nc_nelts_field_id, NULL_TREE, 0); do type = TREE_TYPE (type); while (TREE_CODE (type) == ARRAY_TYPE); @@ -4171,7 +3249,8 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, } else { - error ("type to vector delete is neither pointer or array type"); + if (base != error_mark_node) + error ("type to vector delete is neither pointer or array type"); return error_mark_node; } diff --git a/contrib/gcc/cp/input.c b/contrib/gcc/cp/input.c index 77a6468..5a73fea 100644 --- a/contrib/gcc/cp/input.c +++ b/contrib/gcc/cp/input.c @@ -29,22 +29,16 @@ Boston, MA 02111-1307, USA. */ lex.c for very minor efficiency gains (primarily in function inlining). */ -#include -#include "obstack.h" +#include "system.h" extern FILE *finput; -struct pending_input *save_pending_input (); -void restore_pending_input (); - struct input_source { /* saved string */ char *str; int length; /* current position, when reading as input */ int offset; - /* obstack to free this input string from when finished, if any */ - struct obstack *obstack; /* linked list maintenance */ struct input_source *next; /* values to restore after reading all of current string */ @@ -65,6 +59,25 @@ extern int lineno; #define inline #endif +#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 ()) +#else +#define GETC() getc (finput) +#endif + +extern void feed_input PROTO((char *, int)); +extern void put_input PROTO((int)); +extern void put_back PROTO((int)); +extern int getch PROTO((void)); +extern int input_redirected PROTO((void)); + +static inline struct input_source * allocate_input PROTO((void)); +static inline void free_input PROTO((struct input_source *)); +static inline void end_input PROTO((void)); +static inline int sub_getch PROTO((void)); + static inline struct input_source * allocate_input () { @@ -78,7 +91,6 @@ allocate_input () } inp = (struct input_source *) xmalloc (sizeof (struct input_source)); inp->next = 0; - inp->obstack = 0; return inp; } @@ -86,9 +98,6 @@ static inline void free_input (inp) struct input_source *inp; { - if (inp->obstack) - obstack_free (inp->obstack, inp->str); - inp->obstack = 0; inp->str = 0; inp->length = 0; inp->next = free_inputs; @@ -102,10 +111,9 @@ static int putback_char = -1; inline void -feed_input (str, len, delete) +feed_input (str, len) char *str; int len; - struct obstack *delete; { struct input_source *inp = allocate_input (); @@ -115,7 +123,6 @@ feed_input (str, len, delete) inp->str = str; inp->length = len; - inp->obstack = delete; inp->offset = 0; inp->next = input; inp->filename = input_filename; @@ -129,6 +136,22 @@ feed_input (str, len, delete) struct pending_input *to_be_restored; /* XXX */ extern int end_of_file; +static inline void +end_input () +{ + struct input_source *inp = input; + + end_of_file = 0; + input = inp->next; + input_filename = inp->filename; + lineno = inp->lineno; + /* Get interface/implementation back in sync. */ + extract_interface_info (); + putback_char = inp->putback_char; + restore_pending_input (inp->input); + free_input (inp); +} + static inline int sub_getch () { @@ -140,32 +163,20 @@ sub_getch () } if (input) { - if (input->offset == input->length) + if (input->offset >= input->length) { - struct input_source *inp = input; my_friendly_assert (putback_char == -1, 223); - to_be_restored = inp->input; - input->offset++; - return EOF; - } - else if (input->offset > input->length) - { - struct input_source *inp = input; - - end_of_file = 0; - input = inp->next; - input_filename = inp->filename; - lineno = inp->lineno; - /* Get interface/implementation back in sync. */ - extract_interface_info (); - putback_char = inp->putback_char; - free_input (inp); + ++(input->offset); + if (input->offset - input->length < 64) + return EOF; + + /* We must be stuck in an error-handling rule; give up. */ + end_input (); return getch (); } - if (input) - return input->str[input->offset++]; + return (unsigned char)input->str[input->offset++]; } - return getc (finput); + return GETC (); } inline diff --git a/contrib/gcc/cp/lang-options.h b/contrib/gcc/cp/lang-options.h index d551357..5c50332 100644 --- a/contrib/gcc/cp/lang-options.h +++ b/contrib/gcc/cp/lang-options.h @@ -18,90 +18,106 @@ 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_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", - "-fall-virtual", - "-fno-all-virtual", - "-falt-external-templates", - "-fno-alt-external-templates", - "-fansi-overloading", - "-fno-ansi-overloading", - "-fcadillac", - "-fno-cadillac", - "-fcheck-new", - "-fno-check-new", - "-fconserve-space", - "-fno-conserve-space", - "-fdefault-inline", - "-fno-default-inline", - "-frtti", - "-fno-rtti", - "-felide-constructors", - "-fno-elide-constructors", - "-fenum-int-equiv", - "-fno-enum-int-equiv", - "-fexternal-templates", - "-fno-external-templates", - "-ffor-scope", - "-fno-for-scope", - "-fgc", - "-fno-gc", - "-fgnu-keywords", - "-fno-gnu-keywords", - "-fhandle-exceptions", - "-fno-handle-exceptions", - "-fhandle-signatures", - "-fno-handle-signatures", - "-fhuge-objects", - "-fno-huge-objects", - "-fimplement-inlines", - "-fno-implement-inlines", - "-fimplicit-templates", - "-fno-implicit-templates", - "-flabels-ok", - "-fno-labels-ok", - "-fmemoize-lookups", - "-fno-memoize-lookups", - "-fnonnull-objects", - "-fno-nonnull-objects", - "-foperator-names", - "-fno-operator-names", - "-frepo", - "-fno-repo", - "-fsave-memoized", - "-fno-save-memoized", - "-fshort-temps", - "-fno-short-temps", - "-fstats", - "-fno-stats", - "-fstrict-prototype", - "-fno-strict-prototype", - "-fthis-is-variable", - "-fno-this-is-variable", - "-fvtable-thunks", - "-fno-vtable-thunks", - "-fxref", - "-fno-xref", + { "-+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" }, + { "-fno-all-virtual", "" }, + { "-falt-external-templates", "Change when template instances are emitted" }, + { "-fno-alt-external-templates", "" }, + { "-fansi-overloading", "" }, + { "-fno-ansi-overloading", "" }, + { "-fcheck-new", "Check the return value of new" }, + { "-fno-check-new", "" }, + { "-fconserve-space", "Reduce size of object files" }, + { "-fno-conserve-space", "" }, + { "-fdefault-inline", "" }, + { "-fno-default-inline", "Do not inline mmeber functions be default"}, + { "-frtti", "" }, + { "-fno-rtti", "Do not generate run time type descriptor information" }, + { "-felide-constructors", "" }, + { "-fno-elide-constructors", "" }, + { "-fenum-int-equiv", "" }, + { "-fno-enum-int-equiv", "" }, + { "-fexternal-templates", "" }, + { "-fno-external-templates", "" }, + { "-ffor-scope", "" }, + { "-fno-for-scope", "Scope of for-init-statement vars extends outside" }, + { "-fguiding-decls", "Implement guiding declarations" }, + { "-fno-guiding-decls", "" }, + { "-fgnu-keywords", "" }, + { "-fno-gnu-keywords", "Do not recognise GNU defined keywords" }, + { "-fhandle-exceptions", "Enable exception handling" }, + { "-fno-handle-exceptions", "" }, + { "-fhandle-signatures", "Handle signature language constructs" }, + { "-fno-handle-signatures", "" }, + { "-fhonor-std", "Do not ignore the namespace standard" }, + { "-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", "" }, + { "-flabels-ok", "Labels can be used as first class objects" }, + { "-fno-labels-ok", "" }, + { "-fmemoize-lookups", "Enable caching of member function resolutions" }, + { "-fno-memoize-lookups", "" }, + { "-fname-mangling-version-", "Set the version of name mangling to use" }, + { "-fnew-abi", "Enable experimental ABI changes" }, + { "-fno-new-abi", "" }, + { "-fnonnull-objects", "" }, + { "-fno-nonnull-objects", "Do not assume that a reference is always valid" }, + { "-foperator-names", "Recognise and/bitand/bitor/compl/not/or/xor" }, + { "-fno-operator-names", "" }, + { "-foptional-diags", "" }, + { "-fno-optional-diags", "Disable optional diagnostics" }, + { "-frepo", "Enable automatic template instantiation" }, + { "-fno-repo", "" }, + { "-fsave-memoized", "Save cache of member function resolutions" }, + { "-fno-save-memoized", "" }, + { "-fsquangle", "Enable squashed name mangling" }, + { "-fno-squangle", "" }, + { "-fstats", "Display statistics accumulated during compilation" }, + { "-fno-stats", "" }, + { "-fstrict-prototype", "" }, + { "-fno-strict-prototype", "Do not assume that empty prototype means no args" }, + { "-ftemplate-depth-", "Specify maximum template instantiation depth"}, + { "-fthis-is-variable", "Make 'this' not be type '* const'" }, + { "-fno-this-is-variable", "" }, + { "-fvtable-thunks", "Implement vtables using thunks" }, + { "-fno-vtable-thunks", "" }, + { "-fweak", "Emit common-like symbols as weak symbols" }, + { "-fno-weak", "" }, + { "-fxref", "Emit cross referencing information" }, + { "-fno-xref", "" }, - "-Wreturn-type", - "-Wno-return-type", - "-Woverloaded-virtual", - "-Wno-overloaded-virtual", - "-Wtemplate-debugging", - "-Wno-template-debugging", - "-Wctor-dtor-privacy", - "-Wno-ctor-dtor-privacy", - "-Wnon-virtual-dtor", - "-Wno-non-virtual-dtor", - "-Wextern-inline", - "-Wno-extern-inline", - "-Wreorder", - "-Wno-reorder", - "-Wsynth", - "-Wno-synth", + { "-Wreturn-type", "Warn about inconsistent return types" }, + { "-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", "" }, + { "-Wnon-virtual-dtor", "Warn about non virtual destructors" }, + { "-Wno-non-virtual-dtor", "" }, + { "-Wextern-inline", "Warn when a function is declared extern, then inline" }, + { "-Wno-extern-inline", "" }, + { "-Wreorder", "Warn when the compiler reorders code" }, + { "-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", "" }, + { "-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", "" }, diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h index fbb72c9..b208ca1 100644 --- a/contrib/gcc/cp/lang-specs.h +++ b/contrib/gcc/cp/lang-specs.h @@ -21,39 +21,74 @@ Boston, MA 02111-1307, USA. */ /* This is the contribution to the `default_compilers' array in gcc.c for g++. */ - {".cc", "@c++"}, - {".cxx", "@c++"}, - {".cpp", "@c++"}, - {".c++", "@c++"}, - {".C", "@c++"}, + {".cc", {"@c++"}}, + {".cp", {"@c++"}}, + {".cxx", {"@c++"}}, + {".cpp", {"@c++"}}, + {".c++", {"@c++"}}, + {".C", {"@c++"}}, {"@c++", - "cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\ +#if USE_CPPLIB + { + "%{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\ - %{ansi:-trigraphs -$ -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\ - %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\ - %{traditional-cpp:-traditional} %{trigraphs}\ + %{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}\ + %{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\ + %{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}\ + %{!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*}\ + %{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\ + %{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\ + %{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}\ %{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\ + "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.ii} %1 %2\ %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\ - %{traditional} %{v:-version} %{pg:-p} %{p}\ + %{v:-version} %{pg:-p} %{p}\ %{f*} %{+e*} %{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 }}}}"}, - {".ii", "@c++-cpp-output"}, + %{!pipe:%g.s} %A\n }}}}"}}, +#endif /* ! USE_CPPLIB */ + {".ii", {"@c++-cpp-output"}}, {"@c++-cpp-output", - "%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\ + {"%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\ - %{traditional} %{v:-version} %{pg:-p} %{p}\ + %{v:-version} %{pg:-p} %{p}\ %{f*} %{+e*} %{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 }}}}"}, + %{!pipe:%g.s} %A\n }}}}"}}, diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c index 9e51883..57639ad 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, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -25,64 +25,100 @@ Boston, MA 02111-1307, USA. */ /* Cause the `yydebug' variable to be defined. */ #define YYDEBUG 1 -#include -#include -#include -#include #include "config.h" +#include "system.h" +#include #include "input.h" #include "tree.h" #include "lex.h" -#include "parse.h" #include "cp-tree.h" +#include "parse.h" #include "flags.h" #include "obstack.h" #include "c-pragma.h" +#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 #include #endif -#ifndef errno -extern int errno; /* needed for VAX. */ -#endif -extern jmp_buf toplevel; - #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free -extern struct obstack *expression_obstack, permanent_obstack; -extern struct obstack *current_obstack, *saveable_obstack; +#ifndef DIR_SEPARATOR +#define DIR_SEPARATOR '/' +#endif -extern double atof (); +extern struct obstack permanent_obstack; +extern struct obstack *current_obstack, *saveable_obstack; -extern char *get_directive_line (); /* In c-common.c */ +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 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 readescape PROTO((int *)); +static char *extend_token_buffer PROTO((char *)); +static void consume_string PROTO((struct obstack *, int)); +static void set_typedecl_interface_info PROTO((tree, tree)); +static void feed_defarg PROTO((tree, tree)); +static int set_vardecl_interface_info PROTO((tree, tree)); +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)); +#endif +#ifdef GATHER_STATISTICS +#ifdef REDUCE_LENGTH +static int reduce_cmp PROTO((int *, int *)); +static int token_cmp PROTO((int *, int *)); +#endif +#endif /* Given a file name X, return the nondirectory portion. Keep in mind that X can be computed more than once. */ -#ifndef FILE_NAME_NONDIRECTORY -#define FILE_NAME_NONDIRECTORY(X) \ - (rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X) -#endif - -extern char *index (); -extern char *rindex (); - -void extract_interface_info (); -void yyerror (); +char * +file_name_nondirectory (x) + char *x; +{ + char *tmp = (char *) rindex (x, '/'); + if (DIR_SEPARATOR != '/' && ! tmp) + tmp = (char *) rindex (x, DIR_SEPARATOR); + if (tmp) + return (char *) (tmp + 1); + else + return x; +} /* This obstack is needed to hold text. It is not safe to use TOKEN_BUFFER because `check_newline' calls `yylex'. */ struct obstack inline_text_obstack; -static char *inline_text_firstobj; - -/* This obstack is used to hold information about methods to be - synthesized. It should go away when synthesized methods are handled - properly (i.e. only when needed). */ -struct obstack synth_obstack; -static char *synth_firstobj; +char *inline_text_firstobj; +#if USE_CPPLIB +#include "cpplib.h" +extern cpp_reader parse_in; +extern cpp_options parse_options; +extern unsigned char *yy_cur, *yy_lim; +#else +FILE *finput; +#endif int end_of_file; /* Pending language change. @@ -101,7 +137,7 @@ extern struct obstack token_obstack; #else extern void put_back (/* int */); extern int input_redirected (); -extern void feed_input (/* char *, int, struct obstack * */); +extern void feed_input (/* char *, int */); #endif /* Holds translations from TREE_CODEs to operator name strings, @@ -132,52 +168,43 @@ tree ridpointers[(int) RID_MAX]; /* We may keep statistics about how long which files took to compile. */ static int header_time, body_time; -static tree get_time_identifier (); static tree filename_times; static tree this_filename_time; -/* For implementing #pragma unit. */ -tree current_unit_name; -tree current_unit_language; - /* Array for holding counts of the numbers of tokens seen. */ extern int *token_count; - -/* Textual definition used for default functions. */ -static void default_copy_constructor_body (); -static void default_assign_ref_body (); /* Return something to represent absolute declarators containing a *. TARGET is the absolute declarator that the * contains. - TYPE_QUALS is a list of modifiers such as const or volatile + CV_QUALIFIERS is a list of modifiers such as const or volatile to apply to the pointer type, represented as identifiers. We return an INDIRECT_REF whose "contents" are TARGET and whose type is the modifier list. */ tree -make_pointer_declarator (type_quals, target) - tree type_quals, target; +make_pointer_declarator (cv_qualifiers, target) + tree cv_qualifiers, target; { if (target && TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target)) error ("type name expected before `*'"); target = build_parse_node (INDIRECT_REF, target); - TREE_TYPE (target) = type_quals; + TREE_TYPE (target) = cv_qualifiers; return target; } /* Return something to represent absolute declarators containing a &. TARGET is the absolute declarator that the & contains. - TYPE_QUALS is a list of modifiers such as const or volatile + CV_QUALIFIERS is a list of modifiers such as const or volatile to apply to the reference type, represented as identifiers. We return an ADDR_EXPR whose "contents" are TARGET and whose type is the modifier list. */ tree -make_reference_declarator (type_quals, target) - tree type_quals, target; +make_reference_declarator (cv_qualifiers, target) + tree cv_qualifiers, target; { if (target) { @@ -195,9 +222,26 @@ make_reference_declarator (type_quals, target) error ("type name expected before `&'"); } target = build_parse_node (ADDR_EXPR, target); - TREE_TYPE (target) = type_quals; + TREE_TYPE (target) = cv_qualifiers; + return target; +} + +tree +make_call_declarator (target, parms, cv_qualifiers, exception_specification) + tree target, parms, cv_qualifiers, exception_specification; +{ + target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers); + TREE_TYPE (target) = exception_specification; return target; } + +void +set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification) + tree call_declarator, cv_qualifiers, exception_specification; +{ + TREE_OPERAND (call_declarator, 2) = cv_qualifiers; + TREE_TYPE (call_declarator) = exception_specification; +} /* Build names and nodes for overloaded operators. */ @@ -252,9 +296,6 @@ int interface_unknown; /* whether or not we know this class /* lexical analyzer */ -/* File used for outputting assembler code. */ -extern FILE *asm_out_file; - #ifndef WCHAR_TYPE_SIZE #ifdef INT_TYPE_SIZE #define WCHAR_TYPE_SIZE INT_TYPE_SIZE @@ -272,13 +313,10 @@ char *token_buffer; /* Pointer to token buffer. #include "hash.h" -int check_newline (); /* Nonzero tells yylex to ignore \ in string constants. */ static int ignore_escape_flag = 0; -static int skip_white_space (); - static tree get_time_identifier (name) char *name; @@ -296,7 +334,7 @@ get_time_identifier (name) end_temporary_allocation (); IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0); IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1); - IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times; + SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times); filename_times = time_identifier; pop_obstacks (); } @@ -319,13 +357,13 @@ my_get_run_time () /* Table indexed by tree code giving a string containing a character classifying the tree code. Possibilities are - t, d, s, c, r, <, 1 and 2. See cp/tree.def for details. */ + t, d, s, c, r, <, 1 and 2. See cp/cp-tree.def for details. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, -char *cplus_tree_code_type[] = { - "x", -#include "tree.def" +char cplus_tree_code_type[] = { + 'x', +#include "cp-tree.def" }; #undef DEFTREECODE @@ -337,7 +375,7 @@ char *cplus_tree_code_type[] = { int cplus_tree_code_length[] = { 0, -#include "tree.def" +#include "cp-tree.def" }; #undef DEFTREECODE @@ -347,22 +385,28 @@ int cplus_tree_code_length[] = { char *cplus_tree_code_name[] = { "@@dummy", -#include "tree.def" +#include "cp-tree.def" }; #undef DEFTREECODE /* toplev.c needs to call these. */ void +lang_init_options () +{ + /* Default exceptions on. */ + flag_exceptions = 1; +} + +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. */ put_back (check_newline ()); - - if (flag_cadillac) - cadillac_start (); +#endif if (flag_gnu_xref) GNU_xref_begin (input_filename); init_repo (input_filename); } @@ -394,23 +438,66 @@ init_filename_times () /* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989. Stuck this hack in to get the files open correctly; this is called - in place of init_lex if we are an unexec'd binary. */ + in place of init_parse if we are an unexec'd binary. */ + +#if 0 void reinit_lang_specific () { init_filename_times (); reinit_search_statistics (); } +#endif -void -init_lex () +static int * +init_cpp_parse () +{ +#ifdef GATHER_STATISTICS +#ifdef REDUCE_LENGTH + reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1)); + bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1)); + reduce_count += 1; + token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1)); + bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1)); + token_count += 1; +#endif +#endif + return token_count; +} + +char * +init_parse (filename) + char *filename; { - extern char *(*decl_printable_name) (); extern int flag_no_gnu_keywords; extern int flag_operator_names; int i; +#if USE_CPPLIB + yy_cur = "\n"; + yy_lim = yy_cur + 1; + + parse_in.show_column = 1; + if (! cpp_start_read (&parse_in, filename)) + abort (); +#else + /* Open input file. */ + if (filename == 0 || !strcmp (filename, "-")) + { + finput = stdin; + filename = "stdin"; + } + else + finput = fopen (filename, "r"); + if (finput == 0) + pfatal_with_name (filename); + +#ifdef IO_BUFFER_SIZE + setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE); +#endif +#endif /* !USE_CPPLIB */ + /* Initialize the lookahead machinery. */ init_spew (); @@ -420,18 +507,9 @@ init_lex () init_cplus_expand (); - tree_code_type - = (char **) realloc (tree_code_type, - sizeof (char *) * LAST_CPLUS_TREE_CODE); - tree_code_length - = (int *) realloc (tree_code_length, - sizeof (int) * LAST_CPLUS_TREE_CODE); - tree_code_name - = (char **) realloc (tree_code_name, - sizeof (char *) * LAST_CPLUS_TREE_CODE); - bcopy ((char *)cplus_tree_code_type, - (char *)(tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE), - (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *)); + bcopy (cplus_tree_code_type, + tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE, + (int)LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE); bcopy ((char *)cplus_tree_code_length, (char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE), (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int)); @@ -568,15 +646,13 @@ init_lex () IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1; ansi_opname[(int) COND_EXPR] = get_identifier ("__cn"); IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1; - ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1; + ansi_opname[(int) SIZEOF_EXPR] = get_identifier ("__sz"); + IDENTIFIER_OPNAME_P (ansi_opname[(int) SIZEOF_EXPR]) = 1; init_method (); init_error (); gcc_obstack_init (&inline_text_obstack); inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0); - gcc_obstack_init (&synth_obstack); - synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0); /* Start it at 0, because check_newline is called at the very beginning and will increment it to 1. */ @@ -641,8 +717,11 @@ init_lex () 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. */ + /* 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])); @@ -684,7 +763,7 @@ init_lex () 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++. */ + /* 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])); @@ -694,17 +773,19 @@ init_lex () TREE_TYPE (signature_type_node) = signature_type_node; ridpointers[(int) RID_SIGNATURE] = signature_type_node; + null_node = build_int_2 (0, 0); + ridpointers[RID_NULL] = null_node; + opname_tab[(int) COMPONENT_REF] = "->"; opname_tab[(int) MEMBER_REF] = "->*"; - opname_tab[(int) METHOD_CALL_EXPR] = "->()"; - opname_tab[(int) INDIRECT_REF] = "(unary *)"; + opname_tab[(int) INDIRECT_REF] = "*"; opname_tab[(int) ARRAY_REF] = "[]"; opname_tab[(int) MODIFY_EXPR] = "="; opname_tab[(int) NEW_EXPR] = "new"; opname_tab[(int) DELETE_EXPR] = "delete"; opname_tab[(int) VEC_NEW_EXPR] = "new []"; opname_tab[(int) VEC_DELETE_EXPR] = "delete []"; - opname_tab[(int) COND_EXPR] = "... ? ... : ..."; + opname_tab[(int) COND_EXPR] = "?:"; opname_tab[(int) CALL_EXPR] = "()"; opname_tab[(int) PLUS_EXPR] = "+"; opname_tab[(int) MINUS_EXPR] = "-"; @@ -741,9 +822,9 @@ init_lex () opname_tab[(int) EQ_EXPR] = "=="; opname_tab[(int) NE_EXPR] = "!="; opname_tab[(int) IN_EXPR] = "in"; - opname_tab[(int) RANGE_EXPR] = ".."; - opname_tab[(int) CONVERT_EXPR] = "(unary +)"; - opname_tab[(int) ADDR_EXPR] = "(unary &)"; + opname_tab[(int) RANGE_EXPR] = "..."; + opname_tab[(int) CONVERT_EXPR] = "+"; + opname_tab[(int) ADDR_EXPR] = "&"; opname_tab[(int) PREDECREMENT_EXPR] = "--"; opname_tab[(int) PREINCREMENT_EXPR] = "++"; opname_tab[(int) POSTDECREMENT_EXPR] = "--"; @@ -785,7 +866,7 @@ init_lex () #if 0 /* let's parse things, and if they use it, then give them an error. */ - if (!flag_handle_exceptions) + if (!flag_exceptions) { UNSET_RESERVED_WORD ("throw"); UNSET_RESERVED_WORD ("try"); @@ -793,11 +874,12 @@ init_lex () } #endif - if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords) + if (!flag_rtti || flag_no_gnu_keywords) { UNSET_RESERVED_WORD ("classof"); UNSET_RESERVED_WORD ("headof"); } + if (! flag_handle_signatures || flag_no_gnu_keywords) { /* Easiest way to not recognize signature @@ -822,11 +904,21 @@ init_lex () UNSET_RESERVED_WORD ("xor"); UNSET_RESERVED_WORD ("xor_eq"); } - if (! flag_traditional) - UNSET_RESERVED_WORD ("overload"); - token_count = init_parse (); + token_count = init_cpp_parse (); interface_unknown = 1; + + return filename; +} + +void +finish_parse () +{ +#if USE_CPPLIB + cpp_finish (&parse_in); +#else + fclose (finput); +#endif } void @@ -855,10 +947,14 @@ yyprint (file, yychar, yylval) case IDENTIFIER_DEFN: case TYPENAME_DEFN: case PTYPENAME_DEFN: - case TYPENAME_ELLIPSIS: case SCSPEC: case PRE_PARSED_CLASS_DECL: t = yylval.ttype; + if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == TEMPLATE_DECL) + { + fprintf (file, " `%s'", IDENTIFIER_POINTER (DECL_NAME (t))); + break; + } my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224); if (IDENTIFIER_POINTER (t)) fprintf (file, " `%s'", IDENTIFIER_POINTER (t)); @@ -880,27 +976,19 @@ yyprint (file, yychar, yylval) } } +#if defined(GATHER_STATISTICS) && defined(REDUCE_LENGTH) static int *reduce_count; +#endif + int *token_count; +#if 0 #define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0])) #define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0])) - -int * -init_parse () -{ -#ifdef GATHER_STATISTICS - reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1)); - bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1)); - reduce_count += 1; - token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1)); - bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1)); - token_count += 1; #endif - return token_count; -} #ifdef GATHER_STATISTICS +#ifdef REDUCE_LENGTH void yyhook (yyn) int yyn; @@ -922,11 +1010,13 @@ token_cmp (p, q) return token_count[*q] - token_count[*p]; } #endif +#endif void print_parse_statistics () { #ifdef GATHER_STATISTICS +#ifdef REDUCE_LENGTH #if YYDEBUG != 0 int i; int maxlen = REDUCE_LENGTH; @@ -944,13 +1034,13 @@ print_parse_statistics () qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp); for (i = 0; i < TOKEN_LENGTH; i++) { - int index = sorted[i]; - if (token_count[index] == 0) + int idx = sorted[i]; + if (token_count[idx] == 0) break; - if (token_count[index] < token_count[-1]) + if (token_count[idx] < token_count[-1]) break; fprintf (stderr, "token %d, `%s', count = %d\n", - index, yytname[YYTRANSLATE (index)], token_count[index]); + idx, yytname[YYTRANSLATE (idx)], token_count[idx]); } fprintf (stderr, "\n"); for (i = 0; i < REDUCE_LENGTH; i++) @@ -958,22 +1048,24 @@ print_parse_statistics () qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp); for (i = 0; i < REDUCE_LENGTH; i++) { - int index = sorted[i]; - if (reduce_count[index] == 0) + int idx = sorted[i]; + if (reduce_count[idx] == 0) break; - if (reduce_count[index] < reduce_count[-1]) + if (reduce_count[idx] < reduce_count[-1]) break; fprintf (stderr, "rule %d, line %d, count = %d\n", - index, yyrline[index], reduce_count[index]); + idx, yyrline[idx], reduce_count[idx]); } fprintf (stderr, "\n"); #endif #endif +#endif } /* Sets the value of the 'yydebug' variable to VALUE. This is a function so we don't have to have YYDEBUG defined in order to build the compiler. */ + void set_yydebug (value) int value; @@ -1016,6 +1108,7 @@ static struct impl_files *impl_file_chain; /* Helper function to load global variables with interface information. */ + void extract_interface_info () { @@ -1032,12 +1125,12 @@ extract_interface_info () fileinfo = get_time_identifier (input_filename); fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo); interface_only = TREE_INT_CST_LOW (fileinfo); - if (!processing_template_defn || flag_external_templates) - interface_unknown = TREE_INT_CST_HIGH (fileinfo); + interface_unknown = TREE_INT_CST_HIGH (fileinfo); } /* Return nonzero if S is not considered part of an INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */ + static int interface_strcmp (s) char *s; @@ -1076,7 +1169,7 @@ interface_strcmp (s) return 1; } -void +static void set_typedecl_interface_info (prev, vars) tree prev, vars; { @@ -1085,10 +1178,10 @@ set_typedecl_interface_info (prev, vars) tree type = TREE_TYPE (vars); 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 (vars))); } -void +static int set_vardecl_interface_info (prev, vars) tree prev, vars; { @@ -1097,22 +1190,26 @@ set_vardecl_interface_info (prev, vars) if (CLASSTYPE_INTERFACE_KNOWN (type)) { if (CLASSTYPE_INTERFACE_ONLY (type)) - set_typedecl_interface_info (prev, TYPE_NAME (type)); + set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type)); else CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1; DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type); TREE_PUBLIC (vars) = 1; + return 1; } + return 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 call process_next_inline to start working on the next one. */ + 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) @@ -1121,7 +1218,7 @@ do_pending_inlines () /* Reverse the pending inline functions, since they were cons'd instead of appended. */ { - struct pending_inline *prev = 0, *tail, *bottom = 0; + struct pending_inline *prev = 0, *tail; t = pending_inlines; pending_inlines = 0; @@ -1132,33 +1229,6 @@ do_pending_inlines () t->deja_vu = 1; prev = t; } - - /* This kludge should go away when synthesized methods are handled - properly, i.e. only when needed. */ - for (t = prev; t; t = t->next) - { - if (t->lineno <= 0) - { - tree f = t->fndecl; - DECL_PENDING_INLINE_INFO (f) = 0; - interface_unknown = t->interface == 1; - interface_only = t->interface == 0; - synthesize_method (f); - if (tail) - tail->next = t->next; - else - prev = t->next; - if (! bottom) - bottom = t; - } - else - tail = t; - } - if (bottom) - { - obstack_free (&synth_obstack, bottom); - extract_interface_info (); - } t = prev; } @@ -1166,13 +1236,13 @@ do_pending_inlines () return; /* Now start processing the first inline function. */ - my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE), - 226); - if (t->parm_vec) - push_template_decls (t->parm_vec, t->bindings, 0); + 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, t->can_free ? &inline_text_obstack : 0); + feed_input (t->buf, t->len); lineno = t->lineno; #if 0 if (input_filename != t->filename) @@ -1191,68 +1261,51 @@ do_pending_inlines () /* 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); -#if 0 - if (flag_default_inline && t->fndecl - /* If we're working from a template, don't change - the `inline' state. */ - && t->parm_vec == NULL_TREE) - DECL_INLINE (t->fndecl) = 1; -#endif DECL_PENDING_INLINE_INFO (t->fndecl) = 0; } -extern struct pending_input *to_be_restored; static int nextchar = -1; /* Called from the fndecl rule in the parser when the function just parsed was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from do_pending_inlines). */ + void process_next_inline (t) tree t; { + tree context; struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t); - my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE), - 227); - if (i->parm_vec) - pop_template_decls (i->parm_vec, i->bindings, 0); + context = hack_decl_function_context (i->fndecl); + maybe_end_member_template_processing (i->fndecl); + if (context) + pop_cp_function_context (context); i = i->next; if (yychar == YYEMPTY) yychar = yylex (); if (yychar != END_OF_SAVED_INPUT) { error ("parse error at end of saved function text"); + /* restore_pending_input will abort unless yychar is either - * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're - * hosed, feed back YYEMPTY. - * We also need to discard nextchar, since that may have gotten - * set as well. - */ + END_OF_SAVED_INPUT or YYEMPTY; since we already know we're + hosed, feed back YYEMPTY. We also need to discard nextchar, + since that may have gotten set as well. */ nextchar = -1; } yychar = YYEMPTY; - if (to_be_restored == 0) - my_friendly_abort (123); - restore_pending_input (to_be_restored); - to_be_restored = 0; + end_input (); if (i && i->fndecl != NULL_TREE) { - my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE), - 228); - if (i->parm_vec) - push_template_decls (i->parm_vec, i->bindings, 0); - feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0); + 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); -#if 0 - if (flag_default_inline - /* If we're working from a template, don't change - the `inline' state. */ - && i->parm_vec == NULL_TREE) - DECL_INLINE (i->fndecl) = 1; -#endif DECL_PENDING_INLINE_INFO (i->fndecl) = 0; } if (i) @@ -1367,25 +1420,10 @@ restore_pending_input (p) free (p); } -/* Return next non-whitespace input character, which may come - from `finput', or from `nextchar'. */ -static int -yynextch () -{ - int c; - - if (nextchar >= 0) - { - c = nextchar; - nextchar = -1; - } - else c = getch (); - return skip_white_space (c); -} - /* Unget character CH from the input stream. If RESCAN is non-zero, then we want to `see' this character as the next input token. */ + void yyungetc (ch, rescan) int ch; @@ -1407,106 +1445,30 @@ yyungetc (ch, rescan) } } +void +clear_inline_text_obstack () +{ + obstack_free (&inline_text_obstack, inline_text_firstobj); +} + /* This function stores away the text for an inline function that should be processed later. It decides how much later, and may need to move the info between obstacks; therefore, the caller should not refer to - the T parameter after calling this function. - - This function also stores the list of template-parameter bindings that - will be needed for expanding the template, if any. */ + the T parameter after calling this function. */ static void store_pending_inline (decl, t) tree decl; struct pending_inline *t; { - extern int processing_template_defn; - int delay_to_eof = 0; - struct pending_inline **inlines; - t->fndecl = decl; - /* Default: compile right away, and no extra bindings are needed. */ - t->parm_vec = t->bindings = 0; - if (processing_template_defn) - { - tree type = current_class_type; - /* Assumption: In this (possibly) nested class sequence, only - one name will have template parms. */ - while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't') - { - tree decl = TYPE_NAME (type); - tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl)); - if (tmpl) - { - t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec; - t->bindings = TREE_VALUE (tmpl); - } - type = DECL_CONTEXT (decl); - } - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE - || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) - { - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) - my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type, - 233); - - /* Inline functions can be compiled immediately. Other functions - will be output separately, so if we're in interface-only mode, - punt them now, or output them now if we're doing implementations - and we know no overrides will exist. Otherwise, we delay until - end-of-file, to see if the definition is really required. */ - if (DECL_THIS_INLINE (decl)) - /* delay_to_eof == 0 */; - else if (current_class_type && !interface_unknown) - { - if (interface_only) - { -#if 0 - print_node_brief (stderr, "\ndiscarding text for ", decl, 0); -#endif - if (t->can_free) - obstack_free (&inline_text_obstack, t->buf); - DECL_PENDING_INLINE_INFO (decl) = 0; - return; - } - } - /* Don't delay the processing of virtual functions. */ - else if (DECL_VINDEX (decl) == NULL_TREE) - delay_to_eof = 1; - } - else - my_friendly_abort (58); - } - - if (delay_to_eof) - { - extern struct pending_inline *pending_template_expansions; - - if (t->can_free) - { - char *free_to = t->buf; - t->buf = (char *) obstack_copy (&permanent_obstack, t->buf, - t->len + 1); - t = (struct pending_inline *) obstack_copy (&permanent_obstack, - (char *)t, sizeof (*t)); - obstack_free (&inline_text_obstack, free_to); - } - inlines = &pending_template_expansions; - t->can_free = 0; - } - else - { - inlines = &pending_inlines; - DECL_PENDING_INLINE_INFO (decl) = t; - } + DECL_PENDING_INLINE_INFO (decl) = t; /* Because we use obstacks, we must process these in precise order. */ - t->next = *inlines; - *inlines = t; + t->next = pending_inlines; + pending_inlines = t; } -void reinit_parse_for_block (); - void reinit_parse_for_method (yychar, decl) int yychar; @@ -1516,7 +1478,7 @@ reinit_parse_for_method (yychar, decl) int starting_lineno = lineno; char *starting_filename = input_filename; - reinit_parse_for_block (yychar, &inline_text_obstack, 0); + reinit_parse_for_block (yychar, &inline_text_obstack); len = obstack_object_size (&inline_text_obstack); current_base_init_list = NULL_TREE; @@ -1543,26 +1505,23 @@ reinit_parse_for_method (yychar, decl) t->token_value = 0; t->buf = buf; t->len = len; - t->can_free = 1; t->deja_vu = 0; +#if 0 if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl)) warn_if_unknown_interface (decl); +#endif t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); store_pending_inline (decl, t); } } -/* Consume a block -- actually, a method or template definition beginning - with `:' or `{' -- and save it away on the specified obstack. +/* Consume a block -- actually, a method beginning + with `:' or `{' -- and save it away on the specified obstack. */ - Argument IS_TEMPLATE indicates which set of error messages should be - output if something goes wrong. This should really be cleaned up somehow, - without loss of clarity. */ void -reinit_parse_for_block (pyychar, obstackp, is_template) +reinit_parse_for_block (pyychar, obstackp) int pyychar; struct obstack *obstackp; - int is_template; { register int c = 0; int blev = 1; @@ -1582,13 +1541,13 @@ reinit_parse_for_block (pyychar, obstackp, is_template) look_for_lbrac = 1; blev = 0; } - else if (pyychar == RETURN && !is_template) + else if (pyychar == RETURN) { obstack_grow (obstackp, "return", 6); look_for_lbrac = 1; blev = 0; } - else if (pyychar == TRY && !is_template) + else if (pyychar == TRY) { obstack_grow (obstackp, "try", 3); look_for_lbrac = 1; @@ -1596,9 +1555,7 @@ reinit_parse_for_block (pyychar, obstackp, is_template) } else { - yyerror (is_template - ? "parse error in template specification" - : "parse error in method specification"); + yyerror ("parse error in method specification"); obstack_1grow (obstackp, '{'); } @@ -1695,9 +1652,7 @@ reinit_parse_for_block (pyychar, obstackp, is_template) { if (look_for_lbrac) { - error (is_template - ? "template body missing" - : "function body for constructor missing"); + error ("function body for constructor missing"); obstack_1grow (obstackp, '{'); obstack_1grow (obstackp, '}'); len += 2; @@ -1726,78 +1681,329 @@ reinit_parse_for_block (pyychar, obstackp, is_template) obstack_1grow (obstackp, '\0'); } -/* Build a default function named NAME for type TYPE. - KIND says what to build. - - When KIND == 0, build default destructor. - When KIND == 1, build virtual destructor. - When KIND == 2, build default constructor. - When KIND == 3, build default X(const X&) constructor. - When KIND == 4, build default X(X&) constructor. - When KIND == 5, build default operator = (const X&). - When KIND == 6, build default operator = (X&). */ +/* Consume a no-commas expression -- actually, a default argument -- and + save it away on the specified obstack. */ -tree -cons_up_default_function (type, full_name, kind) - tree type, full_name; - int kind; +static void +reinit_parse_for_expr (obstackp) + struct obstack *obstackp; { - extern tree void_list_node; - char *func_buf = NULL; - int func_len = 0; - tree declspecs = NULL_TREE; - tree fn, args; - tree argtype; - int retref = 0; - int complex = 0; - tree name = constructor_name (full_name); + register int c = 0; + int starting_lineno = lineno; + char *starting_filename = input_filename; + int len; + int plev = 0; - switch (kind) + if (nextchar != EOF) { - /* Destructors. */ - case 1: - declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]); - /* Fall through... */ - case 0: - name = build_parse_node (BIT_NOT_EXPR, name); - args = void_list_node; - break; - - case 2: - /* Default constructor. */ - args = void_list_node; - complex = TYPE_NEEDS_CONSTRUCTING (type); - break; + c = nextchar; + nextchar = EOF; + } + else + c = getch (); + + while (c != EOF) + { + int this_lineno = lineno; - case 3: - type = build_type_variant (type, 1, 0); - /* Fall through... */ - case 4: - /* According to ARM $12.8, the default copy ctor will be declared, but - not defined, unless it's needed. */ - argtype = build_reference_type (type); - args = tree_cons (NULL_TREE, - build_tree_list (hash_tree_chain (argtype, NULL_TREE), - get_identifier ("_ctor_arg")), - void_list_node); - complex = TYPE_HAS_COMPLEX_INIT_REF (type); - break; + c = skip_white_space (c); - case 5: - type = build_type_variant (type, 1, 0); - /* Fall through... */ - case 6: - retref = 1; - declspecs = build_decl_list (NULL_TREE, full_name); + /* Don't lose our cool if there are lots of comments. */ + if (lineno == this_lineno + 1) + obstack_1grow (obstackp, '\n'); + else if (lineno == this_lineno) + ; + else if (lineno - this_lineno < 10) + { + int i; + for (i = lineno - this_lineno; i > 0; --i) + obstack_1grow (obstackp, '\n'); + } + else + { + char buf[16]; + sprintf (buf, "\n# %d \"", lineno); + len = strlen (buf); + obstack_grow (obstackp, buf, len); - name = ansi_opname [(int) MODIFY_EXPR]; + len = strlen (input_filename); + obstack_grow (obstackp, input_filename, len); + obstack_1grow (obstackp, '\"'); + obstack_1grow (obstackp, '\n'); + } + + while (c > ' ') /* ASCII dependent... */ + { + if (plev <= 0 && (c == ')' || c == ',')) + { + put_back (c); + goto done; + } + obstack_1grow (obstackp, c); + if (c == '(' || c == '[') + ++plev; + else if (c == ']' || c == ')') + --plev; + else if (c == '\\') + { + /* Don't act on the next character...e.g, doing an escaped + double-quote. */ + c = getch (); + if (c == EOF) + { + error_with_file_and_line (starting_filename, + starting_lineno, + "end of file read inside definition"); + goto done; + } + obstack_1grow (obstackp, c); + } + else if (c == '\"') + consume_string (obstackp, c); + else if (c == '\'') + consume_string (obstackp, c); + c = getch (); + } + + if (c == EOF) + { + error_with_file_and_line (starting_filename, + starting_lineno, + "end of file read inside definition"); + goto done; + } + else if (c != '\n') + { + obstack_1grow (obstackp, c); + c = getch (); + } + } + done: + obstack_1grow (obstackp, '\0'); +} + +int do_snarf_defarg; + +/* Decide whether the default argument we are about to see should be + gobbled up as text for later parsing. */ + +void +maybe_snarf_defarg () +{ + if (current_class_type && TYPE_BEING_DEFINED (current_class_type)) + do_snarf_defarg = 1; +} + +/* When we see a default argument in a method declaration, we snarf it as + text using snarf_defarg. When we get up to namespace scope, we then go + through and parse all of them using do_pending_defargs. Since yacc + parsers are not reentrant, we retain defargs state in these two + variables so that subsequent calls to do_pending_defargs can resume + where the previous call left off. */ + +tree defarg_fns; +tree defarg_parm; + +tree +snarf_defarg () +{ + int len; + char *buf; + tree arg; + + reinit_parse_for_expr (&inline_text_obstack); + len = obstack_object_size (&inline_text_obstack); + buf = obstack_finish (&inline_text_obstack); + + push_obstacks (&inline_text_obstack, &inline_text_obstack); + arg = make_node (DEFAULT_ARG); + DEFARG_LENGTH (arg) = len - 1; + DEFARG_POINTER (arg) = buf; + pop_obstacks (); + + return arg; +} + +/* Called from grokfndecl to note a function decl with unparsed default + arguments for later processing. Also called from grokdeclarator + for function types with unparsed defargs; the call from grokfndecl + will always come second, so we can overwrite the entry from the type. */ + +void +add_defarg_fn (decl) + tree decl; +{ + if (TREE_CODE (decl) == FUNCTION_DECL) + TREE_VALUE (defarg_fns) = decl; + else + { + push_obstacks (&inline_text_obstack, &inline_text_obstack); + defarg_fns = tree_cons (current_class_type, decl, defarg_fns); + pop_obstacks (); + } +} + +/* Helper for do_pending_defargs. Starts the parsing of a default arg. */ + +static void +feed_defarg (f, p) + tree f, p; +{ + tree d = TREE_PURPOSE (p); + feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d)); + if (TREE_CODE (f) == FUNCTION_DECL) + { + lineno = DECL_SOURCE_LINE (f); + input_filename = DECL_SOURCE_FILE (f); + } + yychar = DEFARG_MARKER; + yylval.ttype = p; +} + +/* Helper for do_pending_defargs. Ends the parsing of a default arg. */ + +static void +finish_defarg () +{ + if (yychar == YYEMPTY) + yychar = yylex (); + if (yychar != END_OF_SAVED_INPUT) + { + error ("parse error at end of saved function text"); + + /* restore_pending_input will abort unless yychar is either + END_OF_SAVED_INPUT or YYEMPTY; since we already know we're + hosed, feed back YYEMPTY. We also need to discard nextchar, + since that may have gotten set as well. */ + nextchar = -1; + } + yychar = YYEMPTY; + end_input (); +} + +/* Main function for deferred parsing of default arguments. Called from + the parser. */ + +void +do_pending_defargs () +{ + if (defarg_parm) + finish_defarg (); + + for (; defarg_fns; defarg_fns = TREE_CHAIN (defarg_fns)) + { + tree defarg_fn = TREE_VALUE (defarg_fns); + if (defarg_parm == NULL_TREE) + { + push_nested_class (TREE_PURPOSE (defarg_fns), 1); + pushlevel (0); + if (TREE_CODE (defarg_fn) == FUNCTION_DECL) + maybe_begin_member_template_processing (defarg_fn); + + if (TREE_CODE (defarg_fn) == FUNCTION_DECL) + { +#if 0 + tree p; + for (p = DECL_ARGUMENTS (defarg_fn); p; p = TREE_CHAIN (p)) + pushdecl (copy_node (p)); +#endif + defarg_parm = TYPE_ARG_TYPES (TREE_TYPE (defarg_fn)); + } + else + defarg_parm = TYPE_ARG_TYPES (defarg_fn); + } + else + defarg_parm = TREE_CHAIN (defarg_parm); + + for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm)) + if (TREE_PURPOSE (defarg_parm) + && TREE_CODE (TREE_PURPOSE (defarg_parm)) == DEFAULT_ARG) + { + feed_defarg (defarg_fn, defarg_parm); + + /* Return to the parser, which will process this defarg + and call us again. */ + return; + } + + if (TREE_CODE (defarg_fn) == FUNCTION_DECL) + { + maybe_end_member_template_processing (defarg_fn); + check_default_args (defarg_fn); + } + + poplevel (0, 0, 0); + pop_nested_class (1); + } +} + +/* Build a default function named NAME for type TYPE. + KIND says what to build. + + When KIND == 0, build default destructor. + When KIND == 1, build virtual destructor. + When KIND == 2, build default constructor. + When KIND == 3, build default X(const X&) constructor. + When KIND == 4, build default X(X&) constructor. + When KIND == 5, build default operator = (const X&). + When KIND == 6, build default operator = (X&). */ + +tree +cons_up_default_function (type, full_name, kind) + tree type, full_name; + int kind; +{ + extern tree void_list_node; + tree declspecs = NULL_TREE; + tree fn, args = NULL_TREE; + tree argtype; + int retref = 0; + tree name = constructor_name (full_name); + + switch (kind) + { + /* Destructors. */ + case 1: + declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]); + /* Fall through... */ + case 0: + name = build_parse_node (BIT_NOT_EXPR, name); + args = void_list_node; + break; + + case 2: + /* Default constructor. */ + args = void_list_node; + break; + + case 3: + type = build_type_variant (type, 1, 0); + /* Fall through... */ + case 4: + /* According to ARM $12.8, the default copy ctor will be declared, but + not defined, unless it's needed. */ + argtype = build_reference_type (type); + args = tree_cons (NULL_TREE, + build_tree_list (hash_tree_chain (argtype, NULL_TREE), + get_identifier ("_ctor_arg")), + void_list_node); + break; + + case 5: + case 6: + retref = 1; + declspecs = build_decl_list (NULL_TREE, type); + + if (kind == 5) + type = build_type_variant (type, 1, 0); + + name = ansi_opname [(int) MODIFY_EXPR]; argtype = build_reference_type (type); args = tree_cons (NULL_TREE, build_tree_list (hash_tree_chain (argtype, NULL_TREE), get_identifier ("_ctor_arg")), void_list_node); - complex = TYPE_HAS_COMPLEX_ASSIGN_REF (type); break; default: @@ -1810,23 +2016,28 @@ cons_up_default_function (type, full_name, kind) TREE_PARMLIST (args) = 1; { - tree declarator = build_parse_node (CALL_EXPR, name, args, NULL_TREE); + tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE); if (retref) declarator = build_parse_node (ADDR_EXPR, declarator); - - fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, - NULL_TREE, NULL_TREE); + + fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); } if (fn == void_type_node) return fn; + if (kind > 2) + SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn))); + +#if 0 if (processing_template_defn) { SET_DECL_IMPLICIT_INSTANTIATION (fn); repo_template_used (fn); } +#endif +#if 0 if (CLASSTYPE_INTERFACE_KNOWN (type)) { DECL_INTERFACE_KNOWN (fn) = 1; @@ -1834,29 +2045,10 @@ cons_up_default_function (type, full_name, kind) && flag_implement_inlines); } else +#endif DECL_NOT_REALLY_EXTERN (fn) = 1; -#if 0 - /* When on-the-fly synthesis works properly, remove the second and third - conditions here. */ - if (flag_keep_inline_functions -#if 0 - || ! flag_no_inline - || complex -#endif - || ! DECL_EXTERNAL (fn)) - { - struct pending_inline *t; - t = (struct pending_inline *) - obstack_alloc (&synth_obstack, sizeof (struct pending_inline)); - t->lineno = -kind; - t->can_free = 0; - t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); - store_pending_inline (fn, t); - } - else -#endif - mark_inline_for_output (fn); + mark_inline_for_output (fn); #ifdef DEBUG_DEFAULT_FUNCTIONS { char *fn_type = NULL; @@ -1888,6 +2080,7 @@ cons_up_default_function (type, full_name, kind) /* Heuristic to tell whether the user is missing a semicolon after a struct or enum declaration. Emit an error message if we know the user has blown it. */ + void check_for_missing_semicolon (type) tree type; @@ -1898,7 +2091,9 @@ check_for_missing_semicolon (type) if ((yychar > 255 && yychar != SCSPEC && yychar != IDENTIFIER - && yychar != TYPENAME) + && yychar != TYPENAME + && yychar != CV_QUALIFIER + && yychar != SELFNAME) || end_of_file) { if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))) @@ -2020,7 +2215,9 @@ get_last_nonwhite_on_line () int linemode; -int +static int handle_cp_pragma PROTO((char *)); + +static int check_newline () { register int c; @@ -2064,254 +2261,35 @@ check_newline () && getch () == 'm' && getch () == 'a') { - /* Read first nonwhite char after the `#pragma'. */ - - do - c = getch (); - while (c == ' ' || c == '\t'); - - if (c == 'v' - && getch () == 't' - && getch () == 'a' - && getch () == 'b' - && getch () == 'l' - && getch () == 'e' - && ((c = getch ()) == ' ' || c == '\t')) - { - extern tree pending_vtables; - - /* More follows: it must be a string constant (class name). */ - token = real_yylex (); - if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid #pragma vtable"); - goto skipline; - } - if (write_virtuals != 2) - { - warning ("use `+e2' option to enable #pragma vtable"); - goto skipline; - } - pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables); - if (nextchar < 0) - nextchar = getch (); - c = nextchar; - if (c != EOF) - warning ("trailing characters ignored"); - } - else if (c == 'u' - && getch () == 'n' - && getch () == 'i' - && getch () == 't' - && ((c = getch ()) == ' ' || c == '\t')) + token = real_yylex (); + if (token == IDENTIFIER + && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE) { - /* More follows: it must be a string constant (unit name). */ - token = real_yylex (); - if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid #pragma unit"); - goto skipline; - } - current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype)); - current_unit_language = current_lang_name; - if (nextchar < 0) - nextchar = getch (); - c = nextchar; - if (c != EOF) - warning ("trailing characters ignored"); + /* If this is 1, we handled it; if it's -1, it was one we + wanted but had something wrong with it. Only if it's + 0 was it not handled. */ + if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype))) + goto skipline; } - else if (c == 'i') - { - tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename)); - c = getch (); - - if (c == 'n' - && getch () == 't' - && getch () == 'e' - && getch () == 'r' - && getch () == 'f' - && getch () == 'a' - && getch () == 'c' - && getch () == 'e' - && ((c = getch ()) == ' ' || c == '\t' || c == EOF)) - { - int warned_already = 0; - char *main_filename = input_filename; - - main_filename = FILE_NAME_NONDIRECTORY (main_filename); - while (c == ' ' || c == '\t') - c = getch (); - if (c != EOF) - { - put_back (c); - token = real_yylex (); - if (token != STRING - || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid `#pragma interface'"); - goto skipline; - } - main_filename = TREE_STRING_POINTER (yylval.ttype); - c = getch(); - put_back (c); - } - - while (c == ' ' || c == '\t') - c = getch (); - - while (c != EOF) - { - if (!warned_already && extra_warnings - && c != ' ' && c != '\t') - { - warning ("garbage after `#pragma interface' ignored"); - warned_already = 1; - } - c = getch (); - } - - write_virtuals = 3; - - if (impl_file_chain == 0) - { - /* If this is zero at this point, then we are - auto-implementing. */ - if (main_input_filename == 0) - main_input_filename = input_filename; - -#ifdef AUTO_IMPLEMENT - filename = FILE_NAME_NONDIRECTORY (main_input_filename); - fi = get_time_identifier (filename); - fi = IDENTIFIER_CLASS_VALUE (fi); - TREE_INT_CST_LOW (fi) = 0; - TREE_INT_CST_HIGH (fi) = 1; - /* Get default. */ - impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files)); - impl_file_chain->filename = filename; - impl_file_chain->next = 0; -#endif - } - - interface_only = interface_strcmp (main_filename); - interface_unknown = 0; - TREE_INT_CST_LOW (fileinfo) = interface_only; - TREE_INT_CST_HIGH (fileinfo) = interface_unknown; - } - else if (c == 'm' - && getch () == 'p' - && getch () == 'l' - && getch () == 'e' - && getch () == 'm' - && getch () == 'e' - && getch () == 'n' - && getch () == 't' - && getch () == 'a' - && getch () == 't' - && getch () == 'i' - && getch () == 'o' - && getch () == 'n' - && ((c = getch ()) == ' ' || c == '\t' || c == EOF)) - { - int warned_already = 0; - char *main_filename = main_input_filename ? main_input_filename : input_filename; - - main_filename = FILE_NAME_NONDIRECTORY (main_filename); - while (c == ' ' || c == '\t') - c = getch (); - if (c != EOF) - { - put_back (c); - token = real_yylex (); - if (token != STRING - || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid `#pragma implementation'"); - goto skipline; - } - main_filename = TREE_STRING_POINTER (yylval.ttype); - c = getch(); - put_back (c); - } - - while (c == ' ' || c == '\t') - c = getch (); - - while (c != EOF) - { - if (!warned_already && extra_warnings - && c != ' ' && c != '\t') - { - warning ("garbage after `#pragma implementation' ignored"); - warned_already = 1; - } - c = getch (); - } + else if (token == END_OF_LINE) + goto skipline; - if (write_virtuals == 3) - { - struct impl_files *ifiles = impl_file_chain; - while (ifiles) - { - if (! strcmp (ifiles->filename, main_filename)) - break; - ifiles = ifiles->next; - } - if (ifiles == 0) - { - ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files)); - ifiles->filename = main_filename; - ifiles->next = impl_file_chain; - impl_file_chain = ifiles; - } - } - else if ((main_input_filename != 0 - && ! strcmp (main_input_filename, input_filename)) - || ! strcmp (input_filename, main_filename)) - { - write_virtuals = 3; - if (impl_file_chain == 0) - { - impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files)); - impl_file_chain->filename = main_filename; - impl_file_chain->next = 0; - } - } - else - error ("`#pragma implementation' can only appear at top-level"); - interface_only = 0; -#if 1 - /* We make this non-zero so that we infer decl linkage - in the impl file only for variables first declared - in the interface file. */ - interface_unknown = 1; -#else - /* We make this zero so that templates in the impl - file will be emitted properly. */ - interface_unknown = 0; -#endif - TREE_INT_CST_LOW (fileinfo) = interface_only; - TREE_INT_CST_HIGH (fileinfo) = interface_unknown; - } - } #ifdef HANDLE_SYSV_PRAGMA - else - { - put_back (c); - handle_sysv_pragma (); - } + if (handle_sysv_pragma (token)) + goto skipline; #else #ifdef HANDLE_PRAGMA - /* FIXME: This will break if we're doing any of the C++ input - tricks. */ - else - { - ungetc (c, finput); - HANDLE_PRAGMA (finput); - } +#if USE_CPPLIB + /* TODO: ??? */ + goto skipline; +#else + if (HANDLE_PRAGMA (finput, yylval.ttype)) + goto skipline; +#endif /* !USE_CPPLIB */ #endif #endif - goto skipline; } + goto skipline; } else if (c == 'd') { @@ -2322,11 +2300,7 @@ check_newline () && getch () == 'e' && ((c = getch ()) == ' ' || c == '\t')) { -#ifdef DWARF_DEBUGGING_INFO - if ((debug_info_level == DINFO_LEVEL_VERBOSE) - && (write_symbols == DWARF_DEBUG)) - dwarfout_define (lineno, get_directive_line (finput)); -#endif /* DWARF_DEBUGGING_INFO */ + debug_define (lineno, GET_DIRECTIVE_LINE ()); goto skipline; } } @@ -2338,11 +2312,7 @@ check_newline () && getch () == 'f' && ((c = getch ()) == ' ' || c == '\t')) { -#ifdef DWARF_DEBUGGING_INFO - if ((debug_info_level == DINFO_LEVEL_VERBOSE) - && (write_symbols == DWARF_DEBUG)) - dwarfout_undef (lineno, get_directive_line (finput)); -#endif /* DWARF_DEBUGGING_INFO */ + debug_undef (lineno, GET_DIRECTIVE_LINE ()); goto skipline; } } @@ -2362,23 +2332,14 @@ check_newline () && getch () == 't' && ((c = getch ()) == ' ' || c == '\t')) { -#ifdef ASM_OUTPUT_IDENT - extern FILE *asm_out_file; -#endif /* #ident. The pedantic warning is now in cccp.c. */ /* Here we have just seen `#ident '. A string constant should follow. */ - while (c == ' ' || c == '\t') - c = getch (); - - /* If no argument, ignore the line. */ - if (c == EOF) - goto skipline; - - put_back (c); token = real_yylex (); + if (token == END_OF_LINE) + goto skipline; if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) { @@ -2483,9 +2444,6 @@ linenum: body_time = this_time; } - if (flag_cadillac) - cadillac_note_source (); - input_filename = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1); strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype)); @@ -2500,7 +2458,7 @@ linenum: { while (ifiles->next) ifiles = ifiles->next; - ifiles->filename = FILE_NAME_NONDIRECTORY (input_filename); + ifiles->filename = file_name_nondirectory (input_filename); } main_input_filename = input_filename; @@ -2590,13 +2548,7 @@ linenum: p->name = input_filename; input_file_stack = p; input_file_stack_tick++; -#ifdef DWARF_DEBUGGING_INFO - if (debug_info_level == DINFO_LEVEL_VERBOSE - && write_symbols == DWARF_DEBUG) - dwarfout_start_new_source_file (input_filename); -#endif /* DWARF_DEBUGGING_INFO */ - if (flag_cadillac) - cadillac_push_source (); + debug_start_source_file (input_filename); in_system_header = entering_system_header; if (c_header_level) ++c_header_level; @@ -2619,29 +2571,19 @@ linenum: warning ("badly nested C headers from preprocessor"); --pending_lang_change; } - if (flag_cadillac) - cadillac_pop_source (); in_system_header = entering_system_header; p = input_file_stack; input_file_stack = p->next; free (p); input_file_stack_tick++; -#ifdef DWARF_DEBUGGING_INFO - if (debug_info_level == DINFO_LEVEL_VERBOSE - && write_symbols == DWARF_DEBUG) - dwarfout_resume_previous_source_file (input_file_stack->line); -#endif /* DWARF_DEBUGGING_INFO */ + debug_end_source_file (input_file_stack->line); } else error ("#-lines for entering and leaving files don't match"); } else - { - in_system_header = entering_system_header; - if (flag_cadillac) - cadillac_switch_source (-1); - } + in_system_header = entering_system_header; } /* If NEXTCHAR is not end of line, we don't care what it is. */ @@ -2655,6 +2597,7 @@ linenum: skipline: linemode = 0; end_of_file = 0; + nextchar = -1; while ((c = getch ()) != EOF && c != '\n'); return c; } @@ -2668,13 +2611,6 @@ do_pending_lang_change () pop_lang_context (); } -#if 0 -#define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0) -#define isdigit(char) (char >= '0' && char <= '9') -#else -#include -#endif - #define ENDFILE -1 /* token that represents end-of-file */ /* Read an escape sequence, returning its equivalent as a character, @@ -2687,25 +2623,19 @@ readescape (ignore_ptr) register int c = getch (); register int code; register unsigned count; - unsigned firstdig; + unsigned firstdig = 0; int nonnull; switch (c) { case 'x': - if (warn_traditional) - warning ("the meaning of `\\x' varies with -traditional"); - - if (flag_traditional) - return c; - code = 0; count = 0; nonnull = 0; while (1) { c = getch (); - if (! isxdigit (c)) + if (! ISXDIGIT (c)) { put_back (c); break; @@ -2773,11 +2703,6 @@ readescape (ignore_ptr) return TARGET_BS; case 'a': - if (warn_traditional) - warning ("the meaning of `\\a' varies with -traditional"); - - if (flag_traditional) - return c; return TARGET_BELL; case 'v': @@ -2812,46 +2737,47 @@ readescape (ignore_ptr) /* Value is 1 (or 2) if we should try to make the next identifier look like a typename (when it may be a local variable or a class variable). Value is 0 if we treat this name in a default fashion. */ -int looking_for_typename = 0; - -#if 0 -/* NO LONGER USED: Value is -1 if we must not see a type name. */ -void -dont_see_typename () -{ - looking_for_typename = -1; - if (yychar == TYPENAME || yychar == PTYPENAME) - { - yychar = IDENTIFIER; - lastiddecl = 0; - } -} -#endif +int looking_for_typename; #ifdef __GNUC__ -extern __inline int identifier_type (); __inline #endif int identifier_type (decl) tree decl; { - if (TREE_CODE (decl) == TEMPLATE_DECL - && DECL_TEMPLATE_IS_CLASS (decl)) - return PTYPENAME; + if (TREE_CODE (decl) == TEMPLATE_DECL) + { + if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL) + return PTYPENAME; + else if (looking_for_template) + return PFUNCNAME; + } + if (looking_for_template && really_overloaded_fn (decl)) + { + tree t; + for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t)) + if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t))) + return PFUNCNAME; + } if (TREE_CODE (decl) == NAMESPACE_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)) + return SELFNAME; return TYPENAME; } void see_typename () { - looking_for_typename = 1; + /* Only types expected, not even namespaces. */ + looking_for_typename = 2; if (yychar < 0) - if ((yychar = yylex()) < 0) yychar = 0; + if ((yychar = yylex ()) < 0) yychar = 0; looking_for_typename = 0; if (yychar == IDENTIFIER) { @@ -2866,20 +2792,44 @@ see_typename () } } +/* Return true if d is in a global scope. */ + +static int +is_global (d) + tree d; +{ + while (1) + switch (TREE_CODE (d)) + { + case OVERLOAD: d = OVL_FUNCTION (d); continue; + case TREE_LIST: d = TREE_VALUE (d); continue; + default: + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (d)) == 'd', 980629); + d = CP_DECL_CONTEXT (d); + return TREE_CODE (d) == NAMESPACE_DECL; + } +} + tree -do_identifier (token) +do_identifier (token, parsing, args) register tree token; + int parsing; + tree args; { - register tree id = lastiddecl; + register tree id; + int lexing = (parsing == 1); + int in_call = (parsing == 2); + + if (! lexing || IDENTIFIER_OPNAME_P (token)) + id = lookup_name (token, 0); + else + id = lastiddecl; - if (yychar == YYEMPTY) - yychar = yylex (); /* Scope class declarations before global declarations. */ - if (id == IDENTIFIER_GLOBAL_VALUE (token) + if ((!id || is_global (id)) && current_class_type != 0 - && TYPE_SIZE (current_class_type) == 0 - && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE) + && TYPE_SIZE (current_class_type) == 0) { /* Could be from one of the base classes. */ tree field = lookup_field (current_class_type, token, 1, 0); @@ -2890,7 +2840,8 @@ do_identifier (token) But we still want to return this value. */ id = lookup_field (current_class_type, token, 0, 0); else if (TREE_CODE (field) == VAR_DECL - || TREE_CODE (field) == CONST_DECL) + || TREE_CODE (field) == CONST_DECL + || TREE_CODE (field) == TEMPLATE_DECL) id = field; else if (TREE_CODE (field) != FIELD_DECL) my_friendly_abort (61); @@ -2903,11 +2854,25 @@ do_identifier (token) } } + /* 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); + } + /* Remember that this name has been used in the class definition, as per [class.scope0] */ - if (id && current_class_type + if (id && current_class_type && parsing && TYPE_BEING_DEFINED (current_class_type) - && ! IDENTIFIER_CLASS_VALUE (token)) + && ! IDENTIFIER_CLASS_VALUE (token) + /* 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) @@ -2920,7 +2885,16 @@ do_identifier (token) if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node) return id; } - if (yychar == '(' || yychar == LEFT_RIGHT) + + if (current_template_parms) + return build_min_nt (LOOKUP_EXPR, token, NULL_TREE); + 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) { id = implicitly_declare (token); } @@ -2931,7 +2905,7 @@ do_identifier (token) } else { - if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node + if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl) { static int undeclared_variable_notice; @@ -2947,7 +2921,7 @@ do_identifier (token) } id = error_mark_node; /* Prevent repeated error messages. */ - IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node; + SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node); SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl); } } @@ -2955,6 +2929,11 @@ do_identifier (token) if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id)) { tree shadowed = DECL_SHADOWED_FOR_VAR (id); + while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL + && DECL_DEAD_FOR_LOCAL (shadowed)) + shadowed = DECL_SHADOWED_FOR_VAR (shadowed); + if (!shadowed) + shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (id)); if (shadowed) { if (!DECL_ERROR_REPORTED (id)) @@ -2992,20 +2971,109 @@ do_identifier (token) if (IDENTIFIER_CLASS_VALUE (token) == id) { /* Check access. */ - enum access_type access - = compute_access (TYPE_BINFO (current_class_type), id); - if (access == access_private) + 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'. */ } - id = DECL_INITIAL (id); + if (! processing_template_decl + || (DECL_INITIAL (id) + && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX)) + id = DECL_INITIAL (id); } else - id = hack_identifier (id, token, yychar); + 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 */ + } + return id; } tree +do_scoped_id (token, parsing) + tree token; + int parsing; +{ + tree id; + /* during parsing, this is ::name. Otherwise, it is black magic. */ + if (parsing) + { + struct tree_binding _b; + id = binding_init (&_b); + if (!qualified_lookup_using_namespace (token, global_namespace, id, 0)) + id = NULL_TREE; + else + id = BINDING_VALUE (id); + } + else + id = IDENTIFIER_GLOBAL_VALUE (token); + if (parsing && yychar == YYEMPTY) + yychar = yylex (); + if (! id) + { + if (processing_template_decl) + { + id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE); + LOOKUP_EXPR_GLOBAL (id) = 1; + return id; + } + if (parsing && (yychar == '(' || yychar == LEFT_RIGHT)) + id = implicitly_declare (token); + else + { + if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node) + error ("undeclared variable `%s' (first use here)", + IDENTIFIER_POINTER (token)); + id = error_mark_node; + /* Prevent repeated error messages. */ + SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node); + } + } + else + { + if (TREE_CODE (id) == ADDR_EXPR) + mark_used (TREE_OPERAND (id, 0)); + else if (TREE_CODE (id) != OVERLOAD) + mark_used (id); + } + if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl) + { + /* XXX CHS - should we set TREE_USED of the constant? */ + id = DECL_INITIAL (id); + /* This is to prevent an enum whose value is 0 + from being considered a null pointer constant. */ + id = build1 (NOP_EXPR, TREE_TYPE (id), id); + TREE_CONSTANT (id) = 1; + } + + if (processing_template_decl) + { + if (is_overloaded_fn (id)) + { + id = build_min (LOOKUP_EXPR, unknown_type_node, + token, get_first_fn (id)); + LOOKUP_EXPR_GLOBAL (id) = 1; + } + /* else just use the decl */ + } + return convert_from_reference (id); +} + +tree identifier_typedecl_value (node) tree node; { @@ -3021,34 +3089,16 @@ identifier_typedecl_value (node) } do (IDENTIFIER_LOCAL_VALUE (node)); do (IDENTIFIER_CLASS_VALUE (node)); - do (IDENTIFIER_GLOBAL_VALUE (node)); + do (IDENTIFIER_NAMESPACE_VALUE (node)); #undef do /* Will this one ever happen? */ - if (TYPE_NAME (type)) - return TYPE_NAME (type); + if (TYPE_MAIN_DECL (type)) + return TYPE_MAIN_DECL (type); /* We used to do an internal error of 62 here, but instead we will - handle the return of a null appropriately in the callers. */ - return NULL_TREE; -} - -struct try_type -{ - tree *node_var; - char unsigned_flag; - char long_flag; - char long_long_flag; -}; - -struct try_type type_sequence[] = -{ - { &integer_type_node, 0, 0, 0}, - { &unsigned_type_node, 1, 0, 0}, - { &long_integer_type_node, 0, 1, 0}, - { &long_unsigned_type_node, 1, 1, 0}, - { &long_long_integer_type_node, 0, 1, 1}, - { &long_long_unsigned_type_node, 1, 1, 1} -}; + handle the return of a null appropriately in the callers. */ + return NULL_TREE; +} int real_yylex () @@ -3103,21 +3153,17 @@ real_yylex () value = END_OF_SAVED_INPUT; else if (linemode) value = END_OF_LINE; - else if (do_pending_expansions ()) - /* this will set yychar for us */ - return yychar; else value = ENDFILE; break; case '$': - if (dollars_in_ident) - { - dollar_seen = 1; - goto letter; - } - value = '$'; - goto done; + if (! dollars_in_ident) + error ("`$' in identifier"); + else if (pedantic) + pedwarn ("`$' in identifier"); + dollar_seen = 1; + goto letter; case 'L': /* Capital L may start a wide-string or wide-character constant. */ @@ -3166,15 +3212,21 @@ real_yylex () /* Make this run fast. We know that we are reading straight from FINPUT in this case (since identifiers cannot straddle input sources. */ - while (isalnum (c) || (c == '_') || c == '$') + while (ISALNUM (c) || (c == '_') || c == '$') { - if (c == '$' && ! dollars_in_ident) - break; + if (c == '$') + { + if (! dollars_in_ident) + error ("`$' in identifier"); + else if (pedantic) + pedwarn ("`$' in identifier"); + } + if (p >= token_buffer + maxtoken) p = extend_token_buffer (p); *p++ = c; - c = getc (finput); + c = getch (); } if (linemode && c == '\n') @@ -3190,10 +3242,16 @@ real_yylex () *p++ = c; c = getch (); - while (isalnum (c) || (c == '_') || c == '$') + while (ISALNUM (c) || (c == '_') || c == '$') { - if (c == '$' && ! dollars_in_ident) - break; + if (c == '$') + { + if (! dollars_in_ident) + error ("`$' in identifier"); + else if (pedantic) + pedwarn ("`$' in identifier"); + } + if (p >= token_buffer + maxtoken) p = extend_token_buffer (p); @@ -3213,7 +3271,7 @@ real_yylex () { register struct resword *ptr; - if (ptr = is_reserved_word (token_buffer, p - token_buffer)) + if ((ptr = is_reserved_word (token_buffer, p - token_buffer))) { if (ptr->rid) { @@ -3226,7 +3284,7 @@ real_yylex () && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL) looking_for_typename = 0; else if (ptr->token == AGGR || ptr->token == ENUM) - looking_for_typename = 1; + looking_for_typename = 2; /* Check if this is a language-type declaration. Just glimpse the next non-white character. */ @@ -3253,13 +3311,13 @@ real_yylex () switch (ptr->rid) { case RID_PUBLIC: - yylval.itype = access_public; + yylval.ttype = access_public_node; break; case RID_PRIVATE: - yylval.itype = access_private; + yylval.ttype = access_private_node; break; case RID_PROTECTED: - yylval.itype = access_protected; + yylval.ttype = access_protected_node; break; default: my_friendly_abort (63); @@ -3313,14 +3371,6 @@ real_yylex () token_buffer[0] = '^'; token_buffer[1] = 0; } - else if (ptr->token == NAMESPACE) - { - static int warned; - if (! warned) - warning ("namespaces are mostly broken in this version of g++"); - - warned = 1; - } value = (int) ptr->token; } @@ -3329,18 +3379,6 @@ real_yylex () /* If we did not find a keyword, look for an identifier (or a typename). */ - if (strcmp ("catch", token_buffer) == 0 - || strcmp ("throw", token_buffer) == 0 - || strcmp ("try", token_buffer) == 0) - { - static int did_warn = 0; - if (! did_warn && ! flag_handle_exceptions) - { - pedwarn ("`catch', `throw', and `try' are all C++ reserved words"); - did_warn = 1; - } - } - if (value == IDENTIFIER || value == TYPESPEC) GNU_xref_ref (current_function_decl, token_buffer); @@ -3365,30 +3403,6 @@ real_yylex () #endif yylval.ttype = tmp; - - /* A user-invisible read-only initialized variable - should be replaced by its value. We only handle strings - since that's the only case used in C (and C++). */ - /* Note we go right after the local value for the identifier - (e.g., __FUNCTION__ or __PRETTY_FUNCTION__). We used to - call lookup_name, but that could result in an error about - ambiguities. */ - tmp = IDENTIFIER_LOCAL_VALUE (yylval.ttype); - if (tmp != NULL_TREE - && TREE_CODE (tmp) == VAR_DECL - && DECL_IGNORED_P (tmp) - && TREE_READONLY (tmp) - && DECL_INITIAL (tmp) != NULL_TREE - && TREE_CODE (DECL_INITIAL (tmp)) == STRING_CST) - { - tree stringval = DECL_INITIAL (tmp); - - /* 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), - TREE_STRING_POINTER (stringval)); - value = STRING; - } } if (value == NEW && ! global_bindings_p ()) { @@ -3421,7 +3435,7 @@ real_yylex () } error ("parse error at `..'"); } - if (isdigit (c1)) + if (ISDIGIT (c1)) { put_back (c1); goto resume_numerical_scan; @@ -3435,7 +3449,7 @@ real_yylex () /* Optimize for most frequent case. */ { register int c1 = getch (); - if (! isalnum (c1) && c1 != '.') + if (! ISALNUM (c1) && c1 != '.') { /* Terminate string. */ token_buffer[0] = c; @@ -3450,7 +3464,7 @@ real_yylex () } put_back (c1); } - /* fall through... */ + /* fall through... */ case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': resume_numerical_scan: @@ -3473,12 +3487,12 @@ real_yylex () enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag = NOT_FLOAT; - p = token_buffer; - *p++ = c; - for (count = 0; count < TOTAL_PARTS; count++) parts[count] = 0; + p = token_buffer; + *p++ = c; + if (c == '0') { *p++ = (c = getch ()); @@ -3500,18 +3514,25 @@ real_yylex () /* Read all the digits-and-decimal-points. */ while (c == '.' - || (isalnum (c) && (c != 'l') && (c != 'L') + || (ISALNUM (c) && (c != 'l') && (c != 'L') && (c != 'u') && (c != 'U') + && c != 'i' && c != 'I' && c != 'j' && c != 'J' && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F'))))) { if (c == '.') { if (base == 16) error ("floating constant may not be in radix 16"); - if (floatflag == AFTER_POINT) + if (floatflag == TOO_MANY_POINTS) + /* We have already emitted an error. Don't need another. */ + ; + else if (floatflag == AFTER_POINT) { error ("malformed floating constant"); floatflag = TOO_MANY_POINTS; + /* Avoid another error from atof by forcing all characters + from here on to be ignored. */ + p[-1] = '\0'; } else floatflag = AFTER_POINT; @@ -3522,7 +3543,7 @@ real_yylex () only when it is followed by a digit. Otherwise, unread the following non-digit and use the '.' as a structural token. */ - if (p == token_buffer + 2 && !isdigit (c)) + if (p == token_buffer + 2 && !ISDIGIT (c)) { if (c == '.') { @@ -3547,7 +3568,7 @@ real_yylex () /* It is not a decimal point. It should be a digit (perhaps a hex digit). */ - if (isdigit (c)) + if (ISDIGIT (c)) { c = c - '0'; } @@ -3611,9 +3632,8 @@ real_yylex () if (floatflag != NOT_FLOAT) { tree type = double_type_node; - char f_seen = 0; - char l_seen = 0; - int garbage_chars = 0; + int exceeds_double = 0; + int imag = 0; REAL_VALUE_TYPE value; jmp_buf handler; @@ -3630,9 +3650,9 @@ real_yylex () *p++ = c; c = getch (); } - if (! isdigit (c)) + 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); @@ -3652,76 +3672,117 @@ real_yylex () } 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); - /* The second argument, machine_mode, of REAL_VALUE_ATOF - tells the desired precision of the binary result of - decimal-to-binary conversion. */ - /* Read the suffixes to choose a data type. */ - switch (c) + while (1) { - case 'f': case 'F': - type = float_type_node; - value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type)); - garbage_chars = -1; - break; + int lose = 0; - case 'l': case 'L': - type = long_double_type_node; - value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type)); - garbage_chars = -1; - break; + /* 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. */ - default: - value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type)); + 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); } - if (pedantic - && (REAL_VALUE_ISINF (value) #ifdef ERANGE - || (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT - && errno == ERANGE - /* ERANGE is also reported for underflow, so test the - value to distinguish overflow from that. */ - && (REAL_VALUES_LESS (dconst1, value) - || REAL_VALUES_LESS (value, dconstm1))) -#endif - )) - { - pedwarn ("floating point number exceeds range of `%s'", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); - } - /* Note: garbage_chars is -1 if first char is *not* garbage. */ - while (isalnum (c)) + if (errno == ERANGE && pedantic) { - if (c == 'f' || c == 'F') - { - if (f_seen) - error ("two `f's in floating constant"); - f_seen = 1; - } - if (c == 'l' || c == 'L') + /* ERANGE is also reported for underflow, + so test the value to distinguish overflow from that. */ + if (REAL_VALUES_LESS (dconst1, value) + || REAL_VALUES_LESS (value, dconstm1)) { - if (l_seen) - error ("two `l's in floating constant"); - l_seen = 1; + pedwarn ("floating point number exceeds range of `%s'", + IDENTIFIER_POINTER (TYPE_IDENTIFIER (type))); + exceeds_double = 1; } - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getch (); - garbage_chars++; } +#endif - if (garbage_chars > 0) - error ("garbage at end of number"); + /* If the result is not a number, assume it must have been + due to some error message above, so silently convert + it to a zero. */ + if (REAL_VALUE_ISNAN (value)) + value = dconst0; /* Create a node with determined type and value. */ - yylval.ttype = build_real (type, value); - - put_back (c); - *p = 0; + if (imag) + yylval.ttype = build_complex (NULL_TREE, + cp_convert (type, integer_zero_node), + build_real (type, value)); + else + yylval.ttype = build_real (type, value); } else { @@ -3730,6 +3791,7 @@ real_yylex () int spec_unsigned = 0; int spec_long = 0; int spec_long_long = 0; + int spec_imag = 0; int bytes, warn; while (1) @@ -3752,29 +3814,22 @@ real_yylex () } spec_long = 1; } - else + else if (c == 'i' || c == 'j' || c == 'I' || c == 'J') { - if (isalnum (c)) - { - error ("garbage at end of number"); - while (isalnum (c)) - { - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getch (); - } - } - break; + if (spec_imag) + error ("more than one `i' or `j' in numeric constant"); + else if (pedantic) + pedwarn ("ANSI C++ forbids imaginary numeric constants"); + spec_imag = 1; } + else + break; if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getch (); } - put_back (c); - /* If the constant is not long long and it won't fit in an unsigned long, or if the constant is long long and won't fit in an unsigned long long, then warn that the constant is out @@ -3813,145 +3868,52 @@ real_yylex () yylval.ttype = build_int_2 (low, high); TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node; -#if 0 - /* Find the first allowable type that the value fits in. */ - type = 0; - for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]); - i++) - if (!(spec_long && !type_sequence[i].long_flag) - && !(spec_long_long && !type_sequence[i].long_long_flag) - && !(spec_unsigned && !type_sequence[i].unsigned_flag) - /* A hex or octal constant traditionally is unsigned. */ - && !(base != 10 && flag_traditional - && !type_sequence[i].unsigned_flag) - /* A decimal constant can't be unsigned int - unless explicitly specified. */ - && !(base == 10 && !spec_unsigned - && *type_sequence[i].node_var == unsigned_type_node)) - if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var)) - { - type = *type_sequence[i].node_var; - break; - } - if (flag_traditional && type == long_unsigned_type_node - && !spec_unsigned) - type = long_integer_type_node; - - if (type == 0) - { - type = long_long_integer_type_node; - warning ("integer constant out of range"); - } - - /* Warn about some cases where the type of a given constant - changes from traditional C to ANSI C. */ - if (warn_traditional) - { - tree other_type = 0; - - /* This computation is the same as the previous one - except that flag_traditional is used backwards. */ - for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]); - i++) - if (!(spec_long && !type_sequence[i].long_flag) - && !(spec_long_long && !type_sequence[i].long_long_flag) - && !(spec_unsigned && !type_sequence[i].unsigned_flag) - /* A hex or octal constant traditionally is unsigned. */ - && !(base != 10 && !flag_traditional - && !type_sequence[i].unsigned_flag) - /* A decimal constant can't be unsigned int - unless explicitly specified. */ - && !(base == 10 && !spec_unsigned - && *type_sequence[i].node_var == unsigned_type_node)) - if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var)) - { - other_type = *type_sequence[i].node_var; - break; - } - if (!flag_traditional && type == long_unsigned_type_node - && !spec_unsigned) - type = long_integer_type_node; - - if (other_type != 0 && other_type != type) - { - if (flag_traditional) - warning ("type of integer constant would be different without -traditional"); - else - warning ("type of integer constant would be different with -traditional"); - } - } - -#else /* 1 */ + /* Calculate the ANSI type. */ if (!spec_long && !spec_unsigned - && !(flag_traditional && base != 10) && int_fits_type_p (yylval.ttype, integer_type_node)) - { -#if 0 - if (warn_traditional && base != 10) - warning ("small nondecimal constant becomes signed in ANSI C++"); -#endif - type = integer_type_node; - } + type = integer_type_node; else if (!spec_long && (base != 10 || spec_unsigned) && int_fits_type_p (yylval.ttype, unsigned_type_node)) - { - /* Nondecimal constants try unsigned even in traditional C. */ - type = unsigned_type_node; - } - + /* Nondecimal constants try unsigned even in traditional C. */ + type = unsigned_type_node; else if (!spec_unsigned && !spec_long_long && int_fits_type_p (yylval.ttype, long_integer_type_node)) type = long_integer_type_node; - - else if (! spec_long_long - && int_fits_type_p (yylval.ttype, - long_unsigned_type_node)) - { -#if 0 - if (warn_traditional && !spec_unsigned) - warning ("large integer constant becomes unsigned in ANSI C++"); -#endif - if (flag_traditional && !spec_unsigned) - type = long_integer_type_node; - else - type = long_unsigned_type_node; - } - + else if (! spec_long_long) + type = long_unsigned_type_node; else if (! spec_unsigned /* Verify value does not overflow into sign bit. */ && TREE_INT_CST_HIGH (yylval.ttype) >= 0 && int_fits_type_p (yylval.ttype, long_long_integer_type_node)) type = long_long_integer_type_node; + else + type = long_long_unsigned_type_node; - else if (int_fits_type_p (yylval.ttype, - long_long_unsigned_type_node)) - { -#if 0 - if (warn_traditional && !spec_unsigned) - warning ("large nondecimal constant is unsigned in ANSI C++"); -#endif + if (!int_fits_type_p (yylval.ttype, type) && !warn) + pedwarn ("integer constant out of range"); - if (flag_traditional && !spec_unsigned) - type = long_long_integer_type_node; - else - type = long_long_unsigned_type_node; - } + if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) + warning ("decimal integer constant is so large that it is unsigned"); - else + if (spec_imag) { - type = long_long_integer_type_node; - warning ("integer constant out of range"); - - if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) - warning ("decimal integer constant is so large that it is unsigned"); + if (TYPE_PRECISION (type) + <= TYPE_PRECISION (integer_type_node)) + yylval.ttype + = build_complex (NULL_TREE, integer_zero_node, + cp_convert (integer_type_node, + yylval.ttype)); + else + error ("complex integer constant is too wide for `__complex int'"); } -#endif - - TREE_TYPE (yylval.ttype) = type; - *p = 0; + else + TREE_TYPE (yylval.ttype) = type; } + put_back (c); + *p = 0; + value = CONSTANT; break; } @@ -3994,7 +3956,7 @@ real_yylex () && (unsigned) c >= (1 << width)) warning ("escape sequence out of range for character"); #ifdef MAP_CHARACTER - if (isprint (c)) + if (ISPRINT (c)) c = MAP_CHARACTER (c); #endif } @@ -4037,7 +3999,7 @@ real_yylex () num_chars = max_chars; error ("character constant too long"); } - else if (num_chars != 1 && ! flag_traditional) + else if (num_chars != 1 && warn_multichar) warning ("multi-character character constant"); /* If char type is signed, sign-extend the constant. */ @@ -4125,7 +4087,7 @@ real_yylex () skipnewline: c = getch (); if (c == EOF) { - error("Unterminated string"); + error ("Unterminated string"); break; } } @@ -4151,27 +4113,29 @@ real_yylex () bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES); #else { - union { long l; char c[sizeof (long)]; } u; - int big_endian; char *wp, *cp; - /* Determine whether host is little or big endian. */ - u.l = 1; - big_endian = u.c[sizeof (long) - 1]; - wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0); - + 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; } 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; } @@ -4373,21 +4337,49 @@ real_yylex () done: /* yylloc.last_line = lineno; */ #ifdef GATHER_STATISTICS +#ifdef REDUCE_LENGTH token_count[value] += 1; #endif +#endif return value; } +int +is_rid (t) + tree t; +{ + return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); +} + +#ifdef GATHER_STATISTICS +/* The original for tree_node_kind is in the toplevel tree.c; changes there + need to be brought into here, unless this were actually put into a header + instead. */ +/* Statistics-gathering stuff. */ typedef enum { - d_kind, t_kind, s_kind, r_kind, e_kind, c_kind, - id_kind, op_id_kind, perm_list_kind, temp_list_kind, - vec_kind, x_kind, lang_decl, lang_type, all_kinds + d_kind, + t_kind, + b_kind, + s_kind, + r_kind, + e_kind, + c_kind, + id_kind, + op_id_kind, + perm_list_kind, + temp_list_kind, + vec_kind, + x_kind, + lang_decl, + lang_type, + all_kinds } tree_node_kind; + extern int tree_node_counts[]; extern int tree_node_sizes[]; -extern char *tree_node_kind_names[]; +#endif /* Place to save freed lang_decls which were allocated on the permanent_obstack. @@ Not currently used. */ @@ -4428,24 +4420,11 @@ build_lang_decl (code, name, type) == TREE_PERMANENT (t), 234); DECL_MAIN_VARIANT (t) = t; if (current_lang_name == lang_name_cplusplus) - { - DECL_LANGUAGE (t) = lang_cplusplus; -#if 0 -#ifndef NO_AUTO_OVERLOAD - if (code == FUNCTION_DECL && name != 0 - && ! (IDENTIFIER_LENGTH (name) == 4 - && IDENTIFIER_POINTER (name)[0] == 'm' - && strcmp (IDENTIFIER_POINTER (name), "main") == 0) - && ! (IDENTIFIER_LENGTH (name) > 10 - && IDENTIFIER_POINTER (name)[0] == '_' - && IDENTIFIER_POINTER (name)[1] == '_' - && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0)) - TREE_OVERLOADED (name) = 1; -#endif -#endif - } + DECL_LANGUAGE (t) = lang_cplusplus; else if (current_lang_name == lang_name_c) DECL_LANGUAGE (t) = lang_c; + else if (current_lang_name == lang_name_java) + DECL_LANGUAGE (t) = lang_java; else my_friendly_abort (64); #if 0 /* not yet, should get fixed properly later */ @@ -4459,7 +4438,7 @@ build_lang_decl (code, name, type) #endif #ifdef GATHER_STATISTICS tree_node_counts[(int)lang_decl] += 1; - tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl); + tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl); #endif return t; @@ -4506,6 +4485,9 @@ copy_lang_decl (node) int size; int *pi; + if (! DECL_LANG_SPECIFIC (node)) + return; + if (TREE_CODE (node) == FIELD_DECL) size = sizeof (struct lang_decl_flags); else @@ -4538,10 +4520,9 @@ make_lang_type (code) pi[--i] = 0; TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi; - CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t); + CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t); SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); CLASSTYPE_INTERFACE_ONLY (t) = interface_only; - CLASSTYPE_VBASE_SIZE (t) = integer_zero_node; 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)); @@ -4553,40 +4534,13 @@ make_lang_type (code) #ifdef GATHER_STATISTICS tree_node_counts[(int)lang_type] += 1; - tree_node_sizes[(int)lang_type] += sizeof(struct lang_type); + tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); #endif return t; } void -copy_decl_lang_specific (decl) - tree decl; -{ - extern struct obstack *current_obstack, *saveable_obstack; - register int *old = (int *)DECL_LANG_SPECIFIC (decl); - struct obstack *obstack = current_obstack; - register int i = sizeof (struct lang_decl) / sizeof (int); - register int *pi; - - if (! TREE_PERMANENT (decl)) - obstack = saveable_obstack; - else - my_friendly_assert (obstack == &permanent_obstack, 237); - - pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl)); - while (i-- > 0) - pi[i] = old[i]; - - DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi; - -#ifdef GATHER_STATISTICS - tree_node_counts[(int)lang_decl] += 1; - tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl); -#endif -} - -void dump_time_statistics () { register tree prev = 0, decl, next; @@ -4604,7 +4558,7 @@ dump_time_statistics () for (decl = filename_times; decl; decl = next) { next = IDENTIFIER_GLOBAL_VALUE (decl); - IDENTIFIER_GLOBAL_VALUE (decl) = prev; + SET_IDENTIFIER_GLOBAL_VALUE (decl, prev); prev = decl; } @@ -4622,32 +4576,6 @@ compiler_error (s, v, v2) sprintf (buf, s, v, v2); error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf); } - -void -compiler_error_with_decl (decl, s) - tree decl; - char *s; -{ - char *name; - count_error (0); - - report_error_function (0); - - if (TREE_CODE (decl) == PARM_DECL) - fprintf (stderr, "%s:%d: ", - DECL_SOURCE_FILE (DECL_CONTEXT (decl)), - DECL_SOURCE_LINE (DECL_CONTEXT (decl))); - else - fprintf (stderr, "%s:%d: ", - DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); - - name = lang_printable_name (decl); - if (name) - fprintf (stderr, s, name); - else - fprintf (stderr, s, "((anonymous))"); - fprintf (stderr, " (compiler error)\n"); -} void yyerror (string) @@ -4679,6 +4607,182 @@ yyerror (string) error (buf, token_buffer); } +static int +handle_cp_pragma (pname) + char *pname; +{ + register int token; + + if (! strcmp (pname, "vtable")) + { + extern tree pending_vtables; + + /* More follows: it must be a string constant (class name). */ + token = real_yylex (); + if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) + { + error ("invalid #pragma vtable"); + return -1; + } + + if (write_virtuals != 2) + { + warning ("use `+e2' option to enable #pragma vtable"); + return -1; + } + pending_vtables + = perm_tree_cons (NULL_TREE, + get_identifier (TREE_STRING_POINTER (yylval.ttype)), + pending_vtables); + token = real_yylex (); + if (token != END_OF_LINE) + warning ("trailing characters ignored"); + return 1; + } + else if (! strcmp (pname, "unit")) + { + /* More follows: it must be a string constant (unit name). */ + token = real_yylex (); + if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) + { + error ("invalid #pragma unit"); + return -1; + } + token = real_yylex (); + if (token != END_OF_LINE) + warning ("trailing characters ignored"); + return 1; + } + else if (! strcmp (pname, "interface")) + { + tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename)); + char *main_filename = input_filename; + + main_filename = file_name_nondirectory (main_filename); + + token = real_yylex (); + + if (token != END_OF_LINE) + { + if (token != STRING + || TREE_CODE (yylval.ttype) != STRING_CST) + { + error ("invalid `#pragma interface'"); + return -1; + } + main_filename = TREE_STRING_POINTER (yylval.ttype); + token = real_yylex (); + } + + if (token != END_OF_LINE) + warning ("garbage after `#pragma interface' ignored"); + +#ifndef NO_LINKAGE_HEURISTICS + write_virtuals = 3; + + if (impl_file_chain == 0) + { + /* If this is zero at this point, then we are + auto-implementing. */ + if (main_input_filename == 0) + main_input_filename = input_filename; + +#ifdef AUTO_IMPLEMENT + filename = file_name_nondirectory (main_input_filename); + fi = get_time_identifier (filename); + fi = IDENTIFIER_CLASS_VALUE (fi); + TREE_INT_CST_LOW (fi) = 0; + TREE_INT_CST_HIGH (fi) = 1; + /* Get default. */ + impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files)); + impl_file_chain->filename = filename; + impl_file_chain->next = 0; +#endif + } + + interface_only = interface_strcmp (main_filename); + interface_unknown = 0; + 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)); + char *main_filename = main_input_filename ? main_input_filename : input_filename; + + main_filename = file_name_nondirectory (main_filename); + token = real_yylex (); + if (token != END_OF_LINE) + { + if (token != STRING + || TREE_CODE (yylval.ttype) != STRING_CST) + { + error ("invalid `#pragma implementation'"); + return -1; + } + main_filename = TREE_STRING_POINTER (yylval.ttype); + token = real_yylex (); + } + + 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; + while (ifiles) + { + if (! strcmp (ifiles->filename, main_filename)) + break; + ifiles = ifiles->next; + } + if (ifiles == 0) + { + ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files)); + ifiles->filename = main_filename; + ifiles->next = impl_file_chain; + impl_file_chain = ifiles; + } + } + else if ((main_input_filename != 0 + && ! strcmp (main_input_filename, input_filename)) + || ! strcmp (input_filename, main_filename)) + { + write_virtuals = 3; + if (impl_file_chain == 0) + { + impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files)); + impl_file_chain->filename = main_filename; + impl_file_chain->next = 0; + } + } + else + error ("`#pragma implementation' can only appear at top-level"); + interface_only = 0; +#if 1 + /* We make this non-zero so that we infer decl linkage + in the impl file only for variables first declared + in the interface file. */ + interface_unknown = 1; +#else + /* We make this zero so that templates in the impl + file will be emitted properly. */ + interface_unknown = 0; +#endif + TREE_INT_CST_LOW (fileinfo) = interface_only; + TREE_INT_CST_HIGH (fileinfo) = interface_unknown; +#endif /* NO_LINKAGE_HEURISTICS */ + + return 1; + } + + return 0; +} + #ifdef HANDLE_SYSV_PRAGMA /* Handle a #pragma directive. INPUT is the current input stream, @@ -4688,11 +4792,13 @@ yyerror (string) /* This function has to be in this file, in order to get at the token types. */ -handle_sysv_pragma () +static int +handle_sysv_pragma (token) + register int token; { for (;;) { - switch (yylex ()) + switch (token) { case IDENTIFIER: case TYPENAME: @@ -4717,14 +4823,11 @@ handle_sysv_pragma () handle_pragma_token (")", NULL_TREE); break; case END_OF_LINE: - handle_pragma_token (NULL_PTR, NULL_TREE); - return; default: handle_pragma_token (NULL_PTR, NULL_TREE); - while (yylex () != END_OF_LINE) - /* continue */; - return; + return 1; } + token = real_yylex (); } } #endif /* HANDLE_SYSV_PRAGMA */ diff --git a/contrib/gcc/cp/lex.h b/contrib/gcc/cp/lex.h index 1cf5687..8df6b76 100644 --- a/contrib/gcc/cp/lex.h +++ b/contrib/gcc/cp/lex.h @@ -62,8 +62,10 @@ enum rid RID_SIGNED, RID_AUTO, RID_MUTABLE, + RID_COMPLEX, - /* This is where grokdeclarator ends its search when setting the specbits. */ + /* This is where grokdeclarator ends its search when setting the + specbits. */ RID_PUBLIC, RID_PRIVATE, @@ -71,22 +73,23 @@ enum rid RID_EXCEPTION, RID_TEMPLATE, RID_SIGNATURE, + RID_NULL, /* Before adding enough to get up to 64, the RIDBIT_* macros - will have to be changed a little. */ + will have to be changed a little. */ RID_MAX }; #define NORID RID_UNUSED #define RID_FIRST_MODIFIER RID_EXTERN -#define RID_LAST_MODIFIER RID_MUTABLE +#define RID_LAST_MODIFIER RID_COMPLEX /* The type that can represent all values of RIDBIT. */ -/* We assume that we can stick in at least 32 bits into this. */ +/* We assume that we can stick in at least 32 bits into this. */ typedef struct { unsigned long idata[2]; } RID_BIT_TYPE; -/* Be careful, all these modify N twice. */ +/* Be careful, all these modify N twice. */ #define RIDBIT_SETP(N, V) (((unsigned long)1 << (int) ((N)%32)) \ & (V).idata[(N)/32]) #define RIDBIT_NOTSETP(NN, VV) (! RIDBIT_SETP (NN, VV)) @@ -129,7 +132,4 @@ extern tree got_object; Positive is push count, negative is pop count. */ extern int pending_lang_change; -extern tree make_pointer_declarator (), make_reference_declarator (); -extern void reinit_parse_for_function (); -extern void reinit_parse_for_method (); -extern int yylex (); +extern int yylex PROTO((void)); diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c index a0e1527..29b31c4 100644 --- a/contrib/gcc/cp/method.c +++ b/contrib/gcc/cp/method.c @@ -1,9 +1,9 @@ /* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. - Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.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 @@ -21,28 +21,33 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __GNUC__ +#define __inline +#endif + #ifndef PARM_CAN_BE_ARRAY_TYPE #define PARM_CAN_BE_ARRAY_TYPE 1 #endif /* Handle method declarations. */ -#include #include "config.h" +#include "system.h" #include "tree.h" #include "cp-tree.h" -#include "class.h" #include "obstack.h" -#include #include "rtl.h" #include "expr.h" #include "output.h" #include "hard-reg-set.h" #include "flags.h" +#include "toplev.h" /* TREE_LIST of the current inline functions that need to be processed. */ struct pending_inline *pending_inlines; +int static_labelno; + #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free @@ -50,6 +55,38 @@ struct pending_inline *pending_inlines; static struct obstack scratch_obstack; 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 void build_overload_identifier PROTO((tree)); +static void build_overload_nested_name PROTO((tree)); +static void build_overload_int PROTO((tree, int)); +static void build_overload_identifier PROTO((tree)); +static void build_qualified_name PROTO((tree)); +static void build_overload_value PROTO((tree, tree, int)); +static void issue_nrepeats PROTO((int, tree)); +static char *build_mangled_name PROTO((tree,int,int)); +static void process_modifiers PROTO((tree)); +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)); +static void start_squangling PROTO((void)); +static void end_squangling PROTO((void)); +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)); +static int is_back_referenceable_type PROTO((tree)); +static int check_btype PROTO((tree)); +static void build_mangled_name_for_type PROTO((tree)); +static void build_mangled_name_for_type_with_Gcode PROTO((tree, int)); + # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) # define OB_PUTC2(C1,C2) \ @@ -62,10 +99,6 @@ static char *scratch_firstobj; # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) # define OB_LAST() (obstack_next_free (&scratch_obstack)[-1]) -#ifdef NO_AUTO_OVERLOAD -int is_overloaded (); -#endif - void init_method () { @@ -91,10 +124,12 @@ do_inline_function_hair (type, friend_list) if (method && TREE_CODE (method) == TREE_VEC) { - if (TREE_VEC_ELT (method, 0)) + if (TREE_VEC_ELT (method, 1)) + method = TREE_VEC_ELT (method, 1); + else if (TREE_VEC_ELT (method, 0)) method = TREE_VEC_ELT (method, 0); else - method = TREE_VEC_ELT (method, 1); + method = TREE_VEC_ELT (method, 2); } while (method) @@ -112,11 +147,6 @@ do_inline_function_hair (type, friend_list) DECL_CONTEXT (args) = method; args = TREE_CHAIN (args); } - - /* Allow this decl to be seen in global scope. Don't do this for - local class methods, though. */ - if (! current_function_decl) - IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method; } method = TREE_CHAIN (method); } @@ -135,157 +165,142 @@ do_inline_function_hair (type, friend_list) DECL_CONTEXT (args) = fndecl; args = TREE_CHAIN (args); } - - /* Allow this decl to be seen in global scope */ - if (! current_function_decl) - IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl; } friend_list = TREE_CHAIN (friend_list); } } -/* Report an argument type mismatch between the best declared function - we could find and the current argument list that we have. */ -void -report_type_mismatch (cp, parmtypes, name_kind) - struct candidate *cp; - tree parmtypes; - char *name_kind; -{ - int i = cp->u.bad_arg; - tree ttf, tta; - char *tmp_firstobj; - - switch (i) - { - case -4: - my_friendly_assert (TREE_CODE (cp->function) == TEMPLATE_DECL, 240); - cp_error ("type unification failed for function template `%#D'", - cp->function); - return; - - case -2: - cp_error ("too few arguments for %s `%#D'", name_kind, cp->function); - return; - case -1: - cp_error ("too many arguments for %s `%#D'", name_kind, cp->function); - return; - case 0: - if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE) - break; - case -3: - /* Happens when the implicit object parameter is rejected. */ - my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))), - 241); - cp_error ("call to non-const %s `%#D' with const object", - name_kind, cp->function); - return; - } - - ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function)); - tta = parmtypes; - - while (i-- > 0) - { - ttf = TREE_CHAIN (ttf); - tta = TREE_CHAIN (tta); - } +/* Here is where overload code starts. */ - OB_INIT (); - OB_PUTS ("bad argument "); - sprintf (digit_buffer, "%d", cp->u.bad_arg - - (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE) - + 1); - OB_PUTCP (digit_buffer); - - OB_PUTS (" for function `"); - OB_PUTCP (decl_as_string (cp->function, 1)); - OB_PUTS ("' (type was "); - - /* Reset `i' so that type printing routines do the right thing. */ - if (tta) - { - enum tree_code code = TREE_CODE (TREE_TYPE (TREE_VALUE (tta))); - if (code == ERROR_MARK) - OB_PUTS ("(failed type instantiation)"); - else - { - i = (code == FUNCTION_TYPE || code == METHOD_TYPE); - OB_PUTCP (type_as_string (TREE_TYPE (TREE_VALUE (tta)), 1)); - } - } - else OB_PUTS ("void"); - OB_PUTC (')'); - OB_FINISH (); +/* type tables for K and B type compression */ +static tree *btypelist = NULL; +static tree *ktypelist = NULL; +static int maxbsize = 0; +static int maxksize = 0; - tmp_firstobj = (char *)alloca (obstack_object_size (&scratch_obstack)); - bcopy (obstack_base (&scratch_obstack), tmp_firstobj, - obstack_object_size (&scratch_obstack)); - error (tmp_firstobj); -} - -/* Here is where overload code starts. */ +/* number of each type seen */ +static int maxbtype = 0; +static int maxktype = 0; -/* Array of types seen so far in top-level call to `build_overload_name'. +/* Array of types seen so far in top-level call to `build_mangled_name'. Allocated and deallocated by caller. */ -static tree *typevec; +static tree *typevec = NULL; +static int typevec_size; -/* Number of types interned by `build_overload_name' so far. */ -static int maxtype; - -/* Number of occurrences of last type seen. */ -static int nrepeats; +/* Number of types interned by `build_mangled_name' so far. */ +static int maxtype = 0; /* Nonzero if we should not try folding parameter types. */ static int nofold; -#define ALLOCATE_TYPEVEC(PARMTYPES) \ - do { maxtype = 0, nrepeats = 0; \ - typevec = (tree *)alloca (list_length (PARMTYPES) * sizeof (tree)); } while (0) +/* This appears to be set to true if an underscore is required to be + comcatenated before another number can be outputed. */ +static int numeric_output_need_bar; + +static __inline void +start_squangling () +{ + if (flag_do_squangling) + { + nofold = 0; + maxbtype = 0; + maxktype = 0; + maxbsize = 50; + maxksize = 50; + btypelist = (tree *)xmalloc (sizeof (tree) * maxbsize); + ktypelist = (tree *)xmalloc (sizeof (tree) * maxksize); + } +} -#define DEALLOCATE_TYPEVEC(PARMTYPES) \ - do { tree t = (PARMTYPES); \ - while (t) { TREE_USED (TREE_VALUE (t)) = 0; t = TREE_CHAIN (t); } \ - } while (0) +static __inline void +end_squangling () +{ + if (flag_do_squangling) + { + if (ktypelist) + free (ktypelist); + if (btypelist) + free (btypelist); + maxbsize = 0; + maxksize = 0; + maxbtype = 0; + maxktype = 0; + ktypelist = NULL; + btypelist = NULL; + } +} /* Code to concatenate an asciified integer to a string. */ -static -#ifdef __GNUC__ -__inline -#endif -void + +static __inline void icat (i) - int i; + HOST_WIDE_INT i; { + unsigned HOST_WIDE_INT ui; + /* Handle this case first, to go really quickly. For many common values, - the result of i/10 below is 1. */ + the result of ui/10 below is 1. */ if (i == 1) { OB_PUTC ('1'); return; } - if (i < 0) + if (i >= 0) + ui = i; + else { OB_PUTC ('m'); - i = -i; + ui = -i; + } + + if (ui >= 10) + icat (ui / 10); + + OB_PUTC ('0' + (ui % 10)); +} + +static void +dicat (lo, hi) + HOST_WIDE_INT lo, hi; +{ + unsigned HOST_WIDE_INT ulo, uhi, qlo, qhi; + + if (hi >= 0) + { + uhi = hi; + ulo = lo; } - if (i < 10) - OB_PUTC ('0' + i); else { - icat (i / 10); - OB_PUTC ('0' + (i % 10)); + uhi = (lo == 0 ? -hi : -hi-1); + ulo = -lo; + } + if (uhi == 0 + && ulo < ((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1))) + { + icat (ulo); + return; } + /* Divide 2^HOST_WIDE_INT*uhi+ulo by 10. */ + qhi = uhi / 10; + uhi = uhi % 10; + qlo = uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) / 5); + qlo += ulo / 10; + ulo = ulo % 10; + ulo += uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) % 5) + * 2; + qlo += ulo / 10; + ulo = ulo % 10; + /* Quotient is 2^HOST_WIDE_INT*qhi+qlo, remainder is ulo. */ + dicat (qlo, qhi); + OB_PUTC ('0' + ulo); } -static -#ifdef __GNUC__ -__inline -#endif -void -flush_repeats (type) +static __inline void +flush_repeats (nrepeats, type) + int nrepeats; tree type; { int tindex = 0; @@ -302,86 +317,327 @@ flush_repeats (type) } else OB_PUTC ('T'); - nrepeats = 0; icat (tindex); if (tindex > 9) OB_PUTC ('_'); } -static int numeric_output_need_bar; -static void build_overload_identifier (); +/* Returns nonzero iff this is a type to which we will want to make + back-references (using the `B' code). */ + +int +is_back_referenceable_type (type) + tree type; +{ + if (btypelist == NULL) + /* We're not generating any back-references. */ + return 0; + + switch (TREE_CODE (type)) + { + 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; + + case TEMPLATE_TYPE_PARM: + /* It would be a bit complex to demangle signatures correctly if + we generated back-references to these, and the manglings of + type parameters are short. */ + return 0; + + default: + return 1; + } +} + +/* Issue the squangling code indicating NREPEATS repetitions of TYPE, + which was the last parameter type output. */ + +static void +issue_nrepeats (nrepeats, type) + int nrepeats; + tree type; +{ + if (nrepeats == 1 && !is_back_referenceable_type (type)) + /* For types whose manglings are short, don't bother using the + repetition code if there's only one repetition, since the + repetition code will be about as long as the ordinary mangling. */ + build_mangled_name_for_type (type); + else + { + OB_PUTC ('n'); + icat (nrepeats); + if (nrepeats > 9) + OB_PUTC ('_'); + } +} + +/* 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 */ +static int +check_ktype (node, add) + tree node; + int add; +{ + int x; + tree localnode = node; + + if (ktypelist == NULL) + return -1; + + if (TREE_CODE (node) == TYPE_DECL) + localnode = TREE_TYPE (node); + + for (x=0; x < maxktype; x++) + { + if (localnode == ktypelist[x]) + return x ; + } + /* Didn't find it, so add it here */ + if (add) + { + if (maxksize <= maxktype) + { + maxksize = maxksize* 3 / 2; + ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize); + } + ktypelist[maxktype++] = localnode; + } + return -1; +} + + +static __inline int +issue_ktype (decl) + tree decl; +{ + int kindex; + kindex = check_ktype (decl, FALSE); + if (kindex != -1) + { + OB_PUTC ('K'); + icat (kindex); + if (kindex > 9) + OB_PUTC ('_'); + return TRUE; + } + return FALSE; +} + +/* Build a representation for DECL, which may be an entity not at + global scope. If so, a marker indicating that the name is + qualified has already been output, but the qualifying context has + not. */ static void build_overload_nested_name (decl) tree decl; { - if (DECL_CONTEXT (decl)) + tree context; + + if (ktypelist && issue_ktype (decl)) + return; + + if (decl == global_namespace) + return; + + context = CP_DECL_CONTEXT (decl); + + /* try to issue a K type, and if we can't continue the normal path */ + if (!(ktypelist && issue_ktype (context))) + { + /* For a template type parameter, we want to output an 'Xn' + rather than 'T' or some such. */ + if (TREE_CODE (context) == TEMPLATE_TYPE_PARM + || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM) + build_mangled_name_for_type (context); + else { - tree context = DECL_CONTEXT (decl); if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') - context = TYPE_MAIN_DECL (context); + context = TYPE_NAME (context); build_overload_nested_name (context); } + } if (TREE_CODE (decl) == FUNCTION_DECL) { tree name = DECL_ASSEMBLER_NAME (decl); char *label; - extern int var_labelno; - ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), var_labelno); - var_labelno++; + ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), static_labelno); + static_labelno++; if (numeric_output_need_bar) - { - OB_PUTC ('_'); - numeric_output_need_bar = 0; - } + OB_PUTC ('_'); icat (strlen (label)); OB_PUTCP (label); + numeric_output_need_bar = 1; } + else if (TREE_CODE (decl) == NAMESPACE_DECL) + build_overload_identifier (DECL_NAME (decl)); else /* TYPE_DECL */ - { - tree name = DECL_NAME (decl); - build_overload_identifier (name); - } + build_overload_identifier (decl); +} + +/* Output the decimal representation of I. If I > 9, the decimal + representation is preceeded and followed by an underscore. */ + +static void +build_underscore_int (i) + int i; +{ + if (i > 9) + OB_PUTC ('_'); + icat (i); + if (i > 9) + OB_PUTC ('_'); } -/* Encoding for an INTEGER_CST value. */ static void -build_overload_int (value) +build_overload_scope_ref (value) tree value; { - my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); - if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT) + OB_PUTC2 ('Q', '2'); + numeric_output_need_bar = 0; + build_mangled_name_for_type (TREE_OPERAND (value, 0)); + build_overload_identifier (TREE_OPERAND (value, 1)); +} + +/* Encoding for an INTEGER_CST value. */ + +static void +build_overload_int (value, in_template) + tree value; + int in_template; +{ + if (in_template && TREE_CODE (value) != INTEGER_CST) { - if (tree_int_cst_lt (value, integer_zero_node)) + if (TREE_CODE (value) == SCOPE_REF) + { + build_overload_scope_ref (value); + return; + } + + OB_PUTC ('E'); + numeric_output_need_bar = 0; + + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value)))) + { + int i; + int operands = tree_code_length[(int) TREE_CODE (value)]; + tree id; + char* name; + + id = ansi_opname [(int) TREE_CODE (value)]; + my_friendly_assert (id != NULL_TREE, 0); + name = IDENTIFIER_POINTER (id); + if (name[0] != '_' || name[1] != '_') + /* On some erroneous inputs, we can get here with VALUE a + LOOKUP_EXPR. In that case, the NAME will be the + identifier for "". We must survive + this routine in order to issue a sensible error + message, so we fall through to the case below. */ + goto bad_value; + + for (i = 0; i < operands; ++i) + { + tree operand; + enum tree_code tc; + + /* We just outputted either the `E' or the name of the + operator. */ + numeric_output_need_bar = 0; + + if (i != 0) + /* Skip the leading underscores. */ + OB_PUTCP (name + 2); + + operand = TREE_OPERAND (value, i); + tc = TREE_CODE (operand); + + if (TREE_CODE_CLASS (tc) == 't') + /* We can get here with sizeof, e.g.: + + template void f(A); */ + build_mangled_name_for_type (operand); + else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) + build_overload_int (operand, in_template); + else + build_overload_value (TREE_TYPE (operand), + operand, + in_template); + } + } + else { - OB_PUTC ('m'); - value = build_int_2 (~ TREE_INT_CST_LOW (value), - - TREE_INT_CST_HIGH (value)); + /* We don't ever want this output, but it's + inconvenient not to be able to build the string. + This should cause assembler errors we'll notice. */ + + static int n; + bad_value: + sprintf (digit_buffer, " *%d", n++); + OB_PUTCP (digit_buffer); } + + OB_PUTC ('W'); + numeric_output_need_bar = 0; + return; + } + + my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); + if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT) + { if (TREE_INT_CST_HIGH (value) != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) { /* need to print a DImode value in decimal */ - sorry ("conversion of long long as PT parameter"); + dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); + numeric_output_need_bar = 1; + return; } /* else fall through to print in smaller mode */ } /* Wordsize or smaller */ icat (TREE_INT_CST_LOW (value)); + numeric_output_need_bar = 1; +} + + +/* Output S followed by a representation of the TEMPLATE_PARM_INDEX + supplied in INDEX. */ + +static void +build_mangled_template_parm_index (s, index) + char* s; + tree index; +{ + OB_PUTCP (s); + build_underscore_int (TEMPLATE_PARM_IDX (index)); + /* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a + representation of the function from the point of view of its + type. */ + build_underscore_int (TEMPLATE_PARM_LEVEL (index)); } + static void -build_overload_value (type, value) +build_overload_value (type, value, in_template) tree type, value; + int in_template; { while (TREE_CODE (value) == NON_LVALUE_EXPR || TREE_CODE (value) == NOP_EXPR) value = TREE_OPERAND (value, 0); - my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242); - type = TREE_TYPE (type); + + 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) { @@ -389,6 +645,12 @@ build_overload_value (type, value) numeric_output_need_bar = 0; } + if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) + { + build_mangled_template_parm_index ("Y", value); + return; + } + if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) { @@ -411,65 +673,82 @@ build_overload_value (type, value) case ENUMERAL_TYPE: case BOOLEAN_TYPE: { - build_overload_int (value); - numeric_output_need_bar = 1; + build_overload_int (value, in_template); return; } -#ifndef REAL_IS_NOT_DOUBLE case REAL_TYPE: { REAL_VALUE_TYPE val; char *bufp = digit_buffer; - extern char *index (); + + pedwarn ("ANSI C++ forbids floating-point template arguments"); my_friendly_assert (TREE_CODE (value) == REAL_CST, 244); val = TREE_REAL_CST (value); - if (val < 0) + if (REAL_VALUE_ISNAN (val)) { - val = -val; - *bufp++ = 'm'; + sprintf (bufp, "NaN"); } - sprintf (bufp, "%e", val); - bufp = (char *) index (bufp, 'e'); - if (!bufp) - strcat (digit_buffer, "e0"); else { - char *p; - bufp++; - if (*bufp == '-') + if (REAL_VALUE_NEGATIVE (val)) { + val = REAL_VALUE_NEGATE (val); *bufp++ = 'm'; } - p = bufp; - if (*p == '+') - p++; - while (*p == '0') - p++; - if (*p == 0) + if (REAL_VALUE_ISINF (val)) { - *bufp++ = '0'; - *bufp = 0; + sprintf (bufp, "Infinity"); } - else if (p != bufp) + else { - while (*p) - *bufp++ = *p++; - *bufp = 0; + REAL_VALUE_TO_DECIMAL (val, "%.20e", bufp); + bufp = (char *) index (bufp, 'e'); + if (!bufp) + strcat (digit_buffer, "e0"); + else + { + char *p; + bufp++; + if (*bufp == '-') + { + *bufp++ = 'm'; + } + p = bufp; + if (*p == '+') + p++; + while (*p == '0') + p++; + if (*p == 0) + { + *bufp++ = '0'; + *bufp = 0; + } + else if (p != bufp) + { + while (*p) + *bufp++ = *p++; + *bufp = 0; + } + } +#ifdef NO_DOT_IN_LABEL + bufp = (char *) index (bufp, '.'); + if (bufp) + *bufp = '_'; +#endif } } OB_PUTCP (digit_buffer); numeric_output_need_bar = 1; return; } -#endif 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. */ + /* 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)); @@ -479,9 +758,9 @@ build_overload_value (type, value) if (TREE_CODE (a1) == INTEGER_CST && TREE_CODE (a2) == INTEGER_CST) { - build_overload_int (a1); + build_overload_int (a1, in_template); OB_PUTC ('_'); - build_overload_int (a2); + build_overload_int (a2, in_template); OB_PUTC ('_'); if (TREE_CODE (a3) == ADDR_EXPR) { @@ -496,8 +775,7 @@ build_overload_value (type, value) else if (TREE_CODE (a3) == INTEGER_CST) { OB_PUTC ('i'); - build_overload_int (a3); - numeric_output_need_bar = 1; + build_overload_int (a3, in_template); return; } } @@ -507,23 +785,31 @@ build_overload_value (type, value) } if (TREE_CODE (value) == INTEGER_CST) { - build_overload_int (value); + build_overload_int (value, in_template); + return; + } + else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) + { + build_mangled_template_parm_index ("", value); numeric_output_need_bar = 1; return; } + value = TREE_OPERAND (value, 0); if (TREE_CODE (value) == VAR_DECL) { my_friendly_assert (DECL_NAME (value) != 0, 245); - build_overload_identifier (DECL_NAME (value)); + build_overload_identifier (DECL_ASSEMBLER_NAME (value)); return; } else if (TREE_CODE (value) == FUNCTION_DECL) { my_friendly_assert (DECL_NAME (value) != 0, 246); - build_overload_identifier (DECL_NAME (value)); + build_overload_identifier (DECL_ASSEMBLER_NAME (value)); return; } + else if (TREE_CODE (value) == SCOPE_REF) + build_overload_scope_ref (value); else my_friendly_abort (71); break; /* not really needed */ @@ -535,46 +821,120 @@ build_overload_value (type, value) } } + +/* Add encodings for the declaration of template template parameters. + PARMLIST must be a TREE_VEC */ + +static void +build_template_template_parm_names (parmlist) + tree parmlist; +{ + int i, nparms; + + my_friendly_assert (TREE_CODE (parmlist) == TREE_VEC, 246.5); + nparms = TREE_VEC_LENGTH (parmlist); + icat (nparms); + for (i = 0; i < nparms; i++) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); + if (TREE_CODE (parm) == TYPE_DECL) + { + /* This parameter is a type. */ + OB_PUTC ('Z'); + } + else if (TREE_CODE (parm) == TEMPLATE_DECL) + { + /* This parameter is a template. */ + OB_PUTC ('z'); + build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm)); + } + else + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); + } +} + + +/* Add encodings for the vector of template parameters in PARMLIST, + given the vector of arguments to be substituted in ARGLIST. */ + +static void +build_template_parm_names (parmlist, arglist) + tree parmlist; + tree arglist; +{ + int i, nparms; + + 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); + if (TREE_CODE (parm) == TYPE_DECL) + { + /* This parameter is a type. */ + OB_PUTC ('Z'); + build_mangled_name_for_type (arg); + } + else if (TREE_CODE (parm) == TEMPLATE_DECL) + { + /* This parameter is a template. */ + if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + /* Output parameter declaration, argument index and level */ + build_mangled_name_for_type (arg); + else + { + /* A TEMPLATE_DECL node, output the parameter declaration + and template name */ + + OB_PUTC ('z'); + 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); + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); + build_overload_value (parm, arg, uses_template_parms (arglist)); + } + } + } + +/* Output the representation for NAME, which is either a TYPE_DECL or + an IDENTIFIER. */ + static void build_overload_identifier (name) tree name; { - if (IDENTIFIER_TEMPLATE (name)) - { + if (TREE_CODE (name) == TYPE_DECL + && IS_AGGR_TYPE (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 + (TREE_TYPE (name)))) + == FUNCTION_DECL))) + { + /* NAME is the TYPE_DECL for a template specialization. */ tree template, parmlist, arglist, tname; - int i, nparms; - template = IDENTIFIER_TEMPLATE (name); - arglist = TREE_VALUE (template); + template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); + arglist = innermost_args (TREE_VALUE (template), 0); template = TREE_PURPOSE (template); tname = DECL_NAME (template); - parmlist = DECL_ARGUMENTS (template); - nparms = TREE_VEC_LENGTH (parmlist); + parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); OB_PUTC ('t'); icat (IDENTIFIER_LENGTH (tname)); OB_PUTID (tname); - icat (nparms); - for (i = 0; i < nparms; i++) - { - tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); - tree arg = TREE_VEC_ELT (arglist, i); - if (TREE_CODE (parm) == TYPE_DECL) - { - /* This parameter is a type. */ - OB_PUTC ('Z'); - build_overload_name (arg, 0, 0); - } - else - { - parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0), - TREE_VEC_LENGTH (arglist), NULL_TREE); - /* It's a PARM_DECL. */ - build_overload_name (TREE_TYPE (parm), 0, 0); - build_overload_value (parm, arg); - } - } + build_template_parm_names (parmlist, arglist); } else { + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); if (numeric_output_need_bar) { OB_PUTC ('_'); @@ -585,392 +945,587 @@ build_overload_identifier (name) } } -/* Given a list of parameters in PARMTYPES, create an unambiguous - overload string. Should distinguish any type that C (or C++) can - distinguish. I.e., pointers to functions are treated correctly. - - Caller must deal with whether a final `e' goes on the end or not. - - Any default conversions must take place before this function - is called. - - BEGIN and END control initialization and finalization of the - obstack where we build the string. */ +/* Given DECL, either a class TYPE, TYPE_DECL or FUNCTION_DECL, produce + the mangling for it. Used by build_mangled_name and build_static_name. */ -char * -build_overload_name (parmtypes, begin, end) - tree parmtypes; - int begin, end; +static void +build_qualified_name (decl) + tree decl; { - int just_one; - tree parmtype; + tree context; + int i = 1; - if (begin) OB_INIT (); - numeric_output_need_bar = 0; + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') + decl = TYPE_NAME (decl); - if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST))) + /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ + if (TREE_CODE (decl) == TYPE_DECL + && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling) { - parmtype = parmtypes; - goto only_one; + tree id = DECL_ASSEMBLER_NAME (decl); + OB_PUTID (id); + if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1])) + numeric_output_need_bar = 1; + return; } - while (parmtypes) + context = decl; + /* if we can't find a Ktype, do it the hard way */ + if (check_ktype (context, FALSE) == -1) { - parmtype = TREE_VALUE (parmtypes); - - only_one: - - if (! nofold && ! just_one) + /* count type and namespace scopes */ + while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace) { - /* Every argument gets counted. */ - typevec[maxtype++] = parmtype; - - if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2]) - { - nrepeats++; - goto next; - } + i += 1; + context = DECL_CONTEXT (context); + if (check_ktype (context, FALSE) != -1) /* found it! */ + break; + if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') + context = TYPE_NAME (context); + } + } - if (nrepeats) - flush_repeats (typevec[maxtype-2]); + if (i > 1) + { + OB_PUTC ('Q'); + build_underscore_int (i); + numeric_output_need_bar = 0; + } + build_overload_nested_name (decl); +} - if (TREE_USED (parmtype)) +/* Output the mangled representation for TYPE. If EXTRA_GCODE is + non-zero, mangled names for structure/union types are intentionally + mangled differently from the method described in the ARM. */ + +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); +} + +/* Like build_mangled_name_for_type_with_Gcode, but never outputs the + `G'. */ + +void +build_mangled_name_for_type (type) + tree type; +{ + build_mangled_name_for_type_with_Gcode (type, 0); +} + +/* Given a list of parameters in PARMTYPES, create an unambiguous + overload string. Should distinguish any type that C (or C++) can + distinguish. I.e., pointers to functions are treated correctly. + + Caller must deal with whether a final `e' goes on the end or not. + + Any default conversions must take place before this function + is called. + + BEGIN and END control initialization and finalization of the + obstack where we build the string. */ + +char * +build_overload_name (parmtypes, begin, end) + tree parmtypes; + int begin, end; +{ + char *ret; + start_squangling (); + ret = build_mangled_name (parmtypes, begin, end); + end_squangling (); + return ret ; +} + +/* Output the mangled representation for PARMTYPES. If PARMTYPES is a + TREE_LIST, then it is a list of parameter types. Otherwise, + PARMTYPES must be a single type. */ + +static char * +build_mangled_name (parmtypes, begin, end) + tree parmtypes; + int begin, end; +{ + if (begin) + OB_INIT (); + + if (TREE_CODE (parmtypes) != TREE_LIST) + /* There is only one type. */ + build_mangled_name_for_type (parmtypes); + else + { + /* There are several types in a parameter list. */ + int nrepeats = 0; + int old_style_repeats = !flag_do_squangling && !nofold && typevec; + tree last_type = NULL_TREE; + + for (; parmtypes && parmtypes != void_list_node; + parmtypes = TREE_CHAIN (parmtypes)) + { + tree parmtype = canonical_type_variant (TREE_VALUE (parmtypes)); + + if (old_style_repeats) { - flush_repeats (parmtype); - goto next; + /* Every argument gets counted. */ + my_friendly_assert (maxtype < typevec_size, 387); + typevec[maxtype++] = parmtype; } - /* 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)) - TREE_USED (parmtype) = 1; - } + if (parmtype == last_type) + { + if (flag_do_squangling + || (old_style_repeats && TREE_USED (parmtype) + && !TYPE_FOR_JAVA (parmtype))) + { + /* The next type is the same as this one. Keep + track of the repetition, and output the repeat + count later. */ + nrepeats++; + continue; + } + } + else if (nrepeats != 0) + { + /* Indicate how many times the previous parameter was + repeated. */ + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + last_type = parmtype; - if (TYPE_PTRMEMFUNC_P (parmtype)) - parmtype = TYPE_PTRMEMFUNC_FN_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; + } - if (TREE_READONLY (parmtype)) - OB_PUTC ('C'); - if (TREE_CODE (parmtype) == INTEGER_TYPE - && TYPE_MAIN_VARIANT (parmtype) == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) - OB_PUTC ('U'); - if (TYPE_VOLATILE (parmtype)) - OB_PUTC ('V'); + /* Output the PARMTYPE. */ + build_mangled_name_for_type_with_Gcode (parmtype, 1); + } - switch (TREE_CODE (parmtype)) + /* Output the repeat count for the last parameter, if + necessary. */ + if (nrepeats != 0) { - case OFFSET_TYPE: - OB_PUTC ('O'); - build_overload_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0); + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + if (!parmtypes) + /* The parameter list ends in an ellipsis. */ + OB_PUTC ('e'); + } + + if (end) + OB_FINISH (); + return (char *)obstack_base (&scratch_obstack); +} + +/* handles emitting modifiers such as Constant, read-only, and volatile */ +void +process_modifiers (parmtype) + tree parmtype; +{ + if (TREE_READONLY (parmtype)) + OB_PUTC ('C'); + if (TREE_CODE (parmtype) == INTEGER_TYPE + && (TYPE_MAIN_VARIANT (parmtype) + == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) + && ! TYPE_FOR_JAVA (parmtype)) + OB_PUTC ('U'); + if (TYPE_VOLATILE (parmtype)) + OB_PUTC ('V'); +} + +/* 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 +check_btype (type) + tree type; +{ + int x; + + if (btypelist == NULL) + return 0; + + 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]) + { + OB_PUTC ('B'); + icat (x); + if (x > 9) OB_PUTC ('_'); - build_overload_name (TREE_TYPE (parmtype), 0, 0); - break; + return 1 ; + } + + if (maxbsize <= maxbtype) + { + /* Enlarge the table. */ + maxbsize = maxbsize * 3 / 2; + btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize); + } + + /* Register the TYPE. */ + btypelist[maxbtype++] = type; + + return 0; +} - case REFERENCE_TYPE: - OB_PUTC ('R'); - goto more; +/* handle emitting the correct code for various node types */ +static void +process_overload_item (parmtype, extra_Gcode) + tree parmtype; + int 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 */ + + switch (TREE_CODE (parmtype)) + { + case REFERENCE_TYPE: + OB_PUTC ('R'); + goto more; - case ARRAY_TYPE: + case ARRAY_TYPE: #if PARM_CAN_BE_ARRAY_TYPE - { - tree length; + { + tree length; - OB_PUTC ('A'); - if (TYPE_DOMAIN (parmtype) == NULL_TREE) - error ("pointer or reference to array of unknown bound in parm type"); - else + OB_PUTC ('A'); + if (TYPE_DOMAIN (parmtype) == NULL_TREE) + error("pointer/reference to array of unknown bound in parm type"); + else + { + tree length = array_type_nelts (parmtype); + if (TREE_CODE (length) != INTEGER_CST || flag_do_squangling) { - length = array_type_nelts (parmtype); - if (TREE_CODE (length) == INTEGER_CST) - icat (TREE_INT_CST_LOW (length) + 1); + length = fold (build (PLUS_EXPR, TREE_TYPE (length), + length, integer_one_node)); + STRIP_NOPS (length); } - OB_PUTC ('_'); - goto more; + build_overload_value (sizetype, length, 1); } + if (numeric_output_need_bar && ! flag_do_squangling) + OB_PUTC ('_'); + goto more; + } #else - OB_PUTC ('P'); - goto more; + OB_PUTC ('P'); + goto more; #endif - case POINTER_TYPE: - OB_PUTC ('P'); - more: - build_overload_name (TREE_TYPE (parmtype), 0, 0); - break; + case POINTER_TYPE: + OB_PUTC ('P'); + more: + build_mangled_name_for_type (TREE_TYPE (parmtype)); + return; + break; - case FUNCTION_TYPE: - case METHOD_TYPE: - { - tree firstarg = TYPE_ARG_TYPES (parmtype); - /* Otherwise have to implement reentrant typevecs, - unmark and remark types, etc. */ - int old_nofold = nofold; - nofold = 1; - - if (nrepeats) - flush_repeats (typevec[maxtype-1]); - - /* @@ It may be possible to pass a function type in - which is not preceded by a 'P'. */ - if (TREE_CODE (parmtype) == FUNCTION_TYPE) - { - OB_PUTC ('F'); - if (firstarg == NULL_TREE) - OB_PUTC ('e'); - else if (firstarg == void_list_node) - OB_PUTC ('v'); - else - build_overload_name (firstarg, 0, 0); - } - else - { - int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg))); - int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg))); - OB_PUTC ('M'); - firstarg = TREE_CHAIN (firstarg); - - build_overload_name (TYPE_METHOD_BASETYPE (parmtype), 0, 0); - if (constp) - OB_PUTC ('C'); - if (volatilep) - OB_PUTC ('V'); - - /* For cfront 2.0 compatibility. */ - OB_PUTC ('F'); - - if (firstarg == NULL_TREE) - OB_PUTC ('e'); - else if (firstarg == void_list_node) - OB_PUTC ('v'); - else - build_overload_name (firstarg, 0, 0); - } + default: + break; + } + + if (flag_do_squangling && check_btype (parmtype)) + /* If PARMTYPE is already in the list of back-referenceable types, + then check_btype will output the appropriate reference, and + there's nothing more to do. */ + return; - /* Separate args from return type. */ - OB_PUTC ('_'); - build_overload_name (TREE_TYPE (parmtype), 0, 0); - nofold = old_nofold; - break; + switch (TREE_CODE (parmtype)) + { + case OFFSET_TYPE: + OB_PUTC ('O'); + build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype)); + OB_PUTC ('_'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + break; + + case FUNCTION_TYPE: + case METHOD_TYPE: + { + tree parms = TYPE_ARG_TYPES (parmtype); + + /* Rather than implementing a reentrant TYPEVEC, we turn off + repeat codes here, unless we're squangling. Squangling + doesn't make use of the TYPEVEC, so there's no reentrancy + problem. */ + int old_nofold = nofold; + if (!flag_do_squangling) + nofold = 1; + + if (TREE_CODE (parmtype) == METHOD_TYPE) + { + /* Mark this as a method. */ + OB_PUTC ('M'); + /* Output the class of which this method is a member. */ + build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype)); + /* Output any qualifiers for the `this' parameter. */ + process_modifiers (TREE_TYPE (TREE_VALUE (parms))); } - case INTEGER_TYPE: - parmtype = TYPE_MAIN_VARIANT (parmtype); - if (parmtype == integer_type_node - || parmtype == unsigned_type_node) - OB_PUTC ('i'); - else if (parmtype == long_integer_type_node - || parmtype == long_unsigned_type_node) - OB_PUTC ('l'); - else if (parmtype == short_integer_type_node - || parmtype == short_unsigned_type_node) - OB_PUTC ('s'); - else if (parmtype == signed_char_type_node) - { - OB_PUTC ('S'); - OB_PUTC ('c'); - } - else if (parmtype == char_type_node - || parmtype == unsigned_char_type_node) - OB_PUTC ('c'); - else if (parmtype == wchar_type_node) - OB_PUTC ('w'); - else if (parmtype == long_long_integer_type_node - || parmtype == long_long_unsigned_type_node) - OB_PUTC ('x'); + /* Output the parameter types. */ + OB_PUTC ('F'); + if (parms == NULL_TREE) + OB_PUTC ('e'); + else if (parms == void_list_node) + OB_PUTC ('v'); + else + build_mangled_name (parms, 0, 0); + + /* Output the return type. */ + OB_PUTC ('_'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + + nofold = old_nofold; + break; + } + + case INTEGER_TYPE: + parmtype = TYPE_MAIN_VARIANT (parmtype); + if (parmtype == integer_type_node + || parmtype == unsigned_type_node + || parmtype == java_int_type_node) + OB_PUTC ('i'); + else if (parmtype == long_integer_type_node + || parmtype == long_unsigned_type_node) + OB_PUTC ('l'); + else if (parmtype == short_integer_type_node + || parmtype == short_unsigned_type_node + || parmtype == java_short_type_node) + OB_PUTC ('s'); + else if (parmtype == signed_char_type_node) + { + OB_PUTC ('S'); + OB_PUTC ('c'); + } + else if (parmtype == char_type_node + || parmtype == unsigned_char_type_node + || parmtype == java_byte_type_node) + OB_PUTC ('c'); + else if (parmtype == wchar_type_node + || parmtype == java_char_type_node) + OB_PUTC ('w'); + else if (parmtype == long_long_integer_type_node + || 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'); + /* 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 - my_friendly_abort (73); - break; - - case BOOLEAN_TYPE: - OB_PUTC ('b'); - break; - - case REAL_TYPE: - parmtype = TYPE_MAIN_VARIANT (parmtype); - if (parmtype == long_double_type_node) - OB_PUTC ('r'); - else if (parmtype == double_type_node) - OB_PUTC ('d'); - else if (parmtype == float_type_node) - OB_PUTC ('f'); - else my_friendly_abort (74); - break; - - case VOID_TYPE: - if (! just_one) - { -#if 0 - extern tree void_list_node; + else if (parmtype == java_boolean_type_node) + OB_PUTC ('b'); + else + my_friendly_abort (73); + break; - /* See if anybody is wasting memory. */ - my_friendly_assert (parmtypes == void_list_node, 247); -#endif - /* This is the end of a parameter list. */ - if (end) OB_FINISH (); - return (char *)obstack_base (&scratch_obstack); - } - OB_PUTC ('v'); - break; - - case ERROR_MARK: /* not right, but nothing is anyway */ - break; - - /* have to do these */ - case UNION_TYPE: - case RECORD_TYPE: - if (! just_one) - /* Make this type signature look incompatible - with AT&T. */ - OB_PUTC ('G'); - goto common; - case ENUMERAL_TYPE: - common: - { - tree name = TYPE_NAME (parmtype); - int i = 1; + case BOOLEAN_TYPE: + OB_PUTC ('b'); + break; - if (TREE_CODE (name) == TYPE_DECL) - { - tree context = name; + case REAL_TYPE: + parmtype = TYPE_MAIN_VARIANT (parmtype); + if (parmtype == long_double_type_node) + OB_PUTC ('r'); + else if (parmtype == double_type_node + || parmtype == java_double_type_node) + OB_PUTC ('d'); + else if (parmtype == float_type_node + || parmtype == java_float_type_node) + OB_PUTC ('f'); + else my_friendly_abort (74); + break; - /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ - if (DECL_ASSEMBLER_NAME (context) != DECL_NAME (context)) - { - OB_PUTID (DECL_ASSEMBLER_NAME (context)); - break; - } - while (DECL_CONTEXT (context)) - { - i += 1; - context = DECL_CONTEXT (context); - if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') - context = TYPE_NAME (context); - } - name = DECL_NAME (name); - } - my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 248); - if (i > 1) - { - OB_PUTC ('Q'); - if (i > 9) - OB_PUTC ('_'); - icat (i); - if (i > 9) - OB_PUTC ('_'); - numeric_output_need_bar = 0; - build_overload_nested_name (TYPE_MAIN_DECL (parmtype)); - } - else - build_overload_identifier (name); - break; - } + case COMPLEX_TYPE: + OB_PUTC ('J'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + break; - case UNKNOWN_TYPE: - /* This will take some work. */ - OB_PUTC ('?'); - break; - - case TEMPLATE_TYPE_PARM: - case TEMPLATE_CONST_PARM: - case UNINSTANTIATED_P_TYPE: - /* We don't ever want this output, but it's inconvenient not to - be able to build the string. This should cause assembler - errors we'll notice. */ - { - static int n; - sprintf (digit_buffer, " *%d", n++); - OB_PUTCP (digit_buffer); - } - break; + case VOID_TYPE: + OB_PUTC ('v'); + break; - default: - my_friendly_abort (75); - } + case ERROR_MARK: /* not right, but nothing is anyway */ + break; - next: - if (just_one) break; - parmtypes = TREE_CHAIN (parmtypes); - } - if (! just_one) - { - if (nrepeats) - flush_repeats (typevec[maxtype-1]); + /* have to do these */ + case UNION_TYPE: + case RECORD_TYPE: + { + if (extra_Gcode) + OB_PUTC ('G'); /* make it look incompatible with AT&T */ + /* drop through into next case */ + } + case ENUMERAL_TYPE: + { + 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); + break; + } + + case UNKNOWN_TYPE: + /* This will take some work. */ + OB_PUTC ('?'); + break; + + case TEMPLATE_TEMPLATE_PARM: + /* Find and output the original template parameter + declaration. */ + if (CLASSTYPE_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)); + } + else + { + build_mangled_template_parm_index ("ZzX", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + build_template_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype))); + } + break; - /* To get here, parms must end with `...'. */ - OB_PUTC ('e'); + case TEMPLATE_TYPE_PARM: + build_mangled_template_parm_index ("X", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + break; + + case TYPENAME_TYPE: + /* When mangling the type of a function template whose + declaration looks like: + + template void foo(typename T::U) + + we have to mangle these. */ + build_qualified_name (parmtype); + break; + + default: + my_friendly_abort (75); } - if (end) OB_FINISH (); - return (char *)obstack_base (&scratch_obstack); } -tree -build_static_name (basetype, name) - tree basetype, name; -{ - char *basename = build_overload_name (basetype, 1, 1); - char *buf = (char *) alloca (IDENTIFIER_LENGTH (name) - + sizeof (STATIC_NAME_FORMAT) - + strlen (basename)); - sprintf (buf, STATIC_NAME_FORMAT, basename, IDENTIFIER_POINTER (name)); - return get_identifier (buf); -} - -/* Generate an identifier that encodes the (ANSI) exception TYPE. */ - -/* This should be part of `ansi_opname', or at least be defined by the std. */ -#define EXCEPTION_NAME_PREFIX "__ex" -#define EXCEPTION_NAME_LENGTH 4 +/* Produce the mangling for a variable named NAME in CONTEXT, which can + be either a class TYPE or a FUNCTION_DECL. */ tree -cplus_exception_name (type) - tree type; +build_static_name (context, name) + tree context, name; { OB_INIT (); - OB_PUTS (EXCEPTION_NAME_PREFIX); - return get_identifier (build_overload_name (type, 0, 1)); + numeric_output_need_bar = 0; + start_squangling (); +#ifdef JOINER + OB_PUTC ('_'); + build_qualified_name (context); + OB_PUTC (JOINER); +#else + OB_PUTS ("__static_"); + build_qualified_name (context); + OB_PUTC ('_'); +#endif + OB_PUTID (name); + OB_FINISH (); + end_squangling (); + + return get_identifier ((char *)obstack_base (&scratch_obstack)); } -/* Change the name of a function definition so that it may be - overloaded. NAME is the name of the function to overload, - PARMS is the parameter list (which determines what name the - final function obtains). - - FOR_METHOD is 1 if this overload is being performed - for a method, rather than a function type. It is 2 if - this overload is being performed for a constructor. */ -tree -build_decl_overload (dname, parms, for_method) +static tree +build_decl_overload_real (dname, parms, ret_type, tparms, targs, + for_method) tree dname; tree parms; + tree ret_type; + tree tparms; + tree targs; int for_method; { char *name = IDENTIFIER_POINTER (dname); /* member operators new and delete look like methods at this point. */ - if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST) + if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST + && TREE_CHAIN (parms) == void_list_node) { if (dname == ansi_opname[(int) DELETE_EXPR]) return get_identifier ("__builtin_delete"); else if (dname == ansi_opname[(int) VEC_DELETE_EXPR]) return get_identifier ("__builtin_vec_delete"); - else if (TREE_CHAIN (parms) == void_list_node) - { - if (dname == ansi_opname[(int) NEW_EXPR]) - return get_identifier ("__builtin_new"); - else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) - return get_identifier ("__builtin_vec_new"); - } + if (dname == ansi_opname[(int) NEW_EXPR]) + return get_identifier ("__builtin_new"); + else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) + return get_identifier ("__builtin_vec_new"); } + start_squangling (); OB_INIT (); if (for_method != 2) OB_PUTCP (name); @@ -978,50 +1533,107 @@ build_decl_overload (dname, parms, for_method) and figure out its name without any extra encoding. */ OB_PUTC2 ('_', '_'); - if (for_method) - { -#if 0 - /* We can get away without doing this. */ - OB_PUTC ('M'); -#endif - { - tree this_type = TREE_VALUE (parms); + numeric_output_need_bar = 0; - if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ - parms = temp_tree_cons (NULL_TREE, SIGNATURE_TYPE (this_type), - TREE_CHAIN (parms)); - else - parms = temp_tree_cons (NULL_TREE, TREE_TYPE (this_type), - TREE_CHAIN (parms)); - } + if (tparms) + { + OB_PUTC ('H'); + build_template_parm_names (tparms, targs); + OB_PUTC ('_'); } - else + else if (!for_method && current_namespace == global_namespace) + /* XXX this works only if we call this in the same namespace + as the declaration. Unfortunately, we don't have the _DECL, + only its name */ OB_PUTC ('F'); + if (!for_method && current_namespace != global_namespace) + /* qualify with namespace */ + build_qualified_name (current_namespace); + if (parms == NULL_TREE) - OB_PUTC2 ('e', '\0'); + OB_PUTC ('e'); else if (parms == void_list_node) - OB_PUTC2 ('v', '\0'); + OB_PUTC ('v'); else { - ALLOCATE_TYPEVEC (parms); + 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 */ + typevec_size++; + typevec = (tree *)alloca (typevec_size * sizeof (tree)); + } nofold = 0; + if (for_method) { - build_overload_name (TREE_VALUE (parms), 0, 0); + tree this_type = TREE_VALUE (parms); + + if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ + this_type = SIGNATURE_TYPE (this_type); + else + this_type = TREE_TYPE (this_type); + + build_mangled_name_for_type (this_type); - typevec[maxtype++] = TREE_VALUE (parms); - TREE_USED (TREE_VALUE (parms)) = 1; + if (!flag_do_squangling) + { + 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)) - build_overload_name (TREE_CHAIN (parms), 0, 1); + build_mangled_name (TREE_CHAIN (parms), 0, 0); else - OB_PUTC2 ('e', '\0'); + OB_PUTC ('e'); } else - build_overload_name (parms, 0, 1); - DEALLOCATE_TYPEVEC (parms); + { + /* the namespace qualifier for a global function + will count as type */ + if (current_namespace != global_namespace + && !flag_do_squangling) + { + my_friendly_assert (maxtype < typevec_size, 387); + typevec[maxtype++] = current_namespace; + } + 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 (ret_type != NULL_TREE && for_method != 2) + { + /* Add the return type. */ + OB_PUTC ('_'); + build_mangled_name_for_type (ret_type); } + + OB_FINISH (); + end_squangling (); { tree n = get_identifier (obstack_base (&scratch_obstack)); if (IDENTIFIER_OPNAME_P (dname)) @@ -1030,441 +1642,146 @@ build_decl_overload (dname, parms, for_method) } } -/* Build an overload name for the type expression TYPE. */ +/* Change the name of a function definition so that it may be + overloaded. NAME is the name of the function to overload, + PARMS is the parameter list (which determines what name the + final function obtains). + + FOR_METHOD is 1 if this overload is being performed + for a method, rather than a function type. It is 2 if + this overload is being performed for a constructor. */ + tree -build_typename_overload (type) - tree type; +build_decl_overload (dname, parms, for_method) + tree dname; + tree parms; + int for_method; { - tree id; - - OB_INIT (); - OB_PUTID (ansi_opname[(int) TYPE_EXPR]); - nofold = 1; - build_overload_name (type, 0, 1); - id = get_identifier (obstack_base (&scratch_obstack)); - IDENTIFIER_OPNAME_P (id) = 1; -#if 0 - IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type); -#endif - TREE_TYPE (id) = type; - return id; + return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE, + NULL_TREE, for_method); } -#ifndef NO_DOLLAR_IN_LABEL -#define T_DESC_FORMAT "TD$" -#define I_DESC_FORMAT "ID$" -#define M_DESC_FORMAT "MD$" -#else -#if !defined(NO_DOT_IN_LABEL) -#define T_DESC_FORMAT "TD." -#define I_DESC_FORMAT "ID." -#define M_DESC_FORMAT "MD." -#else -#define T_DESC_FORMAT "__t_desc_" -#define I_DESC_FORMAT "__i_desc_" -#define M_DESC_FORMAT "__m_desc_" -#endif -#endif -/* Build an overload name for the type expression TYPE. */ +/* Like build_decl_overload, but for template functions. */ + tree -build_t_desc_overload (type) - tree type; +build_template_decl_overload (decl, parms, ret_type, tparms, targs, + for_method) + tree decl; + tree parms; + tree ret_type; + tree tparms; + tree targs; + int for_method; { - OB_INIT (); - OB_PUTS (T_DESC_FORMAT); - nofold = 1; + tree res, saved_ctx; -#if 0 - /* Use a different format if the type isn't defined yet. */ - if (TYPE_SIZE (type) == NULL_TREE) - { - char *p; - int changed; - - for (p = tname; *p; p++) - if (isupper (*p)) - { - changed = 1; - *p = tolower (*p); - } - /* If there's no change, we have an inappropriate T_DESC_FORMAT. */ - my_friendly_assert (changed != 0, 249); - } -#endif + /* 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. */ - build_overload_name (type, 0, 1); - return get_identifier (obstack_base (&scratch_obstack)); -} + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702); + saved_ctx = current_namespace; + current_namespace = CP_DECL_CONTEXT (decl); -/* Top-level interface to explicit overload requests. Allow NAME - to be overloaded. Error if NAME is already declared for the current - scope. Warning if function is redundantly overloaded. */ + res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type, + tparms, targs, for_method); -void -declare_overloaded (name) - tree name; -{ -#ifdef NO_AUTO_OVERLOAD - if (is_overloaded (name)) - warning ("function `%s' already declared overloaded", - IDENTIFIER_POINTER (name)); - else if (IDENTIFIER_GLOBAL_VALUE (name)) - error ("overloading function `%s' that is already defined", - IDENTIFIER_POINTER (name)); - else - { - TREE_OVERLOADED (name) = 1; - IDENTIFIER_GLOBAL_VALUE (name) = build_tree_list (name, NULL_TREE); - TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)) = unknown_type_node; - } -#else - if (current_lang_name == lang_name_cplusplus) - { - if (0) - warning ("functions are implicitly overloaded in C++"); - } - else if (current_lang_name == lang_name_c) - error ("overloading function `%s' cannot be done in C language context"); - else - my_friendly_abort (76); -#endif -} - -#ifdef NO_AUTO_OVERLOAD -/* Check to see if NAME is overloaded. For first approximation, - check to see if its TREE_OVERLOADED is set. This is used on - IDENTIFIER nodes. */ -int -is_overloaded (name) - tree name; -{ - /* @@ */ - return (TREE_OVERLOADED (name) - && (! IDENTIFIER_CLASS_VALUE (name) || current_class_type == 0) - && ! IDENTIFIER_LOCAL_VALUE (name)); + current_namespace = saved_ctx; + return res; } -#endif - -/* Given a tree_code CODE, and some arguments (at least one), - attempt to use an overloaded operator on the arguments. - - For unary operators, only the first argument need be checked. - For binary operators, both arguments may need to be checked. - - Member functions can convert class references to class pointers, - for one-level deep indirection. More than that is not supported. - Operators [](), ()(), and ->() must be member functions. - We call function call building calls with LOOKUP_COMPLAIN if they - are our only hope. This is true when we see a vanilla operator - applied to something of aggregate type. If this fails, we are free - to return `error_mark_node', because we will have reported the - error. - Operators NEW and DELETE overload in funny ways: operator new takes - a single `size' parameter, and operator delete takes a pointer to the - storage being deleted. When overloading these operators, success is - assumed. If there is a failure, report an error message and return - `error_mark_node'. */ +/* Build an overload name for the type expression TYPE. */ -/* NOSTRICT */ tree -build_opfncall (code, flags, xarg1, xarg2, arg3) - enum tree_code code; - int flags; - tree xarg1, xarg2, arg3; +build_typename_overload (type) + tree type; { - tree rval = 0; - tree arg1, arg2; - tree type1, type2, fnname; - tree fields1 = 0, parms = 0; - tree global_fn; - int try_second; - int binary_is_unary; - - if (xarg1 == error_mark_node) - return error_mark_node; - - if (code == COND_EXPR) - { - if (TREE_CODE (xarg2) == ERROR_MARK - || TREE_CODE (arg3) == ERROR_MARK) - return error_mark_node; - } - if (code == COMPONENT_REF) - if (TREE_CODE (TREE_TYPE (xarg1)) == POINTER_TYPE) - return rval; - - /* First, see if we can work with the first argument */ - type1 = TREE_TYPE (xarg1); - - /* Some tree codes have length > 1, but we really only want to - overload them if their first argument has a user defined type. */ - switch (code) - { - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case COMPONENT_REF: - binary_is_unary = 1; - try_second = 0; - break; - - /* ARRAY_REFs and CALL_EXPRs must overload successfully. - If they do not, return error_mark_node instead of NULL_TREE. */ - case ARRAY_REF: - if (xarg2 == error_mark_node) - return error_mark_node; - case CALL_EXPR: - rval = error_mark_node; - binary_is_unary = 0; - try_second = 0; - break; - - case VEC_NEW_EXPR: - case NEW_EXPR: - { - tree args = tree_cons (NULL_TREE, xarg2, arg3); - fnname = ansi_opname[(int) code]; - if (flags & LOOKUP_GLOBAL) - return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN, - (struct candidate *)0); - - rval = build_method_call - (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node), - "new"), - fnname, args, 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) = xarg1; - TREE_CALLS_NEW (rval) = 1; - return rval; - } - break; + tree id; - case VEC_DELETE_EXPR: - case DELETE_EXPR: - { - fnname = ansi_opname[(int) code]; - if (flags & LOOKUP_GLOBAL) - return build_overload_call (fnname, - build_tree_list (NULL_TREE, xarg1), - flags & LOOKUP_COMPLAIN, - (struct candidate *)0); - - rval = build_method_call - (build_indirect_ref (build1 (NOP_EXPR, TREE_TYPE (xarg1), - error_mark_node), - NULL_PTR), - fnname, tree_cons (NULL_TREE, xarg1, - build_tree_list (NULL_TREE, xarg2)), - NULL_TREE, flags); + OB_INIT (); + OB_PUTID (ansi_opname[(int) TYPE_EXPR]); + nofold = 1; + start_squangling (); + build_mangled_name (type, 0, 1); + id = get_identifier (obstack_base (&scratch_obstack)); + IDENTIFIER_OPNAME_P (id) = 1; #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; - } - break; - - default: - binary_is_unary = 0; - try_second = tree_code_length [(int) code] == 2; - if (try_second && xarg2 == error_mark_node) - return error_mark_node; - break; - } - - if (try_second && xarg2 == error_mark_node) - return error_mark_node; - - /* What ever it was, we do not know how to deal with it. */ - if (type1 == NULL_TREE) - return rval; - - if (TREE_CODE (type1) == OFFSET_TYPE) - type1 = TREE_TYPE (type1); - - if (TREE_CODE (type1) == REFERENCE_TYPE) - { - arg1 = convert_from_reference (xarg1); - type1 = TREE_TYPE (arg1); - } - else - { - arg1 = xarg1; - } - - if (!IS_AGGR_TYPE (type1) || TYPE_PTRMEMFUNC_P (type1)) - { - /* Try to fail. First, fail if unary */ - if (! try_second) - return rval; - /* Second, see if second argument is non-aggregate. */ - type2 = TREE_TYPE (xarg2); - if (TREE_CODE (type2) == OFFSET_TYPE) - type2 = TREE_TYPE (type2); - if (TREE_CODE (type2) == REFERENCE_TYPE) - { - arg2 = convert_from_reference (xarg2); - type2 = TREE_TYPE (arg2); - } - else - { - arg2 = xarg2; - } - - if (!IS_AGGR_TYPE (type2)) - return rval; - try_second = 0; - } - - if (try_second) - { - /* First arg may succeed; see whether second should. */ - type2 = TREE_TYPE (xarg2); - if (TREE_CODE (type2) == OFFSET_TYPE) - type2 = TREE_TYPE (type2); - if (TREE_CODE (type2) == REFERENCE_TYPE) - { - arg2 = convert_from_reference (xarg2); - type2 = TREE_TYPE (arg2); - } - else - { - arg2 = xarg2; - } - - if (! IS_AGGR_TYPE (type2)) - try_second = 0; - } - - if (type1 == unknown_type_node - || (try_second && TREE_TYPE (xarg2) == unknown_type_node)) - { - /* This will not be implemented in the foreseeable future. */ - return rval; - } - - if (code == MODIFY_EXPR) - fnname = ansi_assopname[(int) TREE_CODE (arg3)]; - else - fnname = ansi_opname[(int) code]; - - global_fn = lookup_name_nonclass (fnname); - - /* This is the last point where we will accept failure. This - may be too eager if we wish an overloaded operator not to match, - but would rather a normal operator be called on a type-converted - argument. */ + IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type); +#endif + TREE_TYPE (id) = type; + end_squangling (); + return id; +} - if (IS_AGGR_TYPE (type1)) - { - fields1 = lookup_fnfields (TYPE_BINFO (type1), fnname, 0); - /* ARM $13.4.7, prefix/postfix ++/--. */ - if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) - { - xarg2 = integer_zero_node; - binary_is_unary = 0; +tree +build_overload_with_type (name, type) + tree name, type; +{ + OB_INIT (); + OB_PUTID (name); + nofold = 1; - if (fields1) - { - tree t, t2; - int have_postfix = 0; + start_squangling (); + build_mangled_name (type, 0, 1); + end_squangling (); + return get_identifier (obstack_base (&scratch_obstack)); +} - /* Look for an `operator++ (int)'. If they didn't have - one, then we fall back to the old way of doing things. */ - for (t = TREE_VALUE (fields1); t ; t = DECL_CHAIN (t)) - { - t2 = TYPE_ARG_TYPES (TREE_TYPE (t)); - if (TREE_CHAIN (t2) != NULL_TREE - && TREE_VALUE (TREE_CHAIN (t2)) == integer_type_node) - { - have_postfix = 1; - break; - } - } +tree +get_id_2 (name, name2) + char *name; + tree name2; +{ + OB_INIT (); + OB_PUTCP (name); + OB_PUTID (name2); + OB_FINISH (); + return get_identifier (obstack_base (&scratch_obstack)); +} - if (! have_postfix) - { - char *op = POSTINCREMENT_EXPR ? "++" : "--"; - - /* There's probably a LOT of code in the world that - relies upon this old behavior. */ - if (! flag_traditional) - pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead", - op, op); - xarg2 = NULL_TREE; - binary_is_unary = 1; - } - } - } - } +/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */ - if (fields1 == NULL_TREE && global_fn == NULL_TREE) - return rval; +tree +build_destructor_name (type) + tree type; +{ + return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX), + type); +} + +/* Given a tree_code CODE, and some arguments (at least one), + attempt to use an overloaded operator on the arguments. - /* If RVAL winds up being `error_mark_node', we will return - that... There is no way that normal semantics of these - operators will succeed. */ + For unary operators, only the first argument need be checked. + For binary operators, both arguments may need to be checked. - /* This argument may be an uncommitted OFFSET_REF. This is - the case for example when dealing with static class members - which are referenced from their class name rather than - from a class instance. */ - if (TREE_CODE (xarg1) == OFFSET_REF - && TREE_CODE (TREE_OPERAND (xarg1, 1)) == VAR_DECL) - xarg1 = TREE_OPERAND (xarg1, 1); - if (try_second && xarg2 && TREE_CODE (xarg2) == OFFSET_REF - && TREE_CODE (TREE_OPERAND (xarg2, 1)) == VAR_DECL) - xarg2 = TREE_OPERAND (xarg2, 1); + Member functions can convert class references to class pointers, + for one-level deep indirection. More than that is not supported. + Operators [](), ()(), and ->() must be member functions. - if (global_fn) - flags |= LOOKUP_GLOBAL; + We call function call building calls with LOOKUP_COMPLAIN if they + are our only hope. This is true when we see a vanilla operator + applied to something of aggregate type. If this fails, we are free + to return `error_mark_node', because we will have reported the + error. - if (code == CALL_EXPR) - { - /* This can only be a member function. */ - return build_method_call (xarg1, fnname, xarg2, - NULL_TREE, LOOKUP_NORMAL); - } - else if (tree_code_length[(int) code] == 1 || binary_is_unary) - { - parms = NULL_TREE; - rval = build_method_call (xarg1, fnname, NULL_TREE, NULL_TREE, flags); - } - else if (code == COND_EXPR) - { - parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3)); - rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags); - } - else if (code == METHOD_CALL_EXPR) - { - /* must be a member function. */ - parms = tree_cons (NULL_TREE, xarg2, arg3); - return build_method_call (xarg1, fnname, parms, NULL_TREE, - LOOKUP_NORMAL); - } - else if (fields1) - { - parms = build_tree_list (NULL_TREE, xarg2); - rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags); - } - else - { - parms = tree_cons (NULL_TREE, xarg1, - build_tree_list (NULL_TREE, xarg2)); - rval = build_overload_call (fnname, parms, flags, - (struct candidate *)0); - } + Operators NEW and DELETE overload in funny ways: operator new takes + a single `size' parameter, and operator delete takes a pointer to the + storage being deleted. When overloading these operators, success is + assumed. If there is a failure, report an error message and return + `error_mark_node'. */ - return rval; +/* NOSTRICT */ +tree +build_opfncall (code, flags, xarg1, xarg2, arg3) + enum tree_code code; + int flags; + tree xarg1, xarg2, arg3; +{ + return build_new_op (code, flags, xarg1, xarg2, arg3); } /* This function takes an identifier, ID, and attempts to figure out what @@ -1478,7 +1795,6 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) NAME is $1 from the bison rule. It is an IDENTIFIER_NODE. VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1) - yychar is the pending input character (suitably encoded :-). As a last ditch, try to look up the name as a label and return that address. @@ -1488,13 +1804,12 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) compiler faster). */ tree -hack_identifier (value, name, yychar) +hack_identifier (value, name) tree value, name; - int yychar; { tree type; - if (TREE_CODE (value) == ERROR_MARK) + if (value == error_mark_node) { if (current_class_name) { @@ -1507,6 +1822,9 @@ hack_identifier (value, name, yychar) fndecl = TREE_VALUE (fields); my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251); + /* I could not trigger this code. MvL */ + my_friendly_abort (980325); +#ifdef DEAD if (DECL_CHAIN (fndecl) == NULL_TREE) { warning ("methods cannot be converted to function pointers"); @@ -1518,6 +1836,7 @@ hack_identifier (value, name, yychar) IDENTIFIER_POINTER (name)); return error_mark_node; } +#endif } } if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name)) @@ -1530,23 +1849,27 @@ hack_identifier (value, name, yychar) type = TREE_TYPE (value); if (TREE_CODE (value) == FIELD_DECL) { - if (current_class_decl == NULL_TREE) + if (current_class_ptr == NULL_TREE) { error ("request for member `%s' in static member function", IDENTIFIER_POINTER (DECL_NAME (value))); return error_mark_node; } - TREE_USED (current_class_decl) = 1; + TREE_USED (current_class_ptr) = 1; /* Mark 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. */ TREE_USED (value) = 1; - return build_component_ref (C_C_D, name, 0, 1); + value = build_component_ref (current_class_ref, name, NULL_TREE, 1); } - - if (really_overloaded_fn (value)) + 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)) { +#if 0 tree t = get_first_fn (value); for (; t; t = DECL_CHAIN (t)) { @@ -1556,21 +1879,46 @@ hack_identifier (value, name, yychar) assemble_external (t); TREE_USED (t) = 1; } +#endif } + else if (TREE_CODE (value) == OVERLOAD) + /* not really overloaded function */ + mark_used (OVL_FUNCTION (value)); else if (TREE_CODE (value) == TREE_LIST) { + /* Ambiguous reference to base members, possibly other cases?. */ tree t = value; while (t && TREE_CODE (t) == TREE_LIST) { - assemble_external (TREE_VALUE (t)); - TREE_USED (t) = 1; + mark_used (TREE_VALUE (t)); t = TREE_CHAIN (t); } } + else if (TREE_CODE (value) == NAMESPACE_DECL) + { + cp_error ("use of namespace `%D' as expression", value); + return error_mark_node; + } + else if (DECL_CLASS_TEMPLATE_P (value)) + { + cp_error ("use of class template `%T' as expression", value); + return error_mark_node; + } else + mark_used (value); + + if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL) { - assemble_external (value); - TREE_USED (value) = 1; + tree context = decl_function_context (value); + if (context != NULL_TREE && context != current_function_decl + && ! TREE_STATIC (value)) + { + cp_error ("use of %s from containing function", + (TREE_CODE (value) == VAR_DECL + ? "`auto' variable" : "parameter")); + cp_error_at (" `%#D' declared here", value); + value = error_mark_node; + } } if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) @@ -1578,8 +1926,7 @@ hack_identifier (value, name, yychar) if (DECL_LANG_SPECIFIC (value) && DECL_CLASS_CONTEXT (value) != current_class_type) { - tree path; - enum access_type access; + tree path, access; register tree context = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value)) ? DECL_CLASS_CONTEXT (value) @@ -1589,13 +1936,13 @@ hack_identifier (value, name, yychar) if (path) { access = compute_access (path, value); - if (access != access_public) + 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"); + TREE_PRIVATE (value) ? "private" + : "from a private base class"); else error ("enum `%s' is from private base class", IDENTIFIER_POINTER (name)); @@ -1603,9 +1950,8 @@ hack_identifier (value, name, yychar) } } } - return value; } - if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value)) + else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value)) { if (type == 0) { @@ -1617,437 +1963,167 @@ hack_identifier (value, name, yychar) return value; } - if (TREE_CODE (type) == REFERENCE_TYPE) - { - my_friendly_assert (TREE_CODE (value) == VAR_DECL - || TREE_CODE (value) == PARM_DECL - || TREE_CODE (value) == RESULT_DECL, 252); - return convert_from_reference (value); - } + if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl) + value = convert_from_reference (value); return value; } -#if 0 -/* Given an object OF, and a type conversion operator COMPONENT - build a call to the conversion operator, if a call is requested, - or return the address (as a pointer to member function) if one is not. - - OF can be a TYPE_DECL or any kind of datum that would normally - be passed to `build_component_ref'. It may also be NULL_TREE, - in which case `current_class_type' and `current_class_decl' - provide default values. - - BASETYPE_PATH, if non-null, is the path of basetypes - to go through before we get the the instance of interest. - - PROTECT says whether we apply C++ scoping rules or not. */ -tree -build_component_type_expr (of, component, basetype_path, protect) - tree of, component, basetype_path; - int protect; -{ - tree cname = NULL_TREE; - tree tmp, last; - tree name; - int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN; - - if (of) - my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253); - my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254); - - tmp = TREE_OPERAND (component, 0); - last = NULL_TREE; - - while (tmp) - { - switch (TREE_CODE (tmp)) - { - case CALL_EXPR: - if (last) - TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0); - else - TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0); - - last = groktypename (build_tree_list (TREE_TYPE (component), - TREE_OPERAND (component, 0))); - name = build_typename_overload (last); - TREE_TYPE (name) = last; - - if (TREE_OPERAND (tmp, 0) - && TREE_OPERAND (tmp, 0) != void_list_node) - { - cp_error ("`operator %T' requires empty parameter list", last); - TREE_OPERAND (tmp, 0) = NULL_TREE; - } - - if (of && TREE_CODE (of) != TYPE_DECL) - return build_method_call (of, name, NULL_TREE, NULL_TREE, flags); - else if (of) - { - tree this_this; - - if (current_class_decl == NULL_TREE) - { - cp_error ("object required for `operator %T' call", - TREE_TYPE (name)); - return error_mark_node; - } - - this_this = convert_pointer_to (TREE_TYPE (of), - current_class_decl); - this_this = build_indirect_ref (this_this, NULL_PTR); - return build_method_call (this_this, name, NULL_TREE, - NULL_TREE, flags | LOOKUP_NONVIRTUAL); - } - else if (current_class_decl) - return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags); - - cp_error ("object required for `operator %T' call", - TREE_TYPE (name)); - return error_mark_node; - - case INDIRECT_REF: - case ADDR_EXPR: - case ARRAY_REF: - break; - - case SCOPE_REF: - my_friendly_assert (cname == 0, 255); - cname = TREE_OPERAND (tmp, 0); - tmp = TREE_OPERAND (tmp, 1); - break; - - default: - my_friendly_abort (77); - } - last = tmp; - tmp = TREE_OPERAND (tmp, 0); - } - - last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0))); - name = build_typename_overload (last); - TREE_TYPE (name) = last; - if (of && TREE_CODE (of) == TYPE_DECL) - { - if (cname == NULL_TREE) - { - cname = DECL_NAME (of); - of = NULL_TREE; - } - else my_friendly_assert (cname == DECL_NAME (of), 256); - } - - if (of) - { - tree this_this; - - if (current_class_decl == NULL_TREE) - { - cp_error ("object required for `operator %T' call", - TREE_TYPE (name)); - return error_mark_node; - } - - this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl); - return build_component_ref (this_this, name, 0, protect); - } - else if (cname) - return build_offset_ref (cname, name); - else if (current_class_name) - return build_offset_ref (current_class_name, name); - - cp_error ("object required for `operator %T' member reference", - TREE_TYPE (name)); - return error_mark_node; -} -#endif - -static char * -thunk_printable_name (decl) - tree decl; -{ - return ""; -} - tree make_thunk (function, delta) tree function; int delta; { - char buffer[250]; - tree thunk_fndecl, thunk_id; + tree thunk_id; tree thunk; - char *func_name; - static int thunk_number = 0; tree func_decl; + if (TREE_CODE (function) != ADDR_EXPR) abort (); func_decl = TREE_OPERAND (function, 0); if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); - func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl)); - if (delta<=0) - sprintf (buffer, "__thunk_%d_%s", -delta, func_name); + + OB_INIT (); + OB_PUTS ("__thunk_"); + if (delta > 0) + { + OB_PUTC ('n'); + icat (delta); + } else - sprintf (buffer, "__thunk_n%d_%s", delta, func_name); - thunk_id = get_identifier (buffer); + icat (-delta); + OB_PUTC ('_'); + OB_PUTID (DECL_ASSEMBLER_NAME (func_decl)); + OB_FINISH (); + thunk_id = get_identifier (obstack_base (&scratch_obstack)); + thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); if (thunk && TREE_CODE (thunk) != THUNK_DECL) { - error_with_decl ("implementation-reserved name `%s' used"); - IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE; + cp_error ("implementation-reserved name `%D' used", thunk_id); + thunk = NULL_TREE; + SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); } if (thunk == NULL_TREE) { - thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl)); - DECL_RESULT (thunk) - = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type))); - TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type)); - TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type)); - make_function_rtl (thunk); + thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); + TREE_READONLY (thunk) = TREE_READONLY (func_decl); + TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl); + comdat_linkage (thunk); + TREE_SET_CODE (thunk, THUNK_DECL); DECL_INITIAL (thunk) = function; THUNK_DELTA (thunk) = delta; + DECL_EXTERNAL (thunk) = 1; + DECL_ARTIFICIAL (thunk) = 1; /* So that finish_file can write out any thunks that need to be: */ pushdecl_top_level (thunk); } return thunk; } +/* Emit the definition of a C++ multiple inheritance vtable thunk. */ + void emit_thunk (thunk_fndecl) - tree thunk_fndecl; + tree thunk_fndecl; { - rtx insns; - char *fnname; - char buffer[250]; - tree argp; - struct args_size stack_args_size; tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0); int delta = THUNK_DELTA (thunk_fndecl); - int tem; - int failure = 0; - int current_call_is_indirect = 0; /* needed for HPPA FUNCTION_ARG */ - - /* Used to remember which regs we need to emit a USE rtx for. */ - rtx need_use[FIRST_PSEUDO_REGISTER]; - int need_use_count = 0; - - /* rtx for the 'this' parameter. */ - rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx; - - char *(*save_decl_printable_name) () = decl_printable_name; - /* Data on reg parms scanned so far. */ - CUMULATIVE_ARGS args_so_far; if (TREE_ASM_WRITTEN (thunk_fndecl)) return; TREE_ASM_WRITTEN (thunk_fndecl) = 1; - if (TREE_PUBLIC (function)) - { - TREE_PUBLIC (thunk_fndecl) = 1; - if (DECL_EXTERNAL (function)) - { - DECL_EXTERNAL (thunk_fndecl) = 1; - assemble_external (thunk_fndecl); - return; - } - } + TREE_ADDRESSABLE (function) = 1; + mark_used (function); - decl_printable_name = thunk_printable_name; if (current_function_decl) abort (); - current_function_decl = thunk_fndecl; - init_function_start (thunk_fndecl, input_filename, lineno); - pushlevel (0); - expand_start_bindings (1); - - /* Start updating where the next arg would go. */ - INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX); - stack_args_size.constant = 0; - stack_args_size.var = 0; - /* SETUP for possible structure return address FIXME */ - - /* Now look through all the parameters, make sure that we - don't clobber any registers used for parameters. - Also, pick up an rtx for the first "this" parameter. */ - for (argp = TYPE_ARG_TYPES (TREE_TYPE (function)); - argp != NULL_TREE; - argp = TREE_CHAIN (argp)) - - { - tree passed_type = TREE_VALUE (argp); - register rtx entry_parm; - int named = 1; /* FIXME */ - struct args_size stack_offset; - struct args_size arg_size; - - if (passed_type == void_type_node) - break; - - if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST - && contains_placeholder_p (TYPE_SIZE (passed_type))) -#ifdef FUNCTION_ARG_PASS_BY_REFERENCE - || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, - TYPE_MODE (passed_type), - passed_type, named) -#endif - ) - passed_type = build_pointer_type (passed_type); - - entry_parm = FUNCTION_ARG (args_so_far, - TYPE_MODE (passed_type), - passed_type, - named); - if (entry_parm != 0) - need_use[need_use_count++] = entry_parm; - - locate_and_pad_parm (TYPE_MODE (passed_type), passed_type, -#ifdef STACK_PARMS_IN_REG_PARM_AREA - 1, -#else - entry_parm != 0, -#endif - thunk_fndecl, - &stack_args_size, &stack_offset, &arg_size); - -/* REGNO (entry_parm);*/ - if (this_rtx == 0) - { - this_reg_rtx = entry_parm; - if (!entry_parm) - { - rtx offset_rtx = ARGS_SIZE_RTX (stack_offset); - - rtx internal_arg_pointer, stack_parm; - - if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM - || ! (fixed_regs[ARG_POINTER_REGNUM] - || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM))) - internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx); - else - internal_arg_pointer = virtual_incoming_args_rtx; - - if (offset_rtx == const0_rtx) - entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type), - internal_arg_pointer); - else - entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type), - gen_rtx (PLUS, Pmode, - internal_arg_pointer, - offset_rtx)); - } - - this_rtx = entry_parm; - } - - FUNCTION_ARG_ADVANCE (args_so_far, - TYPE_MODE (passed_type), - passed_type, - named); - } - - fixed_this_rtx = plus_constant (this_rtx, delta); - if (this_rtx != fixed_this_rtx) - emit_move_insn (this_rtx, fixed_this_rtx); - - if (this_reg_rtx) - emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx)); - - emit_indirect_jump (XEXP (DECL_RTL (function), 0)); - - while (need_use_count > 0) - emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count])); - - expand_end_bindings (NULL, 1, 0); - poplevel (0, 0, 1); - - /* From now on, allocate rtl in current_obstack, not in saveable_obstack. - Note that that may have been done above, in save_for_inline_copying. - The call to resume_temporary_allocation near the end of this function - goes back to the usual state of affairs. */ - - rtl_in_current_obstack (); - - insns = get_insns (); - - /* Copy any shared structure that should not be shared. */ - - unshare_all_rtl (insns); - - /* Instantiate all virtual registers. */ - - instantiate_virtual_regs (current_function_decl, get_insns ()); - - /* We are no longer anticipating cse in this function, at least. */ - - cse_not_expected = 1; - - /* Now we choose between stupid (pcc-like) register allocation - (if we got the -noreg switch and not -opt) - and smart register allocation. */ - - if (optimize > 0) /* Stupid allocation probably won't work */ - obey_regdecls = 0; /* if optimizations being done. */ - - regclass_init (); - - regclass (insns, max_reg_num ()); - if (obey_regdecls) - { - stupid_life_analysis (insns, max_reg_num (), NULL); - failure = reload (insns, 0, NULL); - } - else - { - /* Do control and data flow analysis, - and write some of the results to dump file. */ - - flow_analysis (insns, max_reg_num (), NULL); - local_alloc (); - failure = global_alloc (NULL); - } - - reload_completed = 1; - -#ifdef LEAF_REGISTERS - leaf_function = 0; - if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ()) - leaf_function = 1; -#endif - - /* If a machine dependent reorganization is needed, call it. */ -#ifdef MACHINE_DEPENDENT_REORG - MACHINE_DEPENDENT_REORG (insns); -#endif - - /* Now turn the rtl into assembler code. */ - - { - char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); - assemble_start_function (thunk_fndecl, fnname); - final (insns, asm_out_file, optimize, 0); - assemble_end_function (thunk_fndecl, fnname); - }; - - exit_rest_of_compilation: - - reload_completed = 0; - /* Cancel the effect of rtl_in_current_obstack. */ + TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL); - resume_temporary_allocation (); + { +#ifdef ASM_OUTPUT_MI_THUNK + char *fnname; + current_function_decl = thunk_fndecl; + /* Make sure we build up its RTL before we go onto the + temporary obstack. */ + make_function_rtl (thunk_fndecl); + temporary_allocation (); + DECL_RESULT (thunk_fndecl) + = build_decl (RESULT_DECL, 0, integer_type_node); + fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); + init_function_start (thunk_fndecl, input_filename, lineno); + current_function_is_thunk = 1; + assemble_start_function (thunk_fndecl, fnname); + ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); + assemble_end_function (thunk_fndecl, fnname); + permanent_allocation (1); + current_function_decl = 0; +#else /* ASM_OUTPUT_MI_THUNK */ + /* If we don't have the necessary macro for efficient thunks, generate a + thunk function that just makes a call to the real function. + Unfortunately, this doesn't work for varargs. */ + + tree a, t; + + if (varargs_function_p (function)) + cp_error ("generic thunk code fails for method `%#D' which uses `...'", + function); + + /* Set up clone argument trees for the thunk. */ + t = NULL_TREE; + for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) + { + tree x = copy_node (a); + TREE_CHAIN (x) = t; + DECL_CONTEXT (x) = thunk_fndecl; + t = x; + } + a = nreverse (t); + DECL_ARGUMENTS (thunk_fndecl) = a; + DECL_RESULT (thunk_fndecl) = NULL_TREE; + DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function); + copy_lang_decl (thunk_fndecl); + DECL_INTERFACE_KNOWN (thunk_fndecl) = 1; + DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1; + + start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1); + store_parm_decls (); + current_function_is_thunk = 1; + + /* Build up the call to the real function. */ + t = build_int_2 (delta, -1 * (delta < 0)); + TREE_TYPE (t) = signed_type (sizetype); + t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t)); + t = expr_tree_cons (NULL_TREE, t, NULL_TREE); + for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) + t = expr_tree_cons (NULL_TREE, a, t); + t = nreverse (t); + t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t); + c_expand_return (t); + + finish_function (lineno, 0, 0); + + /* Don't let the backend defer this function. */ + if (DECL_DEFER_OUTPUT (thunk_fndecl)) + { + output_inline_function (thunk_fndecl); + permanent_allocation (1); + } +#endif /* ASM_OUTPUT_MI_THUNK */ + } - decl_printable_name = save_decl_printable_name; - current_function_decl = 0; + TREE_SET_CODE (thunk_fndecl, THUNK_DECL); } /* Code for synthesizing methods which have default semantics defined. */ /* For the anonymous union in TYPE, return the member that is at least as large as the rest of the members, so we can copy it. */ + static tree largest_union_member (type) tree type; @@ -2064,7 +2140,8 @@ largest_union_member (type) } /* Generate code for default X(X&) constructor. */ -void + +static void do_build_copy_constructor (fndecl) tree fndecl; { @@ -2078,9 +2155,13 @@ do_build_copy_constructor (fndecl) parm = TREE_CHAIN (parm); parm = convert_from_reference (parm); - if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) + if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) + && is_empty_class (current_class_type)) + /* Don't copy the padding byte; it might not have been allocated + if *this is a base subobject. */; + else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { - t = build (INIT_EXPR, void_type_node, C_C_D, parm); + t = build (INIT_EXPR, void_type_node, current_class_ref, parm); TREE_SIDE_EFFECTS (t) = 1; cplus_expand_expr_stmt (t); } @@ -2099,8 +2180,12 @@ do_build_copy_constructor (fndecl) (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); - current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), - p, current_base_init_list); + + if (p == error_mark_node) + cp_error ("in default copy constructor"); + else + current_base_init_list = tree_cons (basetype, + p, current_base_init_list); } for (i = 0; i < n_bases; ++i) @@ -2113,17 +2198,25 @@ do_build_copy_constructor (fndecl) p = convert_to_reference (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); - p = convert_from_reference (p); - current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), - p, current_base_init_list); + + 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); + } } for (; fields; fields = TREE_CHAIN (fields)) { - tree name, init, t; + tree init, t; tree field = fields; if (TREE_CODE (field) != FIELD_DECL) continue; + + init = parm; if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) @@ -2136,14 +2229,22 @@ do_build_copy_constructor (fndecl) continue; } else if ((t = TREE_TYPE (field)) != NULL_TREE - && TREE_CODE (t) == UNION_TYPE - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)) + && ANON_UNION_TYPE_P (t) && TYPE_FIELDS (t) != NULL_TREE) - field = largest_union_member (t); + { + do + { + init = build (COMPONENT_REF, t, init, field); + field = largest_union_member (t); + } + while ((t = TREE_TYPE (field)) != NULL_TREE + && ANON_UNION_TYPE_P (t) + && TYPE_FIELDS (t) != NULL_TREE); + } else continue; - init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); + init = build (COMPONENT_REF, TREE_TYPE (field), init, field); init = build_tree_list (NULL_TREE, init); current_member_init_list @@ -2157,7 +2258,7 @@ do_build_copy_constructor (fndecl) pop_momentary (); } -void +static void do_build_assign_ref (fndecl) tree fndecl; { @@ -2168,9 +2269,13 @@ do_build_assign_ref (fndecl) parm = convert_from_reference (parm); - if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) + if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) + && is_empty_class (current_class_type)) + /* Don't copy the padding byte; it might not have been allocated + if *this is a base subobject. */; + else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { - tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm); + tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm); TREE_SIDE_EFFECTS (t) = 1; cplus_expand_expr_stmt (t); } @@ -2184,17 +2289,13 @@ do_build_assign_ref (fndecl) for (i = 0; i < n_bases; ++i) { tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); - if (TYPE_HAS_ASSIGN_REF (basetype)) - { - tree p = convert_to_reference - (build_reference_type (basetype), parm, - CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); - p = convert_from_reference (p); - p = build_member_call (TYPE_NESTED_NAME (basetype), - ansi_opname [MODIFY_EXPR], - build_tree_list (NULL_TREE, p)); - expand_expr_stmt (p); - } + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); + p = convert_from_reference (p); + p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], + build_expr_list (NULL_TREE, p)); + expand_expr_stmt (p); } for (; fields; fields = TREE_CHAIN (fields)) { @@ -2203,6 +2304,27 @@ do_build_assign_ref (fndecl) if (TREE_CODE (field) != FIELD_DECL) continue; + + if (TREE_READONLY (field)) + { + if (DECL_NAME (field)) + cp_error ("non-static const member `%#D', can't use default assignment operator", field); + else + cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type); + continue; + } + else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) + { + if (DECL_NAME (field)) + cp_error ("non-static reference member `%#D', can't use default assignment operator", field); + else + cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type); + continue; + } + + comp = current_class_ref; + init = parm; + if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) @@ -2215,42 +2337,49 @@ do_build_assign_ref (fndecl) continue; } else if ((t = TREE_TYPE (field)) != NULL_TREE - && TREE_CODE (t) == UNION_TYPE - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)) + && ANON_UNION_TYPE_P (t) && TYPE_FIELDS (t) != NULL_TREE) - field = largest_union_member (t); + { + do + { + comp = build (COMPONENT_REF, t, comp, field); + init = build (COMPONENT_REF, t, init, field); + field = largest_union_member (t); + } + while ((t = TREE_TYPE (field)) != NULL_TREE + && ANON_UNION_TYPE_P (t) + && TYPE_FIELDS (t) != NULL_TREE); + } else continue; - comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field); - init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); + comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); + init = build (COMPONENT_REF, TREE_TYPE (field), init, field); expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); } } - c_expand_return (C_C_D); + c_expand_return (current_class_ref); pop_momentary (); } -void push_cp_function_context (); -void pop_cp_function_context (); - void synthesize_method (fndecl) tree fndecl; { int nested = (current_function_decl != NULL_TREE); - tree context = decl_function_context (fndecl); - char *f = input_filename; - tree base = DECL_CLASS_CONTEXT (fndecl); + tree context = hack_decl_function_context (fndecl); - if (nested) + if (at_eof) + import_export_decl (fndecl); + + if (! context) + push_to_top_level (); + else if (nested) push_cp_function_context (context); - input_filename = DECL_SOURCE_FILE (fndecl); - interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base); - interface_only = CLASSTYPE_INTERFACE_ONLY (base); - start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1); + interface_unknown = 1; + start_function (NULL_TREE, fndecl, NULL_TREE, 1); store_parm_decls (); if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) @@ -2270,18 +2399,9 @@ synthesize_method (fndecl) finish_function (lineno, 0, nested); - /* Do we really *want* to inline this function? */ - if (DECL_INLINE (fndecl)) - { - /* Turn off DECL_INLINE for the moment so function_cannot_inline_p - will check our size. */ - DECL_INLINE (fndecl) = 0; - if (function_cannot_inline_p (fndecl) == 0) - DECL_INLINE (fndecl) = 1; - } - - input_filename = f; extract_interface_info (); - if (nested) + if (! context) + pop_from_top_level (); + else if (nested) pop_cp_function_context (context); } diff --git a/contrib/gcc/cp/mpw-config.in b/contrib/gcc/cp/mpw-config.in new file mode 100644 index 0000000..88dd85f --- /dev/null +++ b/contrib/gcc/cp/mpw-config.in @@ -0,0 +1,11 @@ +# Configuration fragment for G++. +# Most of the real configuration work happens in the main GCC configure. + +# We need to join some lines in the Makefile.in before the sed +# process will work properly. The funky little sed script works by +# recognizing lines with a trailing '$@ \', adding the next line to +# its "pattern space", editing out the backslash and line, then +# putting the result out. + +sed -e '/$@ \\/{N;s/$@ \\./$@ /;P;D;}' \Option-d + "{srcdir}"Makefile.in >"{o}"hacked_Makefile.in diff --git a/contrib/gcc/cp/mpw-make.sed b/contrib/gcc/cp/mpw-make.sed new file mode 100644 index 0000000..120b5a1 --- /dev/null +++ b/contrib/gcc/cp/mpw-make.sed @@ -0,0 +1,112 @@ +# Sed commands to finish translating the G++ Unix makefile into MPW syntax. + +# Remove control-Ls, they upset MPW make. +s/ //g + +# Remove references to always-empty variables used to mark things. +/CYGNUS-LOCAL-/s/{CYGNUS-LOCAL-[a-z0-9]*}//g + +# Add a bunch of definitions, mostly empty. +/^# Variables that exist for you to override.$/a\ +\ +xmake_file = \ +tmake_file = \ +build_xm_file = \ +MALLOC = \ +MD_DEPS = \ +REAL_H = \ +HOST_CC_LD = {CC_LD}\ +ALL_CCLDFLAGS = \ +HOST_CCLDFLAGS = \ +CONFIG_H = \ +LIBDEPS = \ + +# The "target" variable is special to MPW make, avoid it. +/{target}/s/{target}/{target_canonical}/g + +# Suppress the suppression of smart makes. +/^\.y\.c/d + +# Whack out "..." assignments. +/\.\.\./s/^\([a-z_]*= \.\.\.\)/#\1/ + +# Previous edits go a little overboard, undo. +/^objext = /s/"{o}"// + +# Always link in low-level MPW functions. +/^LIBDEPS=/s/$/ ::strerror.c.o ::mpwlib.c.o/ +/{CLIB}/s/{CLIB}/ ::strerror.c.o ::mpwlib.c.o {CLIB}/ + +# Don't get tricky about finding various .o file, point at dir above. +/^SUBDIR_OBSTACK/s/`.*`/::obstack.c.o/ +/^SUBDIR_USE_ALLOCA/s/`.*`/::alloca.c.o/ +/^SUBDIR_MALLOC/s/`.*`// + +# Point includes at parent directly correctly. +/^INCLUDES = /s/:\./::/g +/^INCLUDES = /s/"{srcdir}"\.\./"{topsrcdir}"gcc:/g +/^INCLUDES = /s,"{srcdir}"/\.\.,"{topsrcdir}"gcc:,g +/^INCLUDES = /s,"{srcdir}":config,"{topsrcdir}"gcc:config:,g + +# Add the special MPW include dirs. +/^INCLUDES = /s/$/ -i "{topsrcdir}"include:mpw: -i :::extra-include:/ + +# A nasty hack to reduce confusion. +/true/s/ ; @true$// + +# (should be in common translation?) +/{CC_LD} /s/$/ {EXTRALIBS}/ + +# Don't use general compiler flags (which may include definitions +# and other compiler-only bits) with linking commands. +/{CC_LD} /s/ALL_CFLAGS/ALL_CCLDFLAGS/ + +# Whack out build rules that are not useful. +/^Makefile \\Option-f /,/^$/d +/^config.status \\Option-f /,/^$/d +# (Note that MPW make is not case sensitive, and so this name +# is considered the same as "md_file".) +/^{MD_FILE} \\Option-f/,/^$/d + +# Depending on config.status is not useful for us. +/config.status/s/ config.status// + +# Repeat of stuff from generic edit. +/{s}/s/"{s}""{s}"/"{s}"/g +/{s}/s/"{s}""{srcdir}"/"{s}"/g +/{s}/s/"{srcdir}""{s}"/"{s}"/g + +# Fix references to C frontend files in main dir. +/::c-/s/"{o}"::c-/"{o}":c-/g + +# Fix pathnames to generated files in the objdir. +/parse/s/"{s}"parse\.\([chy]\)/"{o}"parse.\1/g +/parse/s/^parse\.\([chy]\)/"{o}"parse.\1/ +/y.tab.c/s/"{s}"y\.tab\.c/"{o}"y.tab.c/g +/y.tab.c/s/^y\.tab\.c/"{o}"y.tab.c/ +/y.tab.h/s/"{s}"y\.tab\.h/"{o}"y.tab.h/g +/y.tab.h/s/^y\.tab\.h/"{o}"y.tab.h/ + +# Put in the definition of YYEMPTY directly. +/grep/s/grep .* >>/Echo '#define YYEMPTY -1' >>/ + +# If the dates are wrong, then this tries to run gperf, which we don't +# really want. +/^"{srcdir}"hash.h/,/hash.h$/d + +# Sed the object file list instead of using cat (meow). +/cat/s/`cat /`sed -e 's,:,::,g' -e 's,{objext},.o,g' / + +# Simplify dependencies of generated parser files. +/^{PARSE_C}/s/^/#/ +/^stamp-parse/s/^stamp-parse/{PARSE_C}/ + +# Fix the compile line for the generated parser. +/{CC} -c/,/echo {PARSE_C}/c\ + {CC} @DASH_C_FLAG@ {ALL_CFLAGS} {ALL_CPPFLAGS} {INCLUDES} {BIG_SWITCHFLAG} "{o}"parse.c -o "{o}"parse.c.o\ + +# Change all Rez commands to use mac-gcc.r. +/{REZ}/s/"{s}"[-a-zA-Z{}]*\.r/"{topsrcdir}"gcc:mac-gcc.r/ + +# Remove pathname junk from the container name. +/{REZ}/s/'"'::cc1plus'"'/'"'cc1plus'"'/ diff --git a/contrib/gcc/cp/new.cc b/contrib/gcc/cp/new.cc new file mode 100644 index 0000000..28187a4 --- /dev/null +++ b/contrib/gcc/cp/new.cc @@ -0,0 +1,42 @@ +// Implementation file for the -*- C++ -*- dynamic memory management header. +// Copyright (C) 1996 Free Software Foundation + +// 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. + +// 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. + +#pragma implementation "new" +#include "new" + +const std::nothrow_t std::nothrow = { }; + +using std::new_handler; +new_handler __new_handler; + +new_handler +set_new_handler (new_handler handler) +{ + new_handler prev_handler = __new_handler; + __new_handler = handler; + return prev_handler; +} diff --git a/contrib/gcc/cp/new1.cc b/contrib/gcc/cp/new1.cc new file mode 100644 index 0000000..5bb85c9 --- /dev/null +++ b/contrib/gcc/cp/new1.cc @@ -0,0 +1,89 @@ +// Support routines for the -*- C++ -*- dynamic memory management. +// Copyright (C) 1997 Free Software Foundation + +// 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. + +// 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. + +#include "new" +using std::new_handler; +using std::bad_alloc; + +extern "C" void *malloc (size_t); +extern new_handler __new_handler; + +#define WEAK(x) \ + x __attribute__ ((weak)); \ + x + +#ifdef L_op_newnt +WEAK (void * operator new (size_t sz, const std::nothrow_t&) throw()) +{ + void *p; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + new_handler handler = __new_handler; + if (! handler) + return 0; + try + { + handler (); + } + catch (bad_alloc &) + { + return 0; + } + + p = (void *) malloc (sz); + } + + return p; +} +#endif + +#ifdef L_op_new +WEAK (void * operator new (size_t sz) throw (std::bad_alloc)) +{ + void *p; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + new_handler handler = __new_handler; + if (! handler) + throw bad_alloc (); + handler (); + p = (void *) malloc (sz); + } + + return p; +} +#endif diff --git a/contrib/gcc/cp/new2.cc b/contrib/gcc/cp/new2.cc new file mode 100644 index 0000000..0be1c0d --- /dev/null +++ b/contrib/gcc/cp/new2.cc @@ -0,0 +1,80 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997 Free Software Foundation + +// 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. + +// 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. + +#include "new" + +extern "C" void free (void *); + +#define WEAK(x) \ + x __attribute__ ((weak)); \ + x + +#ifdef L_op_vnew +WEAK(void * operator new[] (size_t sz) throw (std::bad_alloc)) +{ + return ::operator new(sz); +} +#endif + +#ifdef L_op_vnewnt +WEAK(void *operator new[] (size_t sz, const std::nothrow_t& nothrow) throw()) +{ + return ::operator new(sz, nothrow); +} +#endif + +#ifdef L_op_delete +WEAK (void operator delete (void *ptr) throw ()) +{ + if (ptr) + free (ptr); +} +#endif + +#ifdef L_op_vdel +WEAK (void operator delete[] (void *ptr) throw ()) +{ + if (ptr) + free (ptr); +} +#endif + +#ifdef L_op_delnt +WEAK (void operator delete (void *ptr, const std::nothrow_t&) throw ()) +{ + if (ptr) + free (ptr); +} +#endif + +#ifdef L_op_vdelnt +WEAK (void operator delete[] (void *ptr, const std::nothrow_t&) throw ()) +{ + if (ptr) + free (ptr); +} +#endif diff --git a/contrib/gcc/cp/parse.y b/contrib/gcc/cp/parse.y index fd034af..279cec3 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, 1989, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 89, 93, 94, 95, 1996 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -32,8 +32,7 @@ Boston, MA 02111-1307, USA. */ #include "config.h" -#include -#include +#include "system.h" #include "tree.h" #include "input.h" @@ -41,6 +40,8 @@ Boston, MA 02111-1307, USA. */ #include "lex.h" #include "cp-tree.h" #include "output.h" +#include "except.h" +#include "toplev.h" /* Since parsers are distinct for each language, put the language string definition here. (fnf) */ @@ -49,18 +50,7 @@ char *language_string = "GNU C++"; extern tree void_list_node; extern struct obstack permanent_obstack; -#ifndef errno -extern int errno; -#endif - extern int end_of_file; -extern int current_class_depth; - -/* FSF LOCAL dje prefix attributes */ -extern tree strip_attrs PROTO((tree)); -/* END FSF LOCAL */ - -void yyerror (); /* Like YYERROR but do call yyerror. */ #define YYERROR1 { yyerror ("syntax error"); YYERROR; } @@ -72,12 +62,12 @@ void yyerror (); error message if the user supplies an empty conditional expression. */ static char *cond_stmt_keyword; +static tree empty_parms PROTO((void)); + /* Nonzero if we have an `extern "C"' acting as an extern specifier. */ int have_extern_spec; int used_extern_spec; -void yyhook (); - /* Cons up an empty parameter list. */ #ifdef __GNUC__ __inline @@ -87,17 +77,19 @@ empty_parms () { tree parms; - if (strict_prototype) + if (strict_prototype + || current_class_type != NULL) parms = void_list_node; else parms = NULL_TREE; return parms; } + %} %start program -%union {long itype; tree ttype; char *strtype; enum tree_code code; } +%union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; } /* All identifiers that are not reserved words and are not declared typedefs in the current block */ @@ -107,6 +99,10 @@ empty_parms () In some contexts, they are treated just like IDENTIFIER, but they can also serve as typespecs in declarations. */ %token TYPENAME +%token SELFNAME + +/* A template function. */ +%token PFUNCNAME /* Reserved words that specify storage class. yylval contains an IDENTIFIER_NODE which indicates which one. */ @@ -118,7 +114,7 @@ empty_parms () /* Reserved words that qualify type: "const" or "volatile". yylval contains an IDENTIFIER_NODE which indicates which one. */ -%token TYPE_QUAL +%token CV_QUALIFIER /* Character or numeric constants. yylval is the node for the constant. */ @@ -132,16 +128,17 @@ empty_parms () %token ELLIPSIS /* the reserved words */ -/* SCO include files test "ASM", so use something else. */ +/* 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 GCC_ASM_KEYWORD TYPEOF ALIGNOF +%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF %token SIGOF %token ATTRIBUTE EXTENSION LABEL +%token REALPART IMAGPART /* the reserved words... C++ extensions */ %token AGGR -%token VISSPEC -%token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE +%token VISSPEC +%token DELETE NEW THIS OPERATOR CXX_TRUE CXX_FALSE %token NAMESPACE TYPENAME_KEYWORD USING %token LEFT_RIGHT TEMPLATE %token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST @@ -159,7 +156,7 @@ empty_parms () %nonassoc IF %nonassoc ELSE -%left IDENTIFIER TYPENAME PTYPENAME SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD +%left IDENTIFIER PFUNCNAME TYPENAME SELFNAME PTYPENAME SCSPEC TYPESPEC CV_QUALIFIER ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD %left '{' ',' ';' @@ -190,14 +187,15 @@ empty_parms () %type unop %type identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist -%type paren_expr_or_null nontrivial_exprlist +%type PFUNCNAME maybe_identifier +%type paren_expr_or_null nontrivial_exprlist SELFNAME %type expr_no_commas cast_expr unary_expr primary string STRING -%type typed_declspecs reserved_declspecs boolean.literal -%type typed_typespecs reserved_typespecquals -%type declmods typespec typespecqual_reserved -%type SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual +%type reserved_declspecs boolean.literal +%type reserved_typespecquals +%type declmods +%type SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier %type initdecls notype_initdecls initdcl /* C++ modification */ -%type init initlist maybeasm maybe_init +%type init initlist maybeasm maybe_init defarg defarg1 %type asm_operands nonnull_asm_operands asm_operand asm_clobbers %type maybe_attribute attributes attribute attribute_list attrib %type any_word @@ -207,77 +205,84 @@ empty_parms () %type declarator notype_declarator after_type_declarator %type direct_notype_declarator direct_after_type_declarator -%type structsp opt.component_decl_list component_decl_list +%type opt.component_decl_list component_decl_list %type component_decl component_decl_1 components notype_components -%type component_declarator component_declarator0 +%type component_declarator component_declarator0 self_reference %type notype_component_declarator notype_component_declarator0 %type after_type_component_declarator after_type_component_declarator0 %type enumlist enumerator -%type type_id absdcl type_quals +%type absdcl cv_qualifiers %type direct_abstract_declarator conversion_declarator -%type new_type_id new_declarator direct_new_declarator -%type xexpr parmlist parms parm bad_parm full_parm +%type new_declarator direct_new_declarator +%type xexpr parmlist parms bad_parm %type identifiers_or_typenames %type fcast_or_absdcl regcast_or_absdcl %type expr_or_declarator complex_notype_declarator %type notype_unqualified_id unqualified_id qualified_id +%type template_id do_id object_template_id notype_template_declarator %type overqualified_id notype_qualified_id any_id %type complex_direct_notype_declarator functional_cast -%type named_parm complex_parmlist typed_declspecs1 parms_comma +%type complex_parmlist parms_comma +%type namespace_qualifier namespace_using_decl + +%type type_id new_type_id typed_typespecs typespec typed_declspecs +%type typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers +%type structsp typespecqual_reserved parm named_parm full_parm /* C++ extensions */ -%token TYPENAME_ELLIPSIS PTYPENAME +%token PTYPENAME %token PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL -%token PRE_PARSED_CLASS_DECL -%type fn.def1 /* Not really! */ -%type fn.def2 return_id +%token PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER +%type component_constructor_declarator +%type fn.def2 return_id fn.defpen constructor_declarator %type ctor_initializer_opt %type named_class_head named_class_head_sans_basetype %type named_complex_class_head_sans_basetype %type unnamed_class_head %type class_head base_class_list -%type base_class_access_list +%type base_class_access_list %type base_class maybe_base_class_list base_class.1 %type exception_specification_opt ansi_raise_identifier ansi_raise_identifiers %type operator_name %type object aggr -%type new delete +%type new delete .begin_new_placement /* %type primary_no_id */ %type nonmomentary_expr maybe_parmlist -%type initdcl0 notype_initdcl0 member_init_list +%type initdcl0 notype_initdcl0 member_init_list initdcl0_innards %type template_header template_parm_list template_parm -%type template_type_parm -%type template_type template_arg_list template_arg -%type template_instantiation template_type_name tmpl.2 -%type template_instantiate_once template_instantiate_some -%type fn_tmpl_end -/* %type try_for_typename */ +%type template_type_parm template_template_parm +%type template_close_bracket +%type template_type template_arg_list template_arg_list_opt +%type template_arg %type condition xcond paren_cond_or_null %type type_name nested_name_specifier nested_type ptr_to_mem -%type qualified_type_name complete_type_name notype_identifier +%type complete_type_name notype_identifier nonnested_type %type complex_type_name nested_name_specifier_1 -%type nomods_initdecls nomods_initdcl0 -%type new_initializer new_placement specialization type_specifier_seq -%type using_decl .poplevel - -/* in order to recognize aggr tags as defining and thus shadowing. */ +%type new_initializer new_placement +%type using_decl +%type typename_sub typename_sub0 typename_sub1 typename_sub2 +%type explicit_template_type +/* in order to recognize aggr tags as defining and thus shadowing. */ %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN -%type named_class_head_sans_basetype_defn +%type named_class_head_sans_basetype_defn %type identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN +%type self_template_type + %token NSNAME %type NSNAME /* Used in lex.c for parsing pragmas. */ %token END_OF_LINE -/* lex.c and pt.c depends on this being the last token. Define +/* lex.c and pt.c depend on this being the last token. Define any new tokens before this one! */ %token END_OF_SAVED_INPUT %{ /* List of types and structure classes of the current declaration. */ static tree current_declspecs; + /* List of prefix attributes in effect. Prefix attributes are parsed by the reserved_declspecs and declmods rules. They create a list that contains *both* declspecs and attrs. */ @@ -291,28 +296,51 @@ static tree current_aggr; /* Tell yyparse how to print a token's value, if yydebug is set. */ #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL) -extern void yyprint (); +extern void yyprint PROTO((FILE *, int, YYSTYPE)); extern tree combine_strings PROTO((tree)); + +static int +parse_decl(declarator, specs_attrs, attributes, initialized, decl) + tree declarator; + tree specs_attrs; + tree attributes; + int initialized; + tree* decl; +{ + int sm; + + split_specs_attrs (specs_attrs, ¤t_declspecs, &prefix_attributes); + if (current_declspecs + && TREE_CODE (current_declspecs) != TREE_LIST) + current_declspecs = get_decl_list (current_declspecs); + if (have_extern_spec && !used_extern_spec) + { + current_declspecs = decl_tree_cons (NULL_TREE, + get_identifier ("extern"), + current_declspecs); + used_extern_spec = 1; + } + sm = suspend_momentary (); + *decl = start_decl (declarator, current_declspecs, initialized, + attributes, prefix_attributes); + return sm; +} %} %% -program: /* empty */ +program: + /* empty */ | extdefs - { - /* In case there were missing closebraces, - get us back to the global binding level. */ - while (! global_bindings_p ()) - poplevel (0, 0, 0); - finish_file (); - } + { finish_translation_unit (); } ; /* the reason for the strange actions in this rule is so that notype_initdecls when reached via datadef - can find a valid list of type and sc specs in $0. */ + can find a valid list of type and sc specs in $0. */ extdefs: - { $$ = NULL_TREE; } lang_extdef + { $$ = NULL_TREE; } + lang_extdef { $$ = NULL_TREE; } | extdefs lang_extdef { $$ = NULL_TREE; } @@ -332,32 +360,36 @@ extdefs_opt: { have_extern_spec = 0; } ; +extension: + EXTENSION + { $$ = pedantic; + pedantic = 0; } + ; + asm_keyword: ASM_KEYWORD - | GCC_ASM_KEYWORD ; lang_extdef: - { if (pending_lang_change) do_pending_lang_change(); } + { if (pending_lang_change) do_pending_lang_change(); } extdef - { if (! toplevel_bindings_p () && ! pseudo_global_level_p()) - pop_everything (); } + { if (! toplevel_bindings_p () && ! pseudo_global_level_p()) + pop_everything (); } ; extdef: - fndef + fndef eat_saved_input { if (pending_inlines) do_pending_inlines (); } | datadef { if (pending_inlines) do_pending_inlines (); } | template_def { if (pending_inlines) do_pending_inlines (); } - | overloaddef | asm_keyword '(' string ')' ';' { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); assemble_asm ($3); } | extern_lang_string '{' extdefs_opt '}' { pop_lang_context (); } - | extern_lang_string .hush_warning fndef .warning_ok + | 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 datadef .warning_ok @@ -371,12 +403,24 @@ extdef: { push_namespace (NULL_TREE); } extdefs_opt '}' { pop_namespace (); } - | NAMESPACE identifier '=' any_id ';' - { do_namespace_alias ($2, $4); } + | namespace_alias | using_decl ';' { do_toplevel_using_decl ($1); } - | USING NAMESPACE any_id ';' - { do_using_directive ($3); } + | using_directive + | extension extdef + { pedantic = $1; } + ; + +namespace_alias: + NAMESPACE identifier '=' + { begin_only_namespace_names (); } + any_id ';' + { + end_only_namespace_names (); + if (lastiddecl) + $5 = lastiddecl; + do_namespace_alias ($2, $5); + } ; using_decl: @@ -388,6 +432,45 @@ using_decl: { $$ = $3; } ; +namespace_using_decl: + USING namespace_qualifier identifier + { $$ = build_parse_node (SCOPE_REF, $2, $3); } + | USING global_scope identifier + { $$ = build_parse_node (SCOPE_REF, global_namespace, $3); } + | USING global_scope namespace_qualifier identifier + { $$ = build_parse_node (SCOPE_REF, $3, $4); } + ; + +using_directive: + USING NAMESPACE + { begin_only_namespace_names (); } + any_id ';' + { + end_only_namespace_names (); + /* If no declaration was found, the using-directive is + invalid. Since that was not reported, we need the + identifier for the error message. */ + if (TREE_CODE ($4) == IDENTIFIER_NODE && lastiddecl) + $4 = lastiddecl; + do_using_directive ($4); + } + ; + +namespace_qualifier: + NSNAME SCOPE + { + if (TREE_CODE ($$) == IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$; + } + | namespace_qualifier NSNAME SCOPE + { + $$ = $2; + if (TREE_CODE ($$) == IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$; + } + any_id: unqualified_id | qualified_id @@ -411,6 +494,9 @@ template_header: { begin_template_parm_list (); } template_parm_list '>' { $$ = end_template_parm_list ($4); } + | TEMPLATE '<' '>' + { begin_specialization(); + $$ = NULL_TREE; } ; template_parm_list: @@ -420,22 +506,22 @@ template_parm_list: { $$ = process_template_parm ($1, $3); } ; +maybe_identifier: + identifier + { $$ = $1; } + | /* empty */ + { $$ = NULL_TREE; } + template_type_parm: - aggr - { - $$ = build_tree_list ($1, NULL_TREE); - ttpa: - if (TREE_PURPOSE ($$) == signature_type_node) - sorry ("signature as template type parameter"); - else if (TREE_PURPOSE ($$) != class_type_node) - pedwarn ("template type parameters must use the keyword `class'"); - } - | aggr identifier - { $$ = build_tree_list ($1, $2); goto ttpa; } - | TYPENAME_KEYWORD - { $$ = build_tree_list (class_type_node, NULL_TREE); } - | TYPENAME_KEYWORD identifier - { $$ = build_tree_list (class_type_node, $2); } + aggr maybe_identifier + { $$ = finish_template_type_parm ($1, $2); } + | TYPENAME_KEYWORD maybe_identifier + { $$ = finish_template_type_parm (class_type_node, $2); } + ; + +template_template_parm: + template_header aggr maybe_identifier + { $$ = finish_template_template_parm ($2, $3); } ; template_parm: @@ -447,169 +533,65 @@ template_parm: their match before considering them nameless parameter declarations. */ template_type_parm - { $$ = build_tree_list (NULL_TREE, $$); } - | template_type_parm '=' typespec - { $$ = build_tree_list ($3, $$); } - | full_parm - ; - -overloaddef: - OVERLOAD ov_identifiers ';' - { warning ("use of `overload' is an anachronism"); } - ; - -ov_identifiers: IDENTIFIER - { declare_overloaded ($1); } - | ov_identifiers ',' IDENTIFIER - { declare_overloaded ($3); } - ; - -template_def: - /* Class template declarations go here; they aren't normal class - declarations, because we can't process the bodies yet. */ - template_header named_class_head_sans_basetype '{' - { yychar = '{'; goto template1; } - ';' - | template_header named_class_head_sans_basetype_defn '{' - { yychar = '{'; goto template1; } - ';' - | template_header named_class_head_sans_basetype ':' - { yychar = ':'; goto template1; } - ';' - | template_header named_class_head_sans_basetype_defn ':' - { - yychar = ':'; - template1: - if (current_aggr == signature_type_node) - sorry ("template type defining a signature"); - /* Maybe pedantic warning for union? - How about an enum? :-) */ - end_template_decl ($1, $2, current_aggr, 1); - reinit_parse_for_template (yychar, $1, $2); - yychar = YYEMPTY; - } - ';' - | template_header named_class_head_sans_basetype ';' - { - end_template_decl ($1, $2, current_aggr, 0); - /* declare $2 as template name with $1 parm list */ - } - | template_header named_class_head_sans_basetype_defn ';' - { - end_template_decl ($1, $2, current_aggr, 0); - /* declare $2 as template name with $1 parm list */ - } - | template_header /* notype_initdcl0 ';' */ - notype_declarator exception_specification_opt maybeasm maybe_attribute - fn_tmpl_end + { $$ = build_tree_list (NULL_TREE, $1); } + | template_type_parm '=' type_id + { $$ = build_tree_list (groktypename ($3.t), $1); } + | parm + { $$ = build_tree_list (NULL_TREE, $1.t); } + | parm '=' expr_no_commas %prec ARITHCOMPARE + { $$ = build_tree_list ($3, $1.t); } + | template_template_parm + { $$ = build_tree_list (NULL_TREE, $1); } + | template_template_parm '=' template_arg { - tree d; - int momentary; - int def = ($6 != ';'); - momentary = suspend_momentary (); - d = start_decl ($2, /*current_declspecs*/NULL_TREE, 0, - $3); - cplus_decl_attributes (d, $5, /*prefix_attributes*/NULL_TREE); - cp_finish_decl (d, NULL_TREE, $4, 0, 0); - end_template_decl ($1, d, 0, def); - if (def) - reinit_parse_for_template ((int) $6, $1, d); - resume_momentary (momentary); - } - | template_header typed_declspecs /*initdcl0*/ - declarator exception_specification_opt maybeasm maybe_attribute - fn_tmpl_end - { - tree d, specs, attrs; - int momentary; - int def = ($7 != ';'); - split_specs_attrs ($2, &specs, &attrs); - momentary = suspend_momentary (); - d = start_decl ($3, specs, 0, $4); - cplus_decl_attributes (d, $6, attrs); - cp_finish_decl (d, NULL_TREE, $5, 0, 0); - end_template_decl ($1, d, 0, def); - if (def) + if (TREE_CODE ($3) != TEMPLATE_DECL + && TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM + && TREE_CODE ($3) != TYPE_DECL) { - reinit_parse_for_template ((int) $7, $1, d); - yychar = YYEMPTY; + error ("invalid default template argument"); + $3 = error_mark_node; } - note_list_got_semicolon ($2); - resume_momentary (momentary); - } - | template_header declmods notype_declarator fn_tmpl_end - { - tree d, specs, attrs; - int def = ($4 != ';'); - split_specs_attrs ($2, &specs, &attrs); - d = start_decl ($3, specs, 0, NULL_TREE); - cplus_decl_attributes (d, NULL_TREE, attrs); - cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); - end_template_decl ($1, d, 0, def); - if (def) - reinit_parse_for_template ((int) $4, $1, d); + $$ = build_tree_list ($3, $1); } - /* Try to recover from syntax errors in templates. */ - | template_header error '}' { end_template_decl ($1, 0, 0, 0); } - | template_header error ';' { end_template_decl ($1, 0, 0, 0); } ; -fn_tmpl_end: '{' { $$ = '{'; } - | ':' { $$ = ':'; } - | ';' { $$ = ';'; } - | '=' { $$ = '='; } - | RETURN { $$ = RETURN; } +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 (); + } ; datadef: nomods_initdecls ';' - {} | declmods notype_initdecls ';' {} - /* Normal case to make fast: "const i;". */ - | declmods notype_declarator ';' - { tree d, specs, attrs; - split_specs_attrs ($1, &specs, &attrs); - d = start_decl ($2, specs, 0, NULL_TREE); - cplus_decl_attributes (d, NULL_TREE, attrs); - cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); - } | typed_declspecs initdecls ';' { - note_list_got_semicolon ($$); - } - /* Normal case: make this fast. */ - | typed_declspecs declarator ';' - { tree d, specs, attrs; - split_specs_attrs ($1, &specs, &attrs); - d = start_decl ($2, specs, 0, NULL_TREE); - cplus_decl_attributes (d, NULL_TREE, attrs); - cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); - note_list_got_semicolon ($$); + note_list_got_semicolon ($1.t); } | declmods ';' - { pedwarn ("empty declaration"); } + { pedwarn ("empty declaration"); } | explicit_instantiation ';' | typed_declspecs ';' - { - tree t, attrs; - split_specs_attrs ($1, &t, &attrs); - shadow_tag (t); - if (TREE_CODE (t) == TREE_LIST - && TREE_PURPOSE (t) == NULL_TREE) - { - t = TREE_VALUE (t); - if (IS_AGGR_TYPE (t) - && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t))) - { - if (CLASSTYPE_USE_TEMPLATE (t) == 0) - SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t); - else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t)) - error ("override declaration for already-expanded template"); - } - } - note_list_got_semicolon ($$); - } + { + tree t, attrs; + split_specs_attrs ($1.t, &t, &attrs); + shadow_tag (t); + note_list_got_semicolon ($1.t); + } | error ';' | error '}' | ';' @@ -635,79 +617,108 @@ eat_saved_input: fndef: fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error - { - finish_function (lineno, (int)$3, 0); - if ($$) process_next_inline ($$); - } + { finish_function (lineno, (int)$3, 0); } | fn.def1 maybe_return_init function_try_block - { - if ($$) process_next_inline ($$); + { } + | fn.def1 maybe_return_init error + { } + ; + +constructor_declarator: + nested_name_specifier SELFNAME '(' + { $$ = begin_constructor_declarator ($1, $2); } + parmlist ')' cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($4, $5, $7, $8); } + | nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt + { $$ = begin_constructor_declarator ($1, $2); + $$ = make_call_declarator ($$, empty_parms (), $4, $5); + } + | global_scope nested_name_specifier SELFNAME '(' + { $$ = begin_constructor_declarator ($2, $3); } + parmlist ')' cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($5, $6, $8, $9); } + | global_scope nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt + { $$ = begin_constructor_declarator ($2, $3); + $$ = make_call_declarator ($$, empty_parms (), $5, $6); + } + | nested_name_specifier self_template_type '(' + { $$ = begin_constructor_declarator ($1, $2); } + parmlist ')' cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($4, $5, $7, $8); } + | nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt + { $$ = begin_constructor_declarator ($1, $2); + $$ = make_call_declarator ($$, empty_parms (), $4, $5); + } + | global_scope nested_name_specifier self_template_type '(' + { $$ = begin_constructor_declarator ($2, $3); } + parmlist ')' cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($5, $6, $8, $9); } + | global_scope nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt + { $$ = begin_constructor_declarator ($2, $3); + $$ = make_call_declarator ($$, empty_parms (), $5, $6); } - eat_saved_input - | typed_declspecs declarator error - {} - | declmods notype_declarator error - {} - | notype_declarator error - {} ; fn.def1: - typed_declspecs declarator exception_specification_opt - { tree specs, attrs; - split_specs_attrs ($1, &specs, &attrs); - if (! start_function (specs, $2, $3, attrs, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } - | declmods notype_declarator exception_specification_opt - { tree specs = strip_attrs ($1); - if (! start_function (specs, $2, $3, NULL_TREE, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } - | notype_declarator exception_specification_opt - { if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } - | PRE_PARSED_FUNCTION_DECL - { start_function (NULL_TREE, TREE_VALUE ($$), - NULL_TREE, NULL_TREE, 1); - reinit_parse_for_function (); } + typed_declspecs declarator + { if (!begin_function_definition ($1.t, $2)) + YYERROR1; } + | declmods notype_declarator + { if (!begin_function_definition ($1, $2)) + YYERROR1; } + | notype_declarator + { if (!begin_function_definition (NULL_TREE, $1)) + YYERROR1; } + | declmods constructor_declarator + { if (!begin_function_definition ($1, $2)) + YYERROR1; } + | constructor_declarator + { if (!begin_function_definition (NULL_TREE, $1)) + YYERROR1; } + ; + +component_constructor_declarator: + SELFNAME '(' parmlist ')' cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($1, $3, $5, $6); } + | SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($1, empty_parms (), $3, $4); } + | self_template_type '(' parmlist ')' cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($1, $3, $5, $6); } + | self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt + { $$ = make_call_declarator ($1, empty_parms (), $3, $4); } ; /* more C++ complexity. See component_decl for a comment on the reduce/reduce conflict introduced by these rules. */ fn.def2: - typed_declspecs '(' parmlist ')' type_quals exception_specification_opt + declmods component_constructor_declarator { tree specs = strip_attrs ($1); - $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5); - $$ = start_method (TREE_CHAIN (specs), $$, $6); + $$ = start_method (specs, $2); rest_of_mdef: if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } - | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt - { tree specs = strip_attrs ($1); - $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), - empty_parms (), $3); - $$ = start_method (TREE_CHAIN (specs), $$, $4); - goto rest_of_mdef; - } - | typed_declspecs declarator exception_specification_opt + | component_constructor_declarator + { $$ = start_method (NULL_TREE, $1); goto rest_of_mdef; } + | typed_declspecs declarator + { tree specs = strip_attrs ($1.t); + $$ = start_method (specs, $2); goto rest_of_mdef; } + | declmods notype_declarator { tree specs = strip_attrs ($1); - $$ = start_method (specs, $2, $3); goto rest_of_mdef; } - | declmods notype_declarator exception_specification_opt + $$ = start_method (specs, $2); goto rest_of_mdef; } + | notype_declarator + { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; } + | declmods constructor_declarator { tree specs = strip_attrs ($1); - $$ = start_method (specs, $2, $3); goto rest_of_mdef; } - | notype_declarator exception_specification_opt - { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; } + $$ = start_method (specs, $2); goto rest_of_mdef; } + | constructor_declarator + { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; } ; -return_id: RETURN IDENTIFIER +return_id: + RETURN IDENTIFIER { if (! current_function_parms_stored) store_parm_decls (); @@ -715,7 +726,8 @@ return_id: RETURN IDENTIFIER } ; -return_init: return_id maybe_init +return_init: + return_id maybe_init { store_return_init ($$, $2); } | return_id '(' nonnull_exprlist ')' { store_return_init ($$, $3); } @@ -737,7 +749,7 @@ base_init: ; .set_base_init: - /* empty */ + /* empty */ { if (! current_function_parms_stored) store_parm_decls (); @@ -765,40 +777,39 @@ member_init_list: | member_init_list error ; -member_init: '(' nonnull_exprlist ')' +member_init: + '(' nonnull_exprlist ')' { - if (current_class_name && !flag_traditional) + if (current_class_name) pedwarn ("anachronistic old style base class initializer"); - expand_member_init (C_C_D, NULL_TREE, $2); + expand_member_init (current_class_ref, NULL_TREE, $2); } | LEFT_RIGHT { - if (current_class_name && !flag_traditional) + if (current_class_name) pedwarn ("anachronistic old style base class initializer"); - expand_member_init (C_C_D, NULL_TREE, void_type_node); + expand_member_init (current_class_ref, NULL_TREE, void_type_node); } | notype_identifier '(' nonnull_exprlist ')' - { expand_member_init (C_C_D, $$, $3); } + { expand_member_init (current_class_ref, $1, $3); } | notype_identifier LEFT_RIGHT - { expand_member_init (C_C_D, $$, void_type_node); } - | complete_type_name '(' nonnull_exprlist ')' - { expand_member_init (C_C_D, $$, $3); } - | complete_type_name LEFT_RIGHT - { expand_member_init (C_C_D, $$, void_type_node); } - /* GNU extension */ - | notype_qualified_id '(' nonnull_exprlist ')' - { - do_member_init (OP0 ($1), OP1 ($1), $3); - } - | notype_qualified_id LEFT_RIGHT - { - do_member_init (OP0 ($1), OP1 ($1), void_type_node); - } + { expand_member_init (current_class_ref, $1, void_type_node); } + | nonnested_type '(' nonnull_exprlist ')' + { expand_member_init (current_class_ref, $1, $3); } + | nonnested_type LEFT_RIGHT + { expand_member_init (current_class_ref, $1, void_type_node); } + | typename_sub '(' nonnull_exprlist ')' + { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1), + $3); } + | typename_sub LEFT_RIGHT + { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1), + void_type_node); } ; identifier: IDENTIFIER | TYPENAME + | SELFNAME | PTYPENAME | NSNAME ; @@ -806,7 +817,7 @@ identifier: notype_identifier: IDENTIFIER | PTYPENAME - | NSNAME %prec EMPTY + | NSNAME %prec EMPTY ; identifier_defn: @@ -816,43 +827,90 @@ identifier_defn: ; explicit_instantiation: - TEMPLATE specialization template_instantiation - { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); } - | TEMPLATE typed_declspecs declarator - { tree specs = strip_attrs ($2); - do_function_instantiation (specs, $3, NULL_TREE); } - | TEMPLATE notype_declarator - { do_function_instantiation (NULL_TREE, $2, NULL_TREE); } - | SCSPEC TEMPLATE specialization template_instantiation - { do_type_instantiation ($4 ? $4 : $3, $1); } - | SCSPEC TEMPLATE typed_declspecs declarator - { tree specs = strip_attrs ($3); - do_function_instantiation (specs, $4, $1); } - | SCSPEC TEMPLATE notype_declarator - { do_function_instantiation (NULL_TREE, $3, $1); } - ; + TEMPLATE begin_explicit_instantiation typespec ';' + { do_type_instantiation ($3.t, NULL_TREE); + yyungetc (';', 1); } + end_explicit_instantiation + | TEMPLATE begin_explicit_instantiation typed_declspecs declarator + { tree specs = strip_attrs ($3.t); + do_decl_instantiation (specs, $4, NULL_TREE); } + end_explicit_instantiation + | TEMPLATE begin_explicit_instantiation notype_declarator + { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); } + end_explicit_instantiation + | TEMPLATE begin_explicit_instantiation constructor_declarator + { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); } + end_explicit_instantiation + | SCSPEC TEMPLATE begin_explicit_instantiation typespec ';' + { do_type_instantiation ($4.t, $1); + yyungetc (';', 1); } + end_explicit_instantiation + | SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs + declarator + { tree specs = strip_attrs ($4.t); + do_decl_instantiation (specs, $5, $1); } + end_explicit_instantiation + | SCSPEC TEMPLATE begin_explicit_instantiation notype_declarator + { do_decl_instantiation (NULL_TREE, $4, $1); } + end_explicit_instantiation + | SCSPEC TEMPLATE begin_explicit_instantiation constructor_declarator + { do_decl_instantiation (NULL_TREE, $4, $1); } + end_explicit_instantiation + ; + +begin_explicit_instantiation: + { begin_explicit_instantiation(); } + +end_explicit_instantiation: + { end_explicit_instantiation(); } + +/* The TYPENAME expansions are to deal with use of a template class name as + a template within the class itself, where the template decl is hidden by + a type decl. Got all that? */ template_type: - template_type_name tmpl.2 template_instantiation - { if ($3) $$ = $3; } + PTYPENAME '<' template_arg_list_opt template_close_bracket + { + $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); + if ($$ != error_mark_node) + $$ = TYPE_STUB_DECL ($$); + } + | TYPENAME '<' template_arg_list_opt template_close_bracket + { + $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); + if ($$ != error_mark_node) + $$ = TYPE_STUB_DECL ($$); + } + | self_template_type ; -template_type_name: - PTYPENAME '<' template_arg_list '>' - { $$ = lookup_template_class ($$, $3, NULL_TREE); } - | PTYPENAME '<' '>' - { $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); } - | TYPENAME '<' template_arg_list '>' - { $$ = lookup_template_class ($$, $3, NULL_TREE); } +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 ($$); + } ; -tmpl.2: - /* empty */ %prec EMPTY - { $$ = instantiate_class_template ($0, 1); } +template_close_bracket: + '>' + | RSHIFT + { + /* Handle `Class>' without space in the `>>' */ + pedwarn ("`>>' should be `> >' in template class name"); + yyungetc ('>', 1); + } ; +template_arg_list_opt: + /* empty */ + { $$ = NULL_TREE; } + | template_arg_list + ; + template_arg_list: - template_arg + template_arg { $$ = build_tree_list (NULL_TREE, $$); } | template_arg_list ',' template_arg { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); } @@ -860,77 +918,14 @@ template_arg_list: template_arg: type_id - { $$ = groktypename ($$); } - | expr_no_commas %prec UNARY - ; - -template_instantiate_once: - PRE_PARSED_CLASS_DECL maybe_base_class_list - { - tree t, decl, tmpl; - - tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE ($1)); - t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, $1, $2, 0); - set_current_level_tags_transparency (1); - my_friendly_assert (TREE_CODE (t) == RECORD_TYPE - || TREE_CODE (t) == UNION_TYPE, 257); - $$ = t; - - /* Now, put a copy of the decl in global scope, to avoid - recursive expansion. */ - decl = IDENTIFIER_LOCAL_VALUE ($1); - if (!decl) - decl = IDENTIFIER_CLASS_VALUE ($1); - /* Now, put a copy of the decl in global scope, to avoid - recursive expansion. */ - if (decl) - { - /* Need to copy it to clear the chain pointer, - and need to get it into permanent storage. */ - my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 258); - push_obstacks (&permanent_obstack, &permanent_obstack); - decl = copy_node (decl); - if (DECL_LANG_SPECIFIC (decl)) - copy_lang_decl (decl); - pop_obstacks (); - pushdecl_top_level (decl); - } - /* Kludge; see instantiate_class_template. */ - TYPE_BEING_DEFINED (t) = 0; - } - left_curly opt.component_decl_list '}' - { - tree t = finish_struct ($3, $5, 0); - - pop_obstacks (); - end_template_instantiation ($1); - - repo_template_used (t); - - /* Now go after the methods & class data. */ - instantiate_member_templates ($1); - - pop_tinst_level(); - - CLASSTYPE_GOT_SEMICOLON (t) = 1; - } + { $$ = groktypename ($1.t); } + | PTYPENAME + { $$ = lastiddecl; } + | expr_no_commas %prec ARITHCOMPARE ; -template_instantiation: - /* empty */ - { $$ = NULL_TREE; } - | template_instantiate_once - { $$ = $1; } - ; - -template_instantiate_some: - /* empty */ - { $$ = NULL_TREE; /* never used from here... */} - | template_instantiate_once template_instantiate_some - { $$ = $1; /*???*/ } - ; - -unop: '-' +unop: + '-' { $$ = NEGATE_EXPR; } | '+' { $$ = CONVERT_EXPR; } @@ -942,7 +937,8 @@ unop: '-' { $$ = TRUTH_NOT_EXPR; } ; -expr: nontrivial_exprlist +expr: + nontrivial_exprlist { $$ = build_x_compound_expr ($$); } | expr_no_commas ; @@ -953,7 +949,7 @@ paren_expr_or_null: cond_stmt_keyword); $$ = integer_zero_node; } | '(' expr ')' - { $$ = condition_conversion ($2); } + { $$ = $2; } ; paren_cond_or_null: @@ -962,20 +958,19 @@ paren_cond_or_null: cond_stmt_keyword); $$ = integer_zero_node; } | '(' condition ')' - { $$ = condition_conversion ($2); } + { $$ = $2; } ; xcond: - /* empty */ + /* empty */ { $$ = NULL_TREE; } | condition - { $$ = condition_conversion ($$); } | error { $$ = NULL_TREE; } ; condition: - type_specifier_seq declarator exception_specification_opt maybeasm maybe_attribute '=' + type_specifier_seq declarator maybeasm maybe_attribute '=' { { tree d; for (d = getdecls (); d; d = TREE_CHAIN (d)) @@ -987,17 +982,16 @@ condition: cp_error ("definition of enum `%T' in condition", s); } } - current_declspecs = $1; - $6 = suspend_momentary (); - $$ = start_decl ($2, current_declspecs, 1, $3); - cplus_decl_attributes ($$, $5, - /*prefix_attributes*/ NULL_TREE); + current_declspecs = $1.t; + $5 = suspend_momentary (); + $$ = start_decl ($2, current_declspecs, 1, + $4, /*prefix_attributes*/ NULL_TREE); } - init + init { - cp_finish_decl ($7, $8, $5, 0, LOOKUP_ONLYCONVERTING); - resume_momentary ($6); - $$ = $7; + cp_finish_decl ($6, $7, $4, 1, LOOKUP_ONLYCONVERTING); + resume_momentary ($5); + $$ = convert_from_reference ($6); if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE) cp_error ("definition of array `%#D' in condition", $$); } @@ -1012,45 +1006,39 @@ compstmtend: ; already_scoped_stmt: - '{' compstmtend - { finish_stmt (); } + '{' + { $$ = begin_compound_stmt (1); } + compstmtend + { finish_compound_stmt (1, $2); } | simple_stmt ; nontrivial_exprlist: expr_no_commas ',' expr_no_commas - { $$ = tree_cons (NULL_TREE, $$, - build_tree_list (NULL_TREE, $3)); } + { $$ = expr_tree_cons (NULL_TREE, $$, + build_expr_list (NULL_TREE, $3)); } | expr_no_commas ',' error - { $$ = tree_cons (NULL_TREE, $$, - build_tree_list (NULL_TREE, error_mark_node)); } + { $$ = expr_tree_cons (NULL_TREE, $$, + build_expr_list (NULL_TREE, error_mark_node)); } | nontrivial_exprlist ',' expr_no_commas - { chainon ($$, build_tree_list (NULL_TREE, $3)); } + { chainon ($$, build_expr_list (NULL_TREE, $3)); } | nontrivial_exprlist ',' error - { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); } + { chainon ($$, build_expr_list (NULL_TREE, error_mark_node)); } ; nonnull_exprlist: expr_no_commas - { $$ = build_tree_list (NULL_TREE, $$); } + { $$ = build_expr_list (NULL_TREE, $$); } | nontrivial_exprlist ; unary_expr: - primary %prec UNARY - { -#if 0 - if (TREE_CODE ($$) == TYPE_EXPR) - $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1); -#endif - } + primary %prec UNARY + { $$ = $1; } /* __extension__ turns off -pedantic for following primary. */ - | EXTENSION - { $1 = pedantic; - pedantic = 0; } - cast_expr %prec UNARY - { $$ = $3; + | extension cast_expr %prec UNARY + { $$ = $2; pedantic = $1; } | '*' cast_expr %prec UNARY { $$ = build_x_indirect_ref ($2, "unary *"); } @@ -1059,71 +1047,62 @@ unary_expr: | '~' cast_expr { $$ = build_x_unary_op (BIT_NOT_EXPR, $2); } | unop cast_expr %prec UNARY - { $$ = build_x_unary_op ($1, $2); - if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST) - TREE_NEGATED_INT ($$) = 1; - overflow_warning ($$); - } + { $$ = finish_unary_op_expr ($1, $2); } /* Refer to the address of a label as a pointer. */ | ANDAND identifier - { tree label = lookup_label ($2); - if (label == NULL_TREE) - $$ = null_pointer_node; - else - { - TREE_USED (label) = 1; - $$ = build1 (ADDR_EXPR, ptr_type_node, label); - TREE_CONSTANT ($$) = 1; - } - } + { if (pedantic) + pedwarn ("ANSI C++ forbids `&&'"); + $$ = finish_label_address_expr ($2); } | SIZEOF unary_expr %prec UNARY - { if (TREE_CODE ($2) == COMPONENT_REF - && DECL_BIT_FIELD (TREE_OPERAND ($2, 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 - because that would break commas in lvalues. - So do the conversion here if operand was a comma. */ - if (TREE_CODE ($2) == COMPOUND_EXPR - && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE)) - $2 = default_conversion ($2); - else if (TREE_CODE ($2) == TREE_LIST) - { - tree t = TREE_VALUE ($2); - 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"); - } - $$ = c_sizeof (TREE_TYPE ($2)); } + { $$ = expr_sizeof ($2); } | SIZEOF '(' type_id ')' %prec HYPERUNARY - { $$ = c_sizeof (groktypename ($3)); } + { $$ = c_sizeof (groktypename ($3.t)); } | ALIGNOF unary_expr %prec UNARY { $$ = grok_alignof ($2); } | ALIGNOF '(' type_id ')' %prec HYPERUNARY - { $$ = c_alignof (groktypename ($3)); } + { $$ = c_alignof (groktypename ($3.t)); + check_for_new_type ("alignof", $3); } /* The %prec EMPTY's here are required by the = init initializer syntax extension; see below. */ - | new new_type_id %prec EMPTY - { $$ = build_new (NULL_TREE, $2, NULL_TREE, $1); } + | new new_type_id %prec EMPTY + { $$ = build_new (NULL_TREE, $2.t, NULL_TREE, $1); + check_for_new_type ("new", $2); } | new new_type_id new_initializer - { $$ = build_new (NULL_TREE, $2, $3, $1); } - | new new_placement new_type_id %prec EMPTY - { $$ = build_new ($2, $3, NULL_TREE, $1); } + { $$ = build_new (NULL_TREE, $2.t, $3, $1); + check_for_new_type ("new", $2); } + | new new_placement new_type_id %prec EMPTY + { $$ = build_new ($2, $3.t, NULL_TREE, $1); + check_for_new_type ("new", $3); } | new new_placement new_type_id new_initializer - { $$ = build_new ($2, $3, $4, $1); } - | new '(' type_id ')' %prec EMPTY - { $$ = build_new (NULL_TREE, groktypename($3), - NULL_TREE, $1); } - | new '(' type_id ')' new_initializer - { $$ = build_new (NULL_TREE, groktypename($3), $5, $1); } - | new new_placement '(' type_id ')' %prec EMPTY - { $$ = build_new ($2, groktypename($4), NULL_TREE, $1); } - | new new_placement '(' type_id ')' new_initializer - { $$ = build_new ($2, groktypename($4), $6, $1); } + { $$ = build_new ($2, $3.t, $4, $1); + check_for_new_type ("new", $3); } + /* The .begin_new_placement in the following rules is + necessary to avoid shift/reduce conflicts that lead to + mis-parsing some expressions. Of course, these constructs + are not really new-placement and it is bogus to call + begin_new_placement. But, the parser cannot always tell at this + point whether the next thing is an expression or a type-id, + so there is nothing we can do. Fortunately, + begin_new_placement does nothing harmful. When we rewrite + the parser, this lossage should be removed, of course. */ + | new '(' .begin_new_placement type_id .finish_new_placement + %prec EMPTY + { $$ = build_new (NULL_TREE, groktypename($4.t), + NULL_TREE, $1); + check_for_new_type ("new", $4); } + | new '(' .begin_new_placement type_id .finish_new_placement + new_initializer + { $$ = build_new (NULL_TREE, groktypename($4.t), $6, $1); + check_for_new_type ("new", $4); } + | new new_placement '(' .begin_new_placement type_id + .finish_new_placement %prec EMPTY + { $$ = build_new ($2, groktypename($5.t), NULL_TREE, $1); + check_for_new_type ("new", $5); } + | new new_placement '(' .begin_new_placement type_id + .finish_new_placement new_initializer + { $$ = build_new ($2, groktypename($5.t), $7, $1); + check_for_new_type ("new", $5); } | delete cast_expr %prec UNARY { $$ = delete_sanity ($2, NULL_TREE, 0, $1); } @@ -1131,20 +1110,34 @@ unary_expr: { $$ = delete_sanity ($4, NULL_TREE, 1, $1); if (yychar == YYEMPTY) yychar = YYLEX; } - | delete '[' expr ']' cast_expr %prec UNARY + | delete '[' expr ']' cast_expr %prec UNARY { $$ = delete_sanity ($5, $3, 2, $1); if (yychar == YYEMPTY) yychar = YYLEX; } + | REALPART cast_expr %prec UNARY + { $$ = build_x_unary_op (REALPART_EXPR, $2); } + | IMAGPART cast_expr %prec UNARY + { $$ = build_x_unary_op (IMAGPART_EXPR, $2); } ; + /* Note this rule is not suitable for use in new_placement + since it uses NULL_TREE as the argument to + finish_new_placement. This rule serves only to avoid + reduce/reduce conflicts in unary_expr. See the comments + there on the use of begin/finish_new_placement. */ +.finish_new_placement: + ')' + { finish_new_placement (NULL_TREE, $-1); } + +.begin_new_placement: + { $$ = begin_new_placement (); } + new_placement: - '(' nonnull_exprlist ')' - { $$ = $2; } - | '{' nonnull_exprlist '}' - { - $$ = $2; - pedwarn ("old style placement syntax, use () instead"); - } + '(' .begin_new_placement nonnull_exprlist ')' + { $$ = finish_new_placement ($3, $2); } + | '{' .begin_new_placement nonnull_exprlist '}' + { cp_pedwarn ("old style placement syntax, use () instead"); + $$ = finish_new_placement ($3, $2); } ; new_initializer: @@ -1154,7 +1147,7 @@ new_initializer: { $$ = NULL_TREE; } | '(' typespec ')' { - cp_error ("`%T' is not a valid expression", $2); + cp_error ("`%T' is not a valid expression", $2.t); $$ = error_mark_node; } /* GNU extension so people can use initializer lists. Note that @@ -1164,21 +1157,24 @@ new_initializer: { if (pedantic) pedwarn ("ANSI C++ forbids initialization of new expression with `='"); - $$ = $2; + if (TREE_CODE ($2) != TREE_LIST + && TREE_CODE ($2) != CONSTRUCTOR) + $$ = build_expr_list (NULL_TREE, $2); + else + $$ = $2; } ; /* This is necessary to postpone reduction of `int ((int)(int)(int))'. */ regcast_or_absdcl: - '(' type_id ')' %prec EMPTY - { $2 = tree_cons (NULL_TREE, $2, void_list_node); - TREE_PARMLIST ($2) = 1; - $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, - NULL_TREE); } - | regcast_or_absdcl '(' type_id ')' %prec EMPTY - { $3 = tree_cons (NULL_TREE, $3, void_list_node); - TREE_PARMLIST ($3) = 1; - $$ = build_parse_node (CALL_EXPR, $$, $3, NULL_TREE); } + '(' type_id ')' %prec EMPTY + { $2.t = finish_parmlist (build_tree_list (NULL_TREE, $2.t), 0); + $$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE); + check_for_new_type ("cast", $2); } + | regcast_or_absdcl '(' type_id ')' %prec EMPTY + { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0); + $$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE); + check_for_new_type ("cast", $3); } ; cast_expr: @@ -1242,15 +1238,11 @@ expr_no_commas: | expr_no_commas '?' xexpr ':' expr_no_commas { $$ = build_x_conditional_expr ($$, $3, $5); } | expr_no_commas '=' expr_no_commas - { $$ = build_modify_expr ($$, NOP_EXPR, $3); - C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } + { $$ = build_x_modify_expr ($$, NOP_EXPR, $3); + if ($$ != error_mark_node) + C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } | expr_no_commas ASSIGN expr_no_commas - { register tree rval; - if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3, - make_node ($2)))) - $$ = rval; - else - $$ = build_modify_expr ($$, $2, $3); } + { $$ = build_x_modify_expr ($$, $2, $3); } | THROW { $$ = build_throw (NULL_TREE); } | THROW expr_no_commas @@ -1258,13 +1250,13 @@ expr_no_commas: /* These extensions are not defined. The second arg to build_m_component_ref is old, build_m_component_ref now does an implicit build_indirect_ref (x, NULL_PTR) on the second argument. - | object '&' expr_no_commas %prec UNARY + | object '&' expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); } | object unop expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); } | object '(' type_id ')' expr_no_commas %prec UNARY - { tree type = groktypename ($3); - $$ = build_m_component_ref ($$, build_c_cast (type, $5, 0)); } + { tree type = groktypename ($3.t); + $$ = build_m_component_ref ($$, build_c_cast (type, $5)); } | object primary_no_id %prec UNARY { $$ = build_m_component_ref ($$, $2); } */ @@ -1273,30 +1265,62 @@ expr_no_commas: notype_unqualified_id: '~' see_typename identifier { $$ = build_parse_node (BIT_NOT_EXPR, $3); } + | template_id | operator_name | IDENTIFIER | PTYPENAME - | NSNAME %prec EMPTY + | NSNAME %prec EMPTY + ; + +do_id: + { $$ = do_identifier ($-1, 1, NULL_TREE); } + +template_id: + PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket + { $$ = lookup_template_function ($3, $4); } + | operator_name '<' do_id template_arg_list_opt template_close_bracket + { $$ = lookup_template_function ($3, $4); } ; +object_template_id: + TEMPLATE identifier '<' template_arg_list_opt template_close_bracket + { $$ = lookup_template_function ($2, $4); } + | TEMPLATE PFUNCNAME '<' template_arg_list_opt template_close_bracket + { $$ = lookup_template_function ($2, $4); } + | TEMPLATE operator_name '<' template_arg_list_opt + template_close_bracket + { $$ = lookup_template_function ($2, $4); } + ; + unqualified_id: notype_unqualified_id | TYPENAME + | SELFNAME ; expr_or_declarator: notype_unqualified_id - | '*' expr_or_declarator %prec UNARY + | '*' expr_or_declarator %prec UNARY { $$ = build_parse_node (INDIRECT_REF, $2); } - | '&' expr_or_declarator %prec UNARY + | '&' expr_or_declarator %prec UNARY { $$ = build_parse_node (ADDR_EXPR, $2); } | '(' expr_or_declarator ')' { $$ = $2; } ; +notype_template_declarator: + IDENTIFIER '<' template_arg_list_opt template_close_bracket + { $$ = lookup_template_function ($1, $3); } + | NSNAME '<' template_arg_list template_close_bracket + { $$ = lookup_template_function ($1, $3); } + ; + direct_notype_declarator: complex_direct_notype_declarator - | notype_unqualified_id + /* This precedence declaration is to prefer this reduce + 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); } ; @@ -1304,43 +1328,26 @@ direct_notype_declarator: primary: notype_unqualified_id { - if (TREE_CODE ($$) == BIT_NOT_EXPR) - $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0)); - else if (IDENTIFIER_OPNAME_P ($$)) - { - tree op = $$; - $$ = lookup_name (op, 0); - if ($$ == NULL_TREE) - { - if (op != ansi_opname[ERROR_MARK]) - error ("operator %s not defined", - operator_name_string (op)); - $$ = error_mark_node; - } - } - else - $$ = do_identifier ($$); + if (TREE_CODE ($1) == BIT_NOT_EXPR) + $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($1, 0)); + else + $$ = finish_id_expr ($1); } | CONSTANT | boolean.literal | string - { $$ = combine_strings ($$); } + { + if (processing_template_decl) + push_obstacks (&permanent_obstack, &permanent_obstack); + $$ = combine_strings ($$); + if (processing_template_decl) + pop_obstacks (); + } | '(' expr ')' - { char class; - $$ = $2; - class = TREE_CODE_CLASS (TREE_CODE ($$)); - if (class == 'e' || class == '1' - || class == '2' || class == '<') - /* This inhibits warnings in truthvalue_conversion. */ - C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); } + { $$ = finish_parenthesized_expr ($2); } | '(' expr_or_declarator ')' - { char class; - $$ = reparse_decl_as_expr (NULL_TREE, $2); - class = TREE_CODE_CLASS (TREE_CODE ($$)); - if (class == 'e' || class == '1' - || class == '2' || class == '<') - /* This inhibits warnings in truthvalue_conversion. */ - C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); } + { $2 = reparse_decl_as_expr (NULL_TREE, $2); + $$ = finish_parenthesized_expr ($2); } | '(' error ')' { $$ = error_mark_node; } | '(' @@ -1349,90 +1356,35 @@ primary: error ("braced-group within expression allowed only inside a function"); YYERROR; } - keep_next_level (); - $$ = expand_start_stmt_expr (); } - compstmt ')' - { tree rtl_exp; if (pedantic) - pedwarn ("ANSI C++ forbids braced-groups within expressions"); - rtl_exp = expand_end_stmt_expr ($2); - /* The statements have side effects, so the group does. */ - TREE_SIDE_EFFECTS (rtl_exp) = 1; - - if (TREE_CODE ($3) == BLOCK) - { - /* Make a BIND_EXPR for the BLOCK already made. */ - $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), - NULL_TREE, rtl_exp, $3); - /* 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 ($3); - } - else - $$ = $3; + pedwarn ("ANSI C++ forbids braced-groups within expressions"); + $$ = begin_stmt_expr (); } + compstmt ')' + { $$ = finish_stmt_expr ($2, $3); } + /* Koenig lookup support + We could store lastiddecl in $1 to avoid another lookup, + but that would result in many additional reduce/reduce conflicts. */ + | notype_unqualified_id '(' nonnull_exprlist ')' + { $$ = finish_call_expr ($1, $3, 1); } + | notype_unqualified_id LEFT_RIGHT + { $$ = finish_call_expr ($1, NULL_TREE, 1); } | primary '(' nonnull_exprlist ')' - { /* [eichin:19911016.1902EST] */ - $$ = build_x_function_call ($1, $3, current_class_decl); - /* here we instantiate_class_template as needed... */ - do_pending_templates (); - } template_instantiate_some { - if (TREE_CODE ($5) == CALL_EXPR - && TREE_TYPE ($5) != void_type_node) - $$ = require_complete_type ($5); - else - $$ = $5; - } + { $$ = finish_call_expr ($1, $3, 0); } | primary LEFT_RIGHT - { - $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); - if (TREE_CODE ($$) == CALL_EXPR - && TREE_TYPE ($$) != void_type_node) - $$ = require_complete_type ($$); - } + { $$ = finish_call_expr ($1, NULL_TREE, 0); } | primary '[' expr ']' { $$ = grok_array_decl ($$, $3); } | primary PLUSPLUS - { /* If we get an OFFSET_REF, turn it into what it really - means (e.g., a COMPONENT_REF). This way if we've got, - say, a reference to a static member that's being operated - on, we don't end up trying to find a member operator for - the class it's in. */ - if (TREE_CODE ($$) == OFFSET_REF) - $$ = resolve_offset_ref ($$); - $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } + { $$ = finish_increment_expr ($1, POSTINCREMENT_EXPR); } | primary MINUSMINUS - { if (TREE_CODE ($$) == OFFSET_REF) - $$ = resolve_offset_ref ($$); - $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } + { $$ = finish_increment_expr ($1, POSTDECREMENT_EXPR); } /* C++ extensions */ | THIS - { if (current_class_decl) - { -#ifdef WARNING_ABOUT_CCD - TREE_USED (current_class_decl) = 1; -#endif - $$ = current_class_decl; - } - else if (current_function_decl - && DECL_STATIC_FUNCTION_P (current_function_decl)) - { - error ("`this' is unavailable for static member functions"); - $$ = error_mark_node; - } - else - { - if (current_function_decl) - error ("invalid use of `this' in non-member function"); - else - error ("invalid use of `this' at top level"); - $$ = error_mark_node; - } - } - | TYPE_QUAL '(' nonnull_exprlist ')' + { $$ = finish_this_expr (); } + | CV_QUALIFIER '(' nonnull_exprlist ')' { - tree type; + tree type = NULL_TREE; tree id = $$; /* This is a C cast in C++'s `functional' notation. */ @@ -1471,180 +1423,80 @@ primary: } #endif else my_friendly_abort (79); - $$ = build_c_cast (type, build_compound_expr ($3), 1); + $$ = build_c_cast (type, build_compound_expr ($3)); } } | functional_cast - | DYNAMIC_CAST '<' - { dont_allow_type_definitions = "inside dynamic_cast"; } - type_id '>' - { dont_allow_type_definitions = 0; } - '(' expr ')' - { tree type = groktypename ($4); - $$ = build_dynamic_cast (type, $8); } - | STATIC_CAST '<' - { dont_allow_type_definitions = "inside static_cast"; } - type_id '>' - { dont_allow_type_definitions = 0; } - '(' expr ')' - { tree type = groktypename ($4); - $$ = build_static_cast (type, $8); } - | REINTERPRET_CAST '<' - { dont_allow_type_definitions = "inside reinterpret_cast"; } - type_id '>' - { dont_allow_type_definitions = 0; } - '(' expr ')' - { tree type = groktypename ($4); - $$ = build_reinterpret_cast (type, $8); } - | CONST_CAST '<' - { dont_allow_type_definitions = "inside const_cast"; } - type_id '>' - { dont_allow_type_definitions = 0; } - '(' expr ')' - { tree type = groktypename ($4); - $$ = build_const_cast (type, $8); } + | DYNAMIC_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3.t); + check_for_new_type ("dynamic_cast", $3); + $$ = build_dynamic_cast (type, $6); } + | STATIC_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3.t); + check_for_new_type ("static_cast", $3); + $$ = build_static_cast (type, $6); } + | REINTERPRET_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3.t); + check_for_new_type ("reinterpret_cast", $3); + $$ = build_reinterpret_cast (type, $6); } + | CONST_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3.t); + check_for_new_type ("const_cast", $3); + $$ = build_const_cast (type, $6); } | TYPEID '(' expr ')' - { $$ = build_typeid ($3); } + { $$ = build_x_typeid ($3); } | TYPEID '(' type_id ')' - { tree type = groktypename ($3); + { tree type = groktypename ($3.t); + check_for_new_type ("typeid", $3); $$ = get_typeid (TYPE_MAIN_VARIANT (type)); } | global_scope IDENTIFIER - { - do_scoped_id: - $$ = IDENTIFIER_GLOBAL_VALUE ($2); - if (yychar == YYEMPTY) - yychar = YYLEX; - if (! $$) - { - if (yychar == '(' || yychar == LEFT_RIGHT) - $$ = implicitly_declare ($2); - else - { - if (IDENTIFIER_GLOBAL_VALUE ($2) != error_mark_node) - error ("undeclared variable `%s' (first use here)", - IDENTIFIER_POINTER ($2)); - $$ = error_mark_node; - /* Prevent repeated error messages. */ - IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node; - } - } - else - { - if (TREE_CODE ($$) == ADDR_EXPR) - assemble_external (TREE_OPERAND ($$, 0)); - else - assemble_external ($$); - TREE_USED ($$) = 1; - } - if (TREE_CODE ($$) == CONST_DECL) - { - /* XXX CHS - should we set TREE_USED of the constant? */ - $$ = DECL_INITIAL ($$); - /* This is to prevent an enum whose value is 0 - from being considered a null pointer constant. */ - $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$); - TREE_CONSTANT ($$) = 1; - } - - } + { $$ = do_scoped_id ($2, 1); } + | global_scope template_id + { $$ = $2; } | global_scope operator_name { got_scope = NULL_TREE; if (TREE_CODE ($2) == IDENTIFIER_NODE) - goto do_scoped_id; - $$ = $2; + $$ = do_scoped_id ($2, 1); + else + $$ = $2; } - | overqualified_id %prec HYPERUNARY + | overqualified_id %prec HYPERUNARY { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); } | overqualified_id '(' nonnull_exprlist ')' - { $$ = build_member_call (OP0 ($$), OP1 ($$), $3); } + { $$ = finish_globally_qualified_member_call_expr ($1, $3); } | overqualified_id LEFT_RIGHT - { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); } + { $$ = finish_globally_qualified_member_call_expr ($1, NULL_TREE); } + | object object_template_id %prec UNARY + { + $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); + } + | object object_template_id '(' nonnull_exprlist ')' + { $$ = finish_object_call_expr ($2, $1, $4); } + | object object_template_id LEFT_RIGHT + { $$ = finish_object_call_expr ($2, $1, NULL_TREE); } | object unqualified_id %prec UNARY - { got_object = NULL_TREE; - $$ = build_component_ref ($$, $2, NULL_TREE, 1); } - | object overqualified_id %prec UNARY - { got_object = NULL_TREE; - $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } + { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); } + | object overqualified_id %prec UNARY + { if (processing_template_decl) + $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2)); + else + $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } | object unqualified_id '(' nonnull_exprlist ')' - { - got_object = NULL_TREE; -#if 0 - /* This is a future direction of this code, but because - build_x_function_call cannot always undo what is done - in build_component_ref entirely yet, we cannot do this. */ - $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, $$); - if (TREE_CODE ($$) == CALL_EXPR - && TREE_TYPE ($$) != void_type_node) - $$ = require_complete_type ($$); -#else - $$ = build_method_call ($$, $2, $4, NULL_TREE, - (LOOKUP_NORMAL|LOOKUP_AGGR)); -#endif - } + { $$ = finish_object_call_expr ($2, $1, $4); } | object unqualified_id LEFT_RIGHT - { - got_object = NULL_TREE; -#if 0 - /* This is a future direction of this code, but because - build_x_function_call cannot always undo what is done - in build_component_ref entirely yet, we cannot do this. */ - $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, $$); - if (TREE_CODE ($$) == CALL_EXPR - && TREE_TYPE ($$) != void_type_node) - $$ = require_complete_type ($$); -#else - $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE, - (LOOKUP_NORMAL|LOOKUP_AGGR)); -#endif - } + { $$ = finish_object_call_expr ($2, $1, NULL_TREE); } | object overqualified_id '(' nonnull_exprlist ')' - { - got_object = NULL_TREE; - if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) - { - warning ("signature name in scope resolution ignored"); - $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE, - (LOOKUP_NORMAL|LOOKUP_AGGR)); - } - else - $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4); - } + { $$ = finish_qualified_object_call_expr ($2, $1, $4); } | object overqualified_id LEFT_RIGHT - { - got_object = NULL_TREE; - if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) - { - warning ("signature name in scope resolution ignored"); - $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE, - (LOOKUP_NORMAL|LOOKUP_AGGR)); - } - else - $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE); - } + { $$ = finish_qualified_object_call_expr ($2, $1, NULL_TREE); } /* p->int::~int() is valid -- 12.4 */ | object '~' TYPESPEC LEFT_RIGHT - { - got_object = NULL_TREE; - if (IDENTIFIER_GLOBAL_VALUE ($3) - && (TREE_CODE (TREE_TYPE ($1)) - != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))) - cp_error ("`%E' is not of type `%T'", $1, $3); - $$ = convert (void_type_node, $1); - } + { $$ = finish_pseudo_destructor_call_expr ($1, NULL_TREE, $3); } | object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT - { - got_object = NULL_TREE; - if ($2 != $5) - cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5); - if (TREE_CODE (TREE_TYPE ($1)) - != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($2)))) - cp_error ("`%E' is not of type `%T'", $1, $2); - $$ = convert (void_type_node, $1); - } + { $$ = finish_pseudo_destructor_call_expr ($1, $2, $5); } | object error { - got_object = NULL_TREE; $$ = error_mark_node; } ; @@ -1668,9 +1520,9 @@ primary_no_id: pedwarn ("ANSI C++ forbids braced-groups within expressions"); $$ = expand_end_stmt_expr ($2); } | primary_no_id '(' nonnull_exprlist ')' - { $$ = build_x_function_call ($$, $3, current_class_decl); } + { $$ = build_x_function_call ($$, $3, current_class_ref); } | primary_no_id LEFT_RIGHT - { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); } + { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); } | primary_no_id '[' expr ']' { goto do_array; } | primary_no_id PLUSPLUS @@ -1687,13 +1539,15 @@ primary_no_id: ; */ -new: NEW +new: + NEW { $$ = 0; } | global_scope NEW { got_scope = NULL_TREE; $$ = 1; } ; -delete: DELETE +delete: + DELETE { $$ = 0; } | global_scope delete { got_scope = NULL_TREE; $$ = 1; } @@ -1726,7 +1580,8 @@ nodecls: } ; -object: primary '.' +object: + primary '.' { got_object = TREE_TYPE ($$); } | primary POINTSAT { @@ -1736,79 +1591,65 @@ object: primary '.' ; decl: - /* Normal case: make this fast. */ - typespec declarator ';' - { tree d = get_decl_list ($1); - int yes = suspend_momentary (); - d = start_decl ($2, d, 0, NULL_TREE); - cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); - resume_momentary (yes); - if (IS_AGGR_TYPE_CODE (TREE_CODE ($1))) - note_got_semicolon ($1); - } - | typed_declspecs declarator ';' - { tree d, specs, attrs; - int yes; - split_specs_attrs ($1, &specs, &attrs); - yes = suspend_momentary (); - d = start_decl ($2, specs, 0, NULL_TREE); - cplus_decl_attributes (d, NULL_TREE, attrs); - cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); - resume_momentary (yes); - note_list_got_semicolon ($1); - } - | typespec initdecls ';' + typespec initdecls ';' { resume_momentary ($2); - if (IS_AGGR_TYPE_CODE (TREE_CODE ($1))) - note_got_semicolon ($1); + if ($1.t && IS_AGGR_TYPE_CODE (TREE_CODE ($1.t))) + note_got_semicolon ($1.t); } | typed_declspecs initdecls ';' { resume_momentary ($2); - note_list_got_semicolon ($1); + note_list_got_semicolon ($1.t); } | declmods notype_initdecls ';' { resume_momentary ($2); } | typed_declspecs ';' { - shadow_tag ($1); - note_list_got_semicolon ($1); + shadow_tag ($1.t); + note_list_got_semicolon ($1.t); } | declmods ';' { warning ("empty declaration"); } + | extension decl + { pedantic = $1; } ; /* Any kind of declarator (thus, all declarators allowed after an explicit typespec). */ declarator: - after_type_declarator %prec EMPTY - | notype_declarator %prec EMPTY + after_type_declarator %prec EMPTY + | notype_declarator %prec EMPTY ; /* This is necessary to postpone reduction of `int()()()()'. */ fcast_or_absdcl: - LEFT_RIGHT %prec EMPTY - { $$ = build_parse_node (CALL_EXPR, NULL_TREE, empty_parms (), - NULL_TREE); } - | fcast_or_absdcl LEFT_RIGHT %prec EMPTY - { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), - NULL_TREE); } + LEFT_RIGHT %prec EMPTY + { $$ = make_call_declarator (NULL_TREE, empty_parms (), + NULL_TREE, NULL_TREE); } + | fcast_or_absdcl LEFT_RIGHT %prec EMPTY + { $$ = make_call_declarator ($$, empty_parms (), NULL_TREE, + NULL_TREE); } ; /* ANSI type-id (8.1) */ type_id: typed_typespecs absdcl - { $$ = build_decl_list ($$, $2); } - | nonempty_type_quals absdcl - { $$ = build_decl_list ($$, $2); } + { $$.t = build_decl_list ($1.t, $2); + $$.new_type_flag = $1.new_type_flag; } + | nonempty_cv_qualifiers absdcl + { $$.t = build_decl_list ($1.t, $2); + $$.new_type_flag = $1.new_type_flag; } | typespec absdcl - { $$ = build_decl_list (get_decl_list ($$), $2); } - | typed_typespecs %prec EMPTY - { $$ = build_decl_list ($$, NULL_TREE); } - | nonempty_type_quals %prec EMPTY - { $$ = build_decl_list ($$, NULL_TREE); } + { $$.t = build_decl_list (get_decl_list ($1.t), $2); + $$.new_type_flag = $1.new_type_flag; } + | typed_typespecs %prec EMPTY + { $$.t = build_decl_list ($1.t, NULL_TREE); + $$.new_type_flag = $1.new_type_flag; } + | nonempty_cv_qualifiers %prec EMPTY + { $$.t = build_decl_list ($1.t, NULL_TREE); + $$.new_type_flag = $1.new_type_flag; } ; /* Declspecs which contain at least one type specifier or typedef name. @@ -1817,24 +1658,30 @@ type_id: In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */ typed_declspecs: - typed_typespecs %prec EMPTY + typed_typespecs %prec EMPTY | typed_declspecs1 ; typed_declspecs1: declmods typespec - { $$ = decl_tree_cons (NULL_TREE, $2, $$); } - | typespec reserved_declspecs %prec HYPERUNARY - { $$ = decl_tree_cons (NULL_TREE, $$, $2); } + { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1); + $$.new_type_flag = $2.new_type_flag; } + | typespec reserved_declspecs %prec HYPERUNARY + { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); + $$.new_type_flag = $1.new_type_flag; } | typespec reserved_typespecquals reserved_declspecs - { $$ = decl_tree_cons (NULL_TREE, $$, chainon ($2, $3)); } + { $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3)); + $$.new_type_flag = $1.new_type_flag; } | declmods typespec reserved_declspecs - { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); } + { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); + $$.new_type_flag = $2.new_type_flag; } | declmods typespec reserved_typespecquals - { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); } + { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); + $$.new_type_flag = $2.new_type_flag; } | declmods typespec reserved_typespecquals reserved_declspecs - { $$ = decl_tree_cons (NULL_TREE, $2, - chainon ($3, chainon ($4, $$))); } + { $$.t = decl_tree_cons (NULL_TREE, $2.t, + chainon ($3, chainon ($4, $1))); + $$.new_type_flag = $2.new_type_flag; } ; reserved_declspecs: @@ -1844,7 +1691,7 @@ reserved_declspecs: IDENTIFIER_POINTER ($$)); $$ = build_decl_list (NULL_TREE, $$); } | reserved_declspecs typespecqual_reserved - { $$ = decl_tree_cons (NULL_TREE, $2, $$); } + { $$ = decl_tree_cons (NULL_TREE, $2.t, $$); } | reserved_declspecs SCSPEC { if (extra_warnings) warning ("`%s' is not at beginning of declaration", @@ -1862,11 +1709,11 @@ reserved_declspecs: In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */ declmods: - nonempty_type_quals %prec EMPTY - { TREE_STATIC ($$) = 1; } + nonempty_cv_qualifiers %prec EMPTY + { $$ = $1.t; TREE_STATIC ($$) = 1; } | SCSPEC { $$ = IDENTIFIER_AS_LIST ($$); } - | declmods TYPE_QUAL + | declmods CV_QUALIFIER { $$ = decl_tree_cons (NULL_TREE, $2, $$); TREE_STATIC ($$) = 1; } | declmods SCSPEC @@ -1889,71 +1736,81 @@ declmods: typed_typespecs: typespec %prec EMPTY - { $$ = get_decl_list ($$); } - | nonempty_type_quals typespec - { $$ = decl_tree_cons (NULL_TREE, $2, $$); } + { $$.t = get_decl_list ($1.t); + $$.new_type_flag = $1.new_type_flag; } + | nonempty_cv_qualifiers typespec + { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t); + $$.new_type_flag = $2.new_type_flag; } | typespec reserved_typespecquals - { $$ = decl_tree_cons (NULL_TREE, $$, $2); } - | nonempty_type_quals typespec reserved_typespecquals - { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); } + { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); + $$.new_type_flag = $1.new_type_flag; } + | nonempty_cv_qualifiers typespec reserved_typespecquals + { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); + $$.new_type_flag = $1.new_type_flag; } ; reserved_typespecquals: typespecqual_reserved - { $$ = build_decl_list (NULL_TREE, $$); } + { $$ = build_decl_list (NULL_TREE, $1.t); } | reserved_typespecquals typespecqual_reserved - { $$ = decl_tree_cons (NULL_TREE, $2, $$); } + { $$ = decl_tree_cons (NULL_TREE, $2.t, $1); } ; /* A typespec (but not a type qualifier). Once we have seen one of these in a declaration, if a typedef name appears then it is being redeclared. */ -typespec: structsp +typespec: + structsp | TYPESPEC %prec EMPTY + { $$.t = $1; $$.new_type_flag = 0; } | complete_type_name + { $$.t = $1; $$.new_type_flag = 0; } | TYPEOF '(' expr ')' - { $$ = TREE_TYPE ($3); - if (pedantic && !in_system_header) - pedwarn ("ANSI C++ forbids `typeof'"); } + { $$.t = TREE_TYPE ($3); + $$.new_type_flag = 0; } | TYPEOF '(' type_id ')' - { $$ = groktypename ($3); - if (pedantic && !in_system_header) - pedwarn ("ANSI C++ forbids `typeof'"); } + { $$.t = groktypename ($3.t); + $$.new_type_flag = 0; } | SIGOF '(' expr ')' { tree type = TREE_TYPE ($3); + $$.new_type_flag = 0; if (IS_AGGR_TYPE (type)) { sorry ("sigof type specifier"); - $$ = type; + $$.t = type; } else { error ("`sigof' applied to non-aggregate expression"); - $$ = error_mark_node; + $$.t = error_mark_node; } } | SIGOF '(' type_id ')' - { tree type = groktypename ($3); + { tree type = groktypename ($3.t); + $$.new_type_flag = 0; if (IS_AGGR_TYPE (type)) { sorry ("sigof type specifier"); - $$ = type; + $$.t = type; } else { error("`sigof' applied to non-aggregate type"); - $$ = error_mark_node; + $$.t = error_mark_node; } } ; /* A typespec that is a reserved word, or a type qualifier. */ -typespecqual_reserved: TYPESPEC - | TYPE_QUAL +typespecqual_reserved: + TYPESPEC + { $$.t = $1; $$.new_type_flag = 0; } + | CV_QUALIFIER + { $$.t = $1; $$.new_type_flag = 0; } | structsp ; @@ -1979,104 +1836,67 @@ maybeasm: { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; } ; -initdcl0: - declarator exception_specification_opt maybeasm maybe_attribute '=' - { split_specs_attrs ($0, ¤t_declspecs, - &prefix_attributes); - if (TREE_CODE (current_declspecs) != TREE_LIST) - current_declspecs = get_decl_list (current_declspecs); - if (have_extern_spec && !used_extern_spec) - { - current_declspecs = decl_tree_cons - (NULL_TREE, get_identifier ("extern"), - current_declspecs); - used_extern_spec = 1; - } - $5 = suspend_momentary (); - $$ = start_decl ($1, current_declspecs, 1, $2); - cplus_decl_attributes ($$, $4, prefix_attributes); } - init -/* Note how the declaration of the variable is in effect while its init is parsed! */ - { cp_finish_decl ($6, $7, $3, 0, LOOKUP_ONLYCONVERTING); - $$ = $5; } - | declarator exception_specification_opt maybeasm maybe_attribute - { tree d; - split_specs_attrs ($0, ¤t_declspecs, - &prefix_attributes); - if (TREE_CODE (current_declspecs) != TREE_LIST) - current_declspecs = get_decl_list (current_declspecs); - if (have_extern_spec && !used_extern_spec) - { - current_declspecs = decl_tree_cons - (NULL_TREE, get_identifier ("extern"), - current_declspecs); - used_extern_spec = 1; - } - $$ = suspend_momentary (); - d = start_decl ($1, current_declspecs, 0, $2); - cplus_decl_attributes (d, $4, prefix_attributes); - cp_finish_decl (d, NULL_TREE, $3, 0, 0); } - ; - initdcl: - declarator exception_specification_opt maybeasm maybe_attribute '=' - { $$ = start_decl ($1, current_declspecs, 1, $2); - cplus_decl_attributes ($$, $4, prefix_attributes); } + declarator maybeasm maybe_attribute '=' + { $$ = start_decl ($1, current_declspecs, 1, + $3, prefix_attributes); } init /* Note how the declaration of the variable is in effect while its init is parsed! */ - { cp_finish_decl ($6, $7, $3, 0, LOOKUP_ONLYCONVERTING); } - | declarator exception_specification_opt maybeasm maybe_attribute - { $$ = start_decl ($1, current_declspecs, 0, $2); - cplus_decl_attributes ($$, $4, prefix_attributes); - cp_finish_decl ($$, NULL_TREE, $3, 0, 0); } - ; - -notype_initdcl0: - notype_declarator exception_specification_opt maybeasm maybe_attribute '=' - { split_specs_attrs ($0, ¤t_declspecs, - &prefix_attributes); - $5 = suspend_momentary (); - $$ = start_decl ($1, current_declspecs, 1, $2); - cplus_decl_attributes ($$, $4, prefix_attributes); } + { cp_finish_decl ($5, $6, $2, 1, LOOKUP_ONLYCONVERTING); } + | declarator maybeasm maybe_attribute + { $$ = start_decl ($1, current_declspecs, 0, + $3, prefix_attributes); + cp_finish_decl ($$, NULL_TREE, $2, 1, 0); } + ; + + /* This rule assumes a certain configuration of the parser stack. + In particular, $0, the element directly before the beginning of + this rule on the stack, must be a maybeasm. $-1 must be a + declarator or notype_declarator. And $-2 must be some declmods + or declspecs. We can't move the maybeasm into this rule because + we need that reduce so we prefer fn.def1 when appropriate. */ +initdcl0_innards: + maybe_attribute '=' + { $2 = parse_decl ($-1, $-2, + $1, 1, &$$); } + /* Note how the declaration of the variable is in effect + while its init is parsed! */ init -/* Note how the declaration of the variable is in effect while its init is parsed! */ - { cp_finish_decl ($6, $7, $3, 0, LOOKUP_ONLYCONVERTING); - $$ = $5; } - | notype_declarator exception_specification_opt maybeasm maybe_attribute + { cp_finish_decl ($3, $4, $0, 1, + LOOKUP_ONLYCONVERTING); + $$ = $2; } + | maybe_attribute { tree d; - split_specs_attrs ($0, ¤t_declspecs, - &prefix_attributes); - $$ = suspend_momentary (); - d = start_decl ($1, current_declspecs, 0, $2); - cplus_decl_attributes (d, $4, prefix_attributes); - cp_finish_decl (d, NULL_TREE, $3, 0, 0); } - ; - + $$ = parse_decl ($-1, $-2, $1, 0, &d); + cp_finish_decl (d, NULL_TREE, $0, 1, 0); } + ; + +initdcl0: + declarator maybeasm initdcl0_innards + { $$ = $3; } + +notype_initdcl0: + notype_declarator maybeasm initdcl0_innards + { $$ = $3; } + ; + nomods_initdcl0: - notype_declarator exception_specification_opt maybeasm maybe_attribute '=' - { current_declspecs = NULL_TREE; - prefix_attributes = NULL_TREE; - $5 = suspend_momentary (); - $$ = start_decl ($1, current_declspecs, 1, $2); - cplus_decl_attributes ($$, $4, prefix_attributes); } - init -/* Note how the declaration of the variable is in effect while its init is parsed! */ - { cp_finish_decl ($6, $7, $3, 0, LOOKUP_ONLYCONVERTING); - $$ = $5; } - | notype_declarator exception_specification_opt maybeasm maybe_attribute + notype_declarator maybeasm + { /* Set things up as initdcl0_innards expects. */ + $2 = $1; + $1 = NULL_TREE; } + initdcl0_innards + {} + | constructor_declarator maybeasm maybe_attribute { tree d; - current_declspecs = NULL_TREE; - prefix_attributes = NULL_TREE; - $$ = suspend_momentary (); - d = start_decl ($1, current_declspecs, 0, $2); - cplus_decl_attributes (d, $4, prefix_attributes); - cp_finish_decl (d, NULL_TREE, $3, 0, 0); } + parse_decl($1, NULL_TREE, $3, 0, &d); + cp_finish_decl (d, NULL_TREE, $2, 1, 0); } ; /* the * rules are dummies to accept the Apollo extended syntax - so that the header files compile. */ + so that the header files compile. */ maybe_attribute: - /* empty */ + /* empty */ { $$ = NULL_TREE; } | attributes { $$ = $1; } @@ -2102,7 +1922,7 @@ attribute_list: ; attrib: - /* empty */ + /* empty */ { $$ = NULL_TREE; } | any_word { $$ = build_tree_list ($1, NULL_TREE); } @@ -2121,25 +1941,28 @@ any_word: identifier | SCSPEC | TYPESPEC - | TYPE_QUAL + | CV_QUALIFIER ; /* A nonempty list of identifiers, including typenames. */ identifiers_or_typenames: - identifier + identifier { $$ = build_tree_list (NULL_TREE, $1); } | identifiers_or_typenames ',' identifier { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } ; maybe_init: - %prec EMPTY /* empty */ + /* empty */ %prec EMPTY { $$ = NULL_TREE; } | '=' init { $$ = $2; } +/* If we are processing a template, we don't want to expand this + initializer yet. */ + init: - expr_no_commas %prec '=' + expr_no_commas %prec '=' | '{' '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); TREE_HAS_CONSTRUCTOR ($$) = 1; } @@ -2159,101 +1982,126 @@ initlist: init { $$ = build_tree_list (NULL_TREE, $$); } | initlist ',' init - { $$ = tree_cons (NULL_TREE, $3, $$); } + { $$ = expr_tree_cons (NULL_TREE, $3, $$); } /* These are for labeled elements. */ | '[' expr_no_commas ']' init - { $$ = build_tree_list ($2, $4); } - | initlist ',' CASE expr_no_commas ':' init - { $$ = tree_cons ($4, $6, $$); } + { $$ = build_expr_list ($2, $4); } | identifier ':' init - { $$ = build_tree_list ($$, $3); } + { $$ = build_expr_list ($$, $3); } | initlist ',' identifier ':' init - { $$ = tree_cons ($3, $5, $$); } + { $$ = expr_tree_cons ($3, $5, $$); } + ; + +fn.defpen: + PRE_PARSED_FUNCTION_DECL + { start_function (NULL_TREE, TREE_VALUE ($1), + NULL_TREE, 1); + reinit_parse_for_function (); } + +pending_inline: + fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error + { + int nested = (hack_decl_function_context + (current_function_decl) != NULL_TREE); + finish_function (lineno, (int)$3, nested); + process_next_inline ($1); + } + | fn.defpen maybe_return_init function_try_block + { process_next_inline ($1); } + | fn.defpen maybe_return_init error + { process_next_inline ($1); } + ; + +pending_inlines: + /* empty */ + | pending_inlines pending_inline eat_saved_input + ; + +/* A regurgitated default argument. The value of DEFARG_MARKER will be + the TREE_LIST node for the parameter in question. */ +defarg_again: + DEFARG_MARKER expr_no_commas END_OF_SAVED_INPUT + { replace_defarg ($1, $2); } + | DEFARG_MARKER error END_OF_SAVED_INPUT + { replace_defarg ($1, error_mark_node); } + +pending_defargs: + /* empty */ %prec EMPTY + | pending_defargs defarg_again + { do_pending_defargs (); } + | pending_defargs error + { do_pending_defargs (); } ; structsp: ENUM identifier '{' { $3 = suspend_momentary (); - $$ = start_enum ($2); } + $$ = start_enum ($2); } enumlist maybecomma_warn '}' - { $$ = finish_enum ($4, $5); + { $$.t = finish_enum ($4, $5); + $$.new_type_flag = 1; resume_momentary ((int) $3); check_for_missing_semicolon ($4); } | ENUM identifier '{' '}' - { $$ = finish_enum (start_enum ($2), NULL_TREE); - check_for_missing_semicolon ($$); } + { $$.t = finish_enum (start_enum ($2), NULL_TREE); + $$.new_type_flag = 1; + check_for_missing_semicolon ($$.t); } | ENUM '{' { $2 = suspend_momentary (); - $$ = start_enum (make_anon_name ()); } + $$ = start_enum (make_anon_name ()); } enumlist maybecomma_warn '}' - { $$ = finish_enum ($3, $4); + { $$.t = finish_enum ($3, $4); resume_momentary ((int) $1); - check_for_missing_semicolon ($3); } + check_for_missing_semicolon ($3); + $$.new_type_flag = 1; } | ENUM '{' '}' - { $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE); - check_for_missing_semicolon ($$); } + { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE); + $$.new_type_flag = 1; + check_for_missing_semicolon ($$.t); } | ENUM identifier - { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); } + { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1); + $$.new_type_flag = 0; } | ENUM complex_type_name - { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); } - | TYPENAME_KEYWORD complex_type_name - { $$ = $2; } + { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1); + $$.new_type_flag = 0; } + | TYPENAME_KEYWORD typename_sub + { $$.t = $2; + $$.new_type_flag = 0; } /* C++ extensions, merged with C to avoid shift/reduce conflicts */ - | class_head left_curly opt.component_decl_list '}' - { + | class_head left_curly + opt.component_decl_list '}' maybe_attribute + { int semi; - tree id; -#if 0 - /* Need to rework class nesting in the - presence of nested classes, etc. */ - shadow_tag (CLASSTYPE_AS_LIST ($$)); */ -#endif if (yychar == YYEMPTY) yychar = YYLEX; semi = yychar == ';'; - /* finish_struct nukes this anyway; if - finish_exception does too, then it can go. */ - if (semi) - note_got_semicolon ($$); - if (TREE_CODE ($$) == ENUMERAL_TYPE) - /* $$ = $1 from default rule. */; - else + $$ = finish_class_definition ($1, $3, $5, semi); + } + pending_defargs + { finish_default_args (); } + pending_inlines + { $$.t = $6; + $$.new_type_flag = 1; + begin_inline_definitions (); } + | class_head %prec EMPTY + { + $$.new_type_flag = 0; + if (TYPE_BINFO ($1) == NULL_TREE) { - $$ = finish_struct ($$, $3, semi); - if (semi) note_got_semicolon ($$); - } - - pop_obstacks (); - - id = TYPE_IDENTIFIER ($$); - if (id && IDENTIFIER_TEMPLATE (id)) + cp_error ("%T is not a class type", $1); + $$.t = error_mark_node; + } + else { - tree decl; - - /* I don't know if the copying of this TYPE_DECL is - * really needed. However, it's such a small per- - * formance penalty that the extra safety is a bargain. - * - niklas@appli.se - */ - push_obstacks (&permanent_obstack, &permanent_obstack); - decl = copy_node (lookup_name (id, 0)); - if (DECL_LANG_SPECIFIC (decl)) - copy_lang_decl (decl); - pop_obstacks (); - undo_template_name_overload (id, 0); - pushdecl_top_level (decl); + $$.t = $1; + /* struct B: public A; is not accepted by the WP grammar. */ + if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t) + && ! TYPE_BEING_DEFINED ($$.t)) + cp_error ("base clause without member specification for `%#T'", + $$.t); } - if (! semi) - check_for_missing_semicolon ($$); } - | class_head %prec EMPTY - { - /* struct B: public A; is not accepted by the WP grammar. */ - if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$) - && ! TYPE_BEING_DEFINED ($$)) - cp_error ("base clause without member specification for `%#T'", - $$); } ; @@ -2265,64 +2113,70 @@ maybecomma: maybecomma_warn: /* empty */ | ',' - { if (pedantic) pedwarn ("comma at end of enumerator list"); } + { if (pedantic && !in_system_header) + pedwarn ("comma at end of enumerator list"); } ; -aggr: AGGR +aggr: + AGGR | aggr SCSPEC { error ("storage class specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); } | aggr TYPESPEC { error ("type specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); } - | aggr TYPE_QUAL + | aggr CV_QUALIFIER { error ("type qualifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); } | aggr AGGR { error ("no body nor ';' separates two class, struct or union declarations"); } - ; - -specialization: - aggr template_type_name ';' - { - yyungetc (';', 1); current_aggr = $$; $$ = $2; - if ($0 == ridpointers[(int) RID_TEMPLATE]) - instantiate_class_template ($$, 2); - } + | aggr attributes + { $$ = build_decl_list ($2, $1); } ; named_class_head_sans_basetype: aggr identifier { current_aggr = $$; $$ = $2; } - | specialization ; named_class_head_sans_basetype_defn: - aggr identifier_defn %prec EMPTY + aggr identifier_defn %prec EMPTY { current_aggr = $$; $$ = $2; } - | aggr template_type_name '{' - { yyungetc ('{', 1); - aggr2: - current_aggr = $$; - $$ = $2; - overload_template_name ($$, 0); } - | aggr template_type_name ':' - { yyungetc (':', 1); goto aggr2; } + | named_class_head_sans_basetype '{' + { yyungetc ('{', 1); } + | named_class_head_sans_basetype ':' + { yyungetc (':', 1); } ; named_complex_class_head_sans_basetype: aggr nested_name_specifier identifier - { current_aggr = $$; $$ = $3; } - | aggr template_type %prec EMPTY + { + current_aggr = $1; + $$ = handle_class_head ($1, $2, $3); + } + | aggr global_scope nested_name_specifier identifier + { + current_aggr = $1; + $$ = handle_class_head ($1, $3, $4); + } + | aggr global_scope identifier + { + current_aggr = $1; + $$ = handle_class_head ($1, NULL_TREE, $3); + } + | aggr template_type { current_aggr = $$; $$ = $2; } + | aggr nested_name_specifier template_type + { current_aggr = $$; $$ = $3; } ; -do_xref_defn: /* empty */ %prec EMPTY - { $$ = xref_tag (current_aggr, $0, NULL_TREE, 0); } +do_xref_defn: + /* empty */ %prec EMPTY + { $$ = xref_tag (current_aggr, $0, NULL_TREE, 0); } ; named_class_head: - named_class_head_sans_basetype %prec EMPTY + named_class_head_sans_basetype %prec EMPTY { $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); } | named_class_head_sans_basetype_defn do_xref_defn - maybe_base_class_list %prec EMPTY + maybe_base_class_list %prec EMPTY { $$ = $2; if ($3) @@ -2331,22 +2185,46 @@ named_class_head: | 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) - xref_basetypes (current_aggr, $1, TREE_TYPE ($1), $2); + { + 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'", $$); + } + xref_basetypes (current_aggr, $1, $$, $2); + } } ; -unnamed_class_head: aggr '{' +unnamed_class_head: + aggr '{' { $$ = xref_tag ($$, make_anon_name (), NULL_TREE, 0); yyungetc ('{', 1); } ; -class_head: unnamed_class_head | named_class_head ; +class_head: + unnamed_class_head + | named_class_head + ; maybe_base_class_list: - %prec EMPTY /* empty */ + /* empty */ %prec EMPTY { $$ = NULL_TREE; } - | ':' see_typename %prec EMPTY + | ':' see_typename %prec EMPTY { yyungetc(':', 1); $$ = NULL_TREE; } | ':' see_typename base_class_list %prec EMPTY { $$ = $3; } @@ -2362,8 +2240,14 @@ base_class: base_class.1 { tree type; - type = IDENTIFIER_TYPE_VALUE ($$); - if (! is_aggr_typedef ($$, 1)) + 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))) @@ -2375,7 +2259,7 @@ base_class: { sorry ("signature inheritance, base type `%s' ignored", IDENTIFIER_POINTER ($$)); - $$ = build_tree_list ((tree)access_public, $$); + $$ = build_tree_list (access_public_node, type); } else if (type && IS_SIGNATURE (type)) { @@ -2383,15 +2267,21 @@ base_class: $$ = NULL_TREE; } else - $$ = build_tree_list ((tree)access_default, $$); + $$ = build_tree_list (access_default_node, type); } | base_class_access_list see_typename base_class.1 { tree type; - type = IDENTIFIER_TYPE_VALUE ($3); + 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_typedef ($3, 1)) + if (! is_aggr_type (type, 1)) $$ = NULL_TREE; else if (current_aggr == signature_type_node && (! type) && (! IS_SIGNATURE (type))) @@ -2403,7 +2293,7 @@ base_class: { sorry ("signature inheritance, base type `%s' ignored", IDENTIFIER_POINTER ($$)); - $$ = build_tree_list ((tree)access_public, $3); + $$ = build_tree_list (access_public_node, type); } else if (type && IS_SIGNATURE (type)) { @@ -2411,12 +2301,14 @@ base_class: $$ = NULL_TREE; } else - $$ = build_tree_list ((tree) $$, $3); + $$ = build_tree_list ($$, type); } ; base_class.1: - complete_type_name + typename_sub + { $$ = TYPE_MAIN_DECL ($1); } + | nonnested_type | SIGOF '(' expr ')' { if (current_aggr == signature_type_node) @@ -2424,8 +2316,7 @@ base_class.1: if (IS_AGGR_TYPE (TREE_TYPE ($3))) { sorry ("`sigof' as base signature specifier"); - /* need to return some dummy signature identifier */ - $$ = $3; + $$ = TREE_TYPE ($3); } else { @@ -2443,11 +2334,10 @@ base_class.1: { if (current_aggr == signature_type_node) { - if (IS_AGGR_TYPE (groktypename ($3))) + if (IS_AGGR_TYPE (groktypename ($3.t))) { sorry ("`sigof' as base signature specifier"); - /* need to return some dummy signature identifier */ - $$ = $3; + $$ = groktypename ($3.t); } else { @@ -2466,128 +2356,65 @@ base_class.1: base_class_access_list: VISSPEC see_typename | SCSPEC see_typename - { if ($$ != ridpointers[(int)RID_VIRTUAL]) - sorry ("non-virtual access"); - $$ = access_default_virtual; } + { if ($1 != ridpointers[(int)RID_VIRTUAL]) + cp_error ("`%D' access", $1); + $$ = access_default_virtual_node; } | base_class_access_list VISSPEC see_typename - { int err = 0; - if ($2 == access_protected) - { - warning ("`protected' access not implemented"); - $2 = access_public; - err++; - } - else if ($2 == access_public) - { - if ($1 == access_private) - { - mixed: - error ("base class cannot be public and private"); - } - else if ($1 == access_default_virtual) - $$ = access_public_virtual; - } - else /* $2 == access_private */ - { - if ($1 == access_public) - goto mixed; - else if ($1 == access_default_virtual) - $$ = access_private_virtual; - } + { + if ($1 != access_default_virtual_node) + error ("multiple access specifiers"); + else if ($2 == access_public_node) + $$ = access_public_virtual_node; + else if ($2 == access_protected_node) + $$ = access_protected_virtual_node; + else /* $2 == access_private_node */ + $$ = access_private_virtual_node; } | base_class_access_list SCSPEC see_typename { if ($2 != ridpointers[(int)RID_VIRTUAL]) - sorry ("non-virtual access"); - if ($$ == access_public) - $$ = access_public_virtual; - else if ($$ == access_private) - $$ = access_private_virtual; } + cp_error ("`%D' access", $2); + else if ($$ == access_public_node) + $$ = access_public_virtual_node; + else if ($$ == access_protected_node) + $$ = access_protected_virtual_node; + else if ($$ == access_private_node) + $$ = access_private_virtual_node; + else + error ("multiple `virtual' specifiers"); + } ; -left_curly: '{' - { tree t = $0; - push_obstacks_nochange (); - end_temporary_allocation (); - - if (! IS_AGGR_TYPE (t)) - { - t = $0 = make_lang_type (RECORD_TYPE); - TYPE_NAME (t) = get_identifier ("erroneous type"); - } - if (TYPE_SIZE (t)) - duplicate_tag_error (t); - if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t)) - { - t = make_lang_type (TREE_CODE (t)); - pushtag (TYPE_IDENTIFIER ($0), t, 0); - $0 = t; - } - pushclass (t, 0); - TYPE_BEING_DEFINED (t) = 1; - /* 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); - - if (! ANON_AGGRNAME_P (name)) - { - CLASSTYPE_INTERFACE_ONLY (t) = interface_only; - SET_CLASSTYPE_INTERFACE_UNKNOWN_X - (t, interface_unknown); - } +left_curly: + '{' + { $0 = begin_class_definition ($0); } + ; - /* Record how to set the access of this class's - virtual functions. If write_virtuals == 2 or 3, then - inline virtuals are ``extern inline''. */ - switch (write_virtuals) - { - case 0: - case 1: - needs_writing = 1; - break; - case 2: - needs_writing = !! value_member (name, pending_vtables); - break; - case 3: - needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t) - && CLASSTYPE_INTERFACE_KNOWN (t); - break; - default: - needs_writing = 0; - } - CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing; - } -#if 0 - t = TYPE_IDENTIFIER ($0); - if (t && IDENTIFIER_TEMPLATE (t)) - overload_template_name (t, 1); -#endif +self_reference: + /* empty */ + { + $$ = build_self_reference (); } ; opt.component_decl_list: - /* empty */ - { $$ = NULL_TREE; } - | 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 ((tree) access_public, $$); + $$ = build_tree_list (access_public_node, $2); else - $$ = build_tree_list ((tree) access_default, $$); + $$ = 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 = (tree) $2; + tree visspec = $2; if (current_aggr == signature_type_node) { error ("access specifier not allowed in signature"); - visspec = (tree) access_public; + visspec = access_public_node; } $$ = chainon ($$, build_tree_list (visspec, $4)); } @@ -2637,6 +2464,13 @@ component_decl: { $$ = finish_method ($$); } | ';' { $$ = NULL_TREE; } + | extension component_decl + { $$ = $2; + pedantic = $1; } + | template_header component_decl + { $$ = finish_member_template_decl ($1, $2); } + | template_header typed_declspecs ';' + { $$ = finish_member_class_template ($1, $2.t); } ; component_decl_1: @@ -2644,12 +2478,15 @@ 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, $2); } + { $$ = grok_x_components ($1.t, $2); } | declmods notype_components { $$ = grok_x_components ($1, $2); } - | notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init - { $$ = grokfield ($$, NULL_TREE, $2, $5, $3, - build_tree_list ($4, NULL_TREE)); } + | notype_declarator maybeasm maybe_attribute maybe_init + { $$ = grokfield ($$, NULL_TREE, $4, $2, + build_tree_list ($3, NULL_TREE)); } + | constructor_declarator maybeasm maybe_attribute maybe_init + { $$ = grokfield ($$, NULL_TREE, $4, $2, + build_tree_list ($3, NULL_TREE)); } | ':' expr_no_commas { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } | error @@ -2663,25 +2500,18 @@ component_decl_1: should "A::foo" be declared as a function or "A::bar" as a data member? In other words, is "bar" an after_type_declarator or a parmlist? */ - | typed_declspecs '(' parmlist ')' type_quals exception_specification_opt maybeasm maybe_attribute maybe_init + | declmods component_constructor_declarator maybeasm maybe_attribute maybe_init { tree specs, attrs; split_specs_attrs ($1, &specs, &attrs); - $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), - $3, $5); - $$ = grokfield ($$, TREE_CHAIN (specs), $6, $9, $7, - build_tree_list ($8, attrs)); } - | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt maybeasm maybe_attribute maybe_init - { tree specs, attrs; - split_specs_attrs ($1, &specs, &attrs); - $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), - empty_parms (), $3); - $$ = grokfield ($$, TREE_CHAIN (specs), $4, $7, $5, - build_tree_list ($6, attrs)); } + $$ = grokfield ($2, specs, $5, $3, + build_tree_list ($4, attrs)); } + | component_constructor_declarator maybeasm maybe_attribute maybe_init + { $$ = grokfield ($$, NULL_TREE, $4, $2, + build_tree_list ($3, NULL_TREE)); } | using_decl { $$ = do_class_using_decl ($1); } - ; -/* The case of exactly one component is handled directly by component_decl. */ +/* The case of exactly one component is handled directly by component_decl. */ /* ??? Huh? ^^^ */ components: /* empty: possibly anonymous */ @@ -2724,12 +2554,12 @@ component_declarator: ; after_type_component_declarator0: - after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init + after_type_declarator maybeasm maybe_attribute maybe_init { split_specs_attrs ($0, ¤t_declspecs, &prefix_attributes); $0 = current_declspecs; - $$ = grokfield ($$, current_declspecs, $2, $5, $3, - build_tree_list ($4, prefix_attributes)); } + $$ = grokfield ($$, current_declspecs, $4, $2, + build_tree_list ($3, prefix_attributes)); } | TYPENAME ':' expr_no_commas maybe_attribute { split_specs_attrs ($0, ¤t_declspecs, &prefix_attributes); @@ -2739,12 +2569,18 @@ after_type_component_declarator0: ; notype_component_declarator0: - notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init + notype_declarator maybeasm maybe_attribute maybe_init + { split_specs_attrs ($0, ¤t_declspecs, + &prefix_attributes); + $0 = current_declspecs; + $$ = grokfield ($$, current_declspecs, $4, $2, + build_tree_list ($3, prefix_attributes)); } + | constructor_declarator maybeasm maybe_attribute maybe_init { split_specs_attrs ($0, ¤t_declspecs, &prefix_attributes); $0 = current_declspecs; - $$ = grokfield ($$, current_declspecs, $2, $5, $3, - build_tree_list ($4, prefix_attributes)); } + $$ = grokfield ($$, current_declspecs, $4, $2, + build_tree_list ($3, prefix_attributes)); } | IDENTIFIER ':' expr_no_commas maybe_attribute { split_specs_attrs ($0, ¤t_declspecs, &prefix_attributes); @@ -2760,18 +2596,18 @@ notype_component_declarator0: ; after_type_component_declarator: - after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init - { $$ = grokfield ($$, current_declspecs, $2, $5, $3, - build_tree_list ($4, prefix_attributes)); } + after_type_declarator maybeasm maybe_attribute maybe_init + { $$ = grokfield ($$, current_declspecs, $4, $2, + build_tree_list ($3, prefix_attributes)); } | TYPENAME ':' expr_no_commas maybe_attribute { $$ = grokbitfield ($$, current_declspecs, $3); cplus_decl_attributes ($$, $4, prefix_attributes); } ; notype_component_declarator: - notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init - { $$ = grokfield ($$, current_declspecs, $2, $5, $3, - build_tree_list ($4, prefix_attributes)); } + notype_declarator maybeasm maybe_attribute maybe_init + { $$ = grokfield ($$, current_declspecs, $4, $2, + build_tree_list ($3, prefix_attributes)); } | IDENTIFIER ':' expr_no_commas maybe_attribute { $$ = grokbitfield ($$, current_declspecs, $3); cplus_decl_attributes ($$, $4, prefix_attributes); } @@ -2800,44 +2636,52 @@ enumerator: /* ANSI new-type-id (5.3.4) */ new_type_id: type_specifier_seq new_declarator - { $$ = build_decl_list ($$, $2); } - | type_specifier_seq %prec EMPTY - { $$ = build_decl_list ($$, NULL_TREE); } + { $$.t = build_decl_list ($1.t, $2); + $$.new_type_flag = $1.new_type_flag; } + | type_specifier_seq %prec EMPTY + { $$.t = build_decl_list ($1.t, NULL_TREE); + $$.new_type_flag = $1.new_type_flag; } /* GNU extension to allow arrays of arbitrary types with - non-constant dimension. */ - | '(' type_id ')' '[' expr ']' + non-constant dimension. For the use of begin_new_placement + here, see the comments in unary_expr above. */ + | '(' .begin_new_placement type_id .finish_new_placement + '[' expr ']' { if (pedantic) pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new"); - $$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5); - $$ = build_decl_list (TREE_PURPOSE ($2), $$); + $$.t = build_parse_node (ARRAY_REF, TREE_VALUE ($3.t), $6); + $$.t = build_decl_list (TREE_PURPOSE ($3.t), $$.t); + $$.new_type_flag = $3.new_type_flag; } ; -type_quals: - /* empty */ %prec EMPTY +cv_qualifiers: + /* empty */ %prec EMPTY { $$ = NULL_TREE; } - | type_quals TYPE_QUAL + | cv_qualifiers CV_QUALIFIER { $$ = decl_tree_cons (NULL_TREE, $2, $$); } ; -nonempty_type_quals: - TYPE_QUAL - { $$ = IDENTIFIER_AS_LIST ($$); } - | nonempty_type_quals TYPE_QUAL - { $$ = decl_tree_cons (NULL_TREE, $2, $$); } +nonempty_cv_qualifiers: + CV_QUALIFIER + { $$.t = IDENTIFIER_AS_LIST ($1); + $$.new_type_flag = 0; } + | nonempty_cv_qualifiers CV_QUALIFIER + { $$.t = decl_tree_cons (NULL_TREE, $2, $1.t); + $$.new_type_flag = $1.new_type_flag; } ; /* These rules must follow the rules for function declarations and component declarations. That way, longer rules are preferred. */ suspend_mom: - { $$ = suspend_momentary (); } + /* empty */ + { $$ = suspend_momentary (); } /* An expression which will not live on the momentary obstack. */ nonmomentary_expr: - suspend_mom expr - { resume_momentary ((int) $1); $$ = $2; } + suspend_mom expr + { resume_momentary ((int) $1); $$ = $2; } ; /* An expression which will not live on the momentary obstack. */ @@ -2855,72 +2699,90 @@ maybe_parmlist: /* A declarator that is allowed only after an explicit typespec. */ /* may all be followed by prec '.' */ after_type_declarator: - '*' nonempty_type_quals after_type_declarator %prec UNARY - { $$ = make_pointer_declarator ($2, $3); } - | '&' nonempty_type_quals after_type_declarator %prec UNARY - { $$ = make_reference_declarator ($2, $3); } + '*' nonempty_cv_qualifiers after_type_declarator %prec UNARY + { $$ = make_pointer_declarator ($2.t, $3); } + | '&' nonempty_cv_qualifiers after_type_declarator %prec UNARY + { $$ = make_reference_declarator ($2.t, $3); } | '*' after_type_declarator %prec UNARY { $$ = make_pointer_declarator (NULL_TREE, $2); } | '&' after_type_declarator %prec UNARY { $$ = make_reference_declarator (NULL_TREE, $2); } - | ptr_to_mem type_quals after_type_declarator + | ptr_to_mem cv_qualifiers after_type_declarator { tree arg = make_pointer_declarator ($2, $3); $$ = build_parse_node (SCOPE_REF, $1, arg); } | direct_after_type_declarator ; -qualified_type_name: - type_name %prec EMPTY +nonnested_type: + type_name %prec EMPTY { - /* 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 ($$)) + if (TREE_CODE ($1) == IDENTIFIER_NODE) { - tree t = lookup_name ($$, -2); - if (t) - pushdecl_class_level (t); + $$ = 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 ($$); + } } + else + $$ = $1; + } + | global_scope type_name + { + if (TREE_CODE ($2) == IDENTIFIER_NODE) + $$ = IDENTIFIER_GLOBAL_VALUE ($2); + else + $$ = $2; + got_scope = NULL_TREE; } + ; + +complete_type_name: + nonnested_type | nested_type + | global_scope nested_type + { $$ = $2; } ; nested_type: - nested_name_specifier type_name %prec EMPTY - { $$ = $2; } + nested_name_specifier type_name %prec EMPTY + { $$ = get_type_decl ($2); } ; direct_after_type_declarator: - direct_after_type_declarator maybe_parmlist type_quals %prec '.' - { $$ = build_parse_node (CALL_EXPR, $$, $2, $3); } + 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 (TREE_TYPE ($$), 3); + | 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 + | type_name %prec EMPTY ; /* A declarator allowed whether or not there has been an explicit typespec. These cannot redeclare a typedef-name. */ notype_declarator: - '*' nonempty_type_quals notype_declarator %prec UNARY - { $$ = make_pointer_declarator ($2, $3); } - | '&' nonempty_type_quals notype_declarator %prec UNARY - { $$ = make_reference_declarator ($2, $3); } + '*' nonempty_cv_qualifiers notype_declarator %prec UNARY + { $$ = make_pointer_declarator ($2.t, $3); } + | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY + { $$ = make_reference_declarator ($2.t, $3); } | '*' notype_declarator %prec UNARY { $$ = make_pointer_declarator (NULL_TREE, $2); } | '&' notype_declarator %prec UNARY { $$ = make_reference_declarator (NULL_TREE, $2); } - | ptr_to_mem type_quals notype_declarator + | ptr_to_mem cv_qualifiers notype_declarator { tree arg = make_pointer_declarator ($2, $3); $$ = build_parse_node (SCOPE_REF, $1, arg); } @@ -2928,15 +2790,15 @@ notype_declarator: ; complex_notype_declarator: - '*' nonempty_type_quals notype_declarator %prec UNARY - { $$ = make_pointer_declarator ($2, $3); } - | '&' nonempty_type_quals notype_declarator %prec UNARY - { $$ = make_reference_declarator ($2, $3); } + '*' nonempty_cv_qualifiers notype_declarator %prec UNARY + { $$ = make_pointer_declarator ($2.t, $3); } + | '&' nonempty_cv_qualifiers notype_declarator %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 type_quals notype_declarator + | ptr_to_mem cv_qualifiers notype_declarator { tree arg = make_pointer_declarator ($2, $3); $$ = build_parse_node (SCOPE_REF, $1, arg); } @@ -2944,8 +2806,8 @@ complex_notype_declarator: ; complex_direct_notype_declarator: - direct_notype_declarator maybe_parmlist type_quals %prec '.' - { $$ = build_parse_node (CALL_EXPR, $$, $2, $3); } + direct_notype_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.' + { $$ = make_call_declarator ($$, $2, $3, $4); } | '(' complex_notype_declarator ')' { $$ = $2; } | direct_notype_declarator '[' nonmomentary_expr ']' @@ -2953,24 +2815,44 @@ complex_direct_notype_declarator: | direct_notype_declarator '[' ']' { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } | notype_qualified_id - { if (TREE_TYPE (OP0 ($$)) != current_class_type) + { 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 (TREE_TYPE (OP0 ($$)), 3); + push_nested_class (OP0 ($1), 3); + TREE_COMPLEXITY ($1) = current_class_depth; + } + } + | 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; } } ; qualified_id: - nested_name_specifier unqualified_id + nested_name_specifier unqualified_id { got_scope = NULL_TREE; $$ = build_parse_node (SCOPE_REF, $$, $2); } + | nested_name_specifier object_template_id + { got_scope = NULL_TREE; + $$ = build_parse_node (SCOPE_REF, $1, $2); } ; notype_qualified_id: - nested_name_specifier notype_unqualified_id + nested_name_specifier notype_unqualified_id { got_scope = NULL_TREE; $$ = build_parse_node (SCOPE_REF, $$, $2); } + | nested_name_specifier object_template_id + { got_scope = NULL_TREE; + $$ = build_parse_node (SCOPE_REF, $1, $2); } ; overqualified_id: @@ -2981,33 +2863,58 @@ overqualified_id: functional_cast: typespec '(' nonnull_exprlist ')' - { $$ = build_functional_cast ($$, $3); } + { $$ = build_functional_cast ($1.t, $3); } | typespec '(' expr_or_declarator ')' - { $$ = reparse_decl_as_expr ($$, $3); } - | typespec fcast_or_absdcl %prec EMPTY - { $$ = reparse_absdcl_as_expr ($$, $2); } + { $$ = reparse_decl_as_expr ($1.t, $3); } + | typespec fcast_or_absdcl %prec EMPTY + { $$ = reparse_absdcl_as_expr ($1.t, $2); } ; type_name: TYPENAME - | template_type %prec EMPTY + | SELFNAME + | template_type %prec EMPTY ; nested_name_specifier: nested_name_specifier_1 | nested_name_specifier nested_name_specifier_1 { $$ = $2; } + | nested_name_specifier TEMPLATE explicit_template_type SCOPE + { got_scope = $$ = make_typename_type ($1, $3); } ; /* Why the @#$%^& do type_name and notype_identifier need to be expanded inline here?!? (jason) */ nested_name_specifier_1: TYPENAME SCOPE - { got_scope = TREE_TYPE ($$); } + { + 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 ($$); + } + got_scope = $$ = TYPE_MAIN_VARIANT (TREE_TYPE ($$)); + } + | SELFNAME SCOPE + { + if (TREE_CODE ($1) == IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$ = TREE_TYPE ($$); + } | NSNAME SCOPE - { got_scope = $$; } + { + if (TREE_CODE ($$) == IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$; + } | template_type SCOPE - { got_scope = TREE_TYPE ($$); } + { got_scope = $$ = complete_type (TREE_TYPE ($1)); } /* These break 'const i;' | IDENTIFIER SCOPE { @@ -3020,15 +2927,106 @@ nested_name_specifier_1: { goto failed_scope; } */ ; -complete_type_name: - qualified_type_name - | global_scope qualified_type_name +typename_sub: + typename_sub0 + | global_scope typename_sub0 { $$ = $2; } ; +typename_sub0: + typename_sub1 identifier %prec EMPTY + { + if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't') + $$ = make_typename_type ($1, $2); + else if (TREE_CODE ($2) == IDENTIFIER_NODE) + cp_error ("`%T' is not a class or namespace", $2); + else + { + $$ = $2; + if (TREE_CODE ($$) == TYPE_DECL) + $$ = TREE_TYPE ($$); + } + } + | typename_sub1 template_type %prec EMPTY + { $$ = TREE_TYPE ($2); } + | typename_sub1 explicit_template_type %prec EMPTY + { $$ = make_typename_type ($1, $2); } + | typename_sub1 TEMPLATE explicit_template_type %prec EMPTY + { $$ = make_typename_type ($1, $3); } + ; + +typename_sub1: + typename_sub2 + { + if (TREE_CODE ($1) == IDENTIFIER_NODE) + cp_error ("`%T' is not a class or namespace", $1); + } + | typename_sub1 typename_sub2 + { + if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't') + $$ = make_typename_type ($1, $2); + else if (TREE_CODE ($2) == IDENTIFIER_NODE) + cp_error ("`%T' is not a class or namespace", $2); + else + { + $$ = $2; + if (TREE_CODE ($$) == TYPE_DECL) + $$ = TREE_TYPE ($$); + } + } + | typename_sub1 explicit_template_type SCOPE + { got_scope = $$ = make_typename_type ($1, $2); } + | typename_sub1 TEMPLATE explicit_template_type SCOPE + { got_scope = $$ = make_typename_type ($1, $3); } + ; + +typename_sub2: + TYPENAME SCOPE + { + if (TREE_CODE ($1) != IDENTIFIER_NODE) + $1 = lastiddecl; + + /* Retrieve the type for the identifier, which might involve + some computation. */ + got_scope = $$ = complete_type (IDENTIFIER_TYPE_VALUE ($1)); + + if ($$ == error_mark_node) + cp_error ("`%T' is not a class or namespace", $1); + } + | SELFNAME SCOPE + { + if (TREE_CODE ($1) != IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$ = complete_type (TREE_TYPE ($$)); + } + | template_type SCOPE + { got_scope = $$ = complete_type (TREE_TYPE ($$)); } + | PTYPENAME SCOPE + | IDENTIFIER SCOPE + | NSNAME SCOPE + { + if (TREE_CODE ($$) == IDENTIFIER_NODE) + $$ = lastiddecl; + got_scope = $$; + } + ; + +explicit_template_type: + identifier '<' template_arg_list_opt template_close_bracket + { $$ = build_min_nt (TEMPLATE_ID_EXPR, $1, $3); } + ; + complex_type_name: - nested_type - | global_scope qualified_type_name + global_scope type_name + { + if (TREE_CODE ($2) == IDENTIFIER_NODE) + $$ = IDENTIFIER_GLOBAL_VALUE ($2); + else + $$ = $2; + got_scope = NULL_TREE; + } + | nested_type + | global_scope nested_type { $$ = $2; } ; @@ -3040,7 +3038,7 @@ ptr_to_mem: ; /* All uses of explicit global scope must go through this nonterminal so - that got_scope will be set before yylex is called to get the next token. */ + that got_scope will be set before yylex is called to get the next token. */ global_scope: SCOPE { got_scope = void_type_node; } @@ -3048,23 +3046,23 @@ global_scope: /* ANSI new-declarator (5.3.4) */ new_declarator: - '*' type_quals new_declarator + '*' cv_qualifiers new_declarator { $$ = make_pointer_declarator ($2, $3); } - | '*' type_quals %prec EMPTY + | '*' cv_qualifiers %prec EMPTY { $$ = make_pointer_declarator ($2, NULL_TREE); } - | '&' type_quals new_declarator %prec EMPTY + | '&' cv_qualifiers new_declarator %prec EMPTY { $$ = make_reference_declarator ($2, $3); } - | '&' type_quals %prec EMPTY + | '&' cv_qualifiers %prec EMPTY { $$ = make_reference_declarator ($2, NULL_TREE); } - | ptr_to_mem type_quals %prec EMPTY + | ptr_to_mem cv_qualifiers %prec EMPTY { tree arg = make_pointer_declarator ($2, NULL_TREE); $$ = build_parse_node (SCOPE_REF, $1, arg); } - | ptr_to_mem type_quals new_declarator + | ptr_to_mem cv_qualifiers new_declarator { tree arg = make_pointer_declarator ($2, $3); $$ = build_parse_node (SCOPE_REF, $1, arg); } - | direct_new_declarator %prec EMPTY + | direct_new_declarator %prec EMPTY ; /* ANSI direct-new-declarator (5.3.4) */ @@ -3077,31 +3075,31 @@ direct_new_declarator: /* ANSI abstract-declarator (8.1) */ absdcl: - '*' nonempty_type_quals absdcl - { $$ = make_pointer_declarator ($2, $3); } + '*' nonempty_cv_qualifiers absdcl + { $$ = make_pointer_declarator ($2.t, $3); } | '*' absdcl { $$ = make_pointer_declarator (NULL_TREE, $2); } - | '*' nonempty_type_quals %prec EMPTY - { $$ = make_pointer_declarator ($2, NULL_TREE); } - | '*' %prec EMPTY + | '*' nonempty_cv_qualifiers %prec EMPTY + { $$ = make_pointer_declarator ($2.t, NULL_TREE); } + | '*' %prec EMPTY { $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); } - | '&' nonempty_type_quals absdcl - { $$ = make_reference_declarator ($2, $3); } + | '&' nonempty_cv_qualifiers absdcl + { $$ = make_reference_declarator ($2.t, $3); } | '&' absdcl { $$ = make_reference_declarator (NULL_TREE, $2); } - | '&' nonempty_type_quals %prec EMPTY - { $$ = make_reference_declarator ($2, NULL_TREE); } - | '&' %prec EMPTY + | '&' nonempty_cv_qualifiers %prec EMPTY + { $$ = make_reference_declarator ($2.t, NULL_TREE); } + | '&' %prec EMPTY { $$ = make_reference_declarator (NULL_TREE, NULL_TREE); } - | ptr_to_mem type_quals %prec EMPTY + | ptr_to_mem cv_qualifiers %prec EMPTY { tree arg = make_pointer_declarator ($2, NULL_TREE); $$ = build_parse_node (SCOPE_REF, $1, arg); } - | ptr_to_mem type_quals absdcl + | ptr_to_mem cv_qualifiers absdcl { tree arg = make_pointer_declarator ($2, $3); $$ = build_parse_node (SCOPE_REF, $1, arg); } - | direct_abstract_declarator %prec EMPTY + | direct_abstract_declarator %prec EMPTY ; /* ANSI direct-abstract-declarator (8.1) */ @@ -3110,20 +3108,20 @@ direct_abstract_declarator: { $$ = $2; } /* `(typedef)1' is `int'. */ | PAREN_STAR_PAREN - | direct_abstract_declarator '(' parmlist ')' type_quals %prec '.' - { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } - | direct_abstract_declarator LEFT_RIGHT type_quals %prec '.' - { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); } + | direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt %prec '.' + { $$ = make_call_declarator ($$, $3, $5, $6); } + | direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt %prec '.' + { $$ = make_call_declarator ($$, empty_parms (), $3, $4); } | direct_abstract_declarator '[' nonmomentary_expr ']' %prec '.' { $$ = build_parse_node (ARRAY_REF, $$, $3); } | direct_abstract_declarator '[' ']' %prec '.' { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } - | '(' complex_parmlist ')' type_quals %prec '.' - { $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, $4); } - | regcast_or_absdcl type_quals %prec '.' - { TREE_OPERAND ($$, 2) = $2; } - | fcast_or_absdcl type_quals %prec '.' - { TREE_OPERAND ($$, 2) = $2; } + | '(' complex_parmlist ')' cv_qualifiers exception_specification_opt %prec '.' + { $$ = make_call_declarator (NULL_TREE, $2, $4, $5); } + | regcast_or_absdcl cv_qualifiers exception_specification_opt %prec '.' + { set_quals_and_spec ($$, $2, $3); } + | fcast_or_absdcl cv_qualifiers exception_specification_opt %prec '.' + { set_quals_and_spec ($$, $2, $3); } | '[' nonmomentary_expr ']' %prec '.' { $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); } | '[' ']' %prec '.' @@ -3141,25 +3139,8 @@ stmts: | stmts errstmt ; -errstmt: error ';' - ; - -/* build the LET_STMT node before parsing its contents, - so that any LET_STMTs within the context can have their display pointers - set up to point at this one. */ - -.pushlevel: /* empty */ - { emit_line_note (input_filename, lineno); - pushlevel (0); - clear_last_expr (); - push_momentary (); - expand_start_bindings (0); } - ; - -.poplevel: /* empty */ - { expand_end_bindings (getdecls (), kept_level_p (), 1); - $$ = poplevel (kept_level_p (), 1, 0); - pop_momentary (); } +errstmt: + error ';' ; /* Read zero or more forward-declarations for labels @@ -3196,29 +3177,35 @@ compstmt_or_error: | error compstmt ; -compstmt: '{' .pushlevel compstmtend .poplevel - { $$ = $4; } +compstmt: + '{' + { $$ = begin_compound_stmt (0); } + compstmtend + { $$ = finish_compound_stmt (0, $2); } ; simple_if: IF - { cond_stmt_keyword = "if"; } - .pushlevel paren_cond_or_null - { emit_line_note (input_filename, lineno); - expand_start_cond ($4, 0); } - implicitly_scoped_stmt + { + $$ = begin_if_stmt (); + cond_stmt_keyword = "if"; + } + paren_cond_or_null + { finish_if_stmt_cond ($3, $2); } + implicitly_scoped_stmt + { $$ = finish_then_clause ($2); } ; implicitly_scoped_stmt: compstmt - { finish_stmt (); } - | .pushlevel simple_stmt .poplevel - { $$ = $3; } + | { $$ = begin_compound_stmt (0); } + simple_stmt + { $$ = finish_compound_stmt (0, $1); } ; stmt: compstmt - { finish_stmt (); } + {} | simple_stmt ; @@ -3226,234 +3213,93 @@ simple_stmt: decl { finish_stmt (); } | expr ';' - { - tree expr = $1; - emit_line_note (input_filename, lineno); - /* Do default conversion if safe and possibly important, - in case within ({...}). */ - if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE - && lvalue_p (expr)) - || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE) - expr = default_conversion (expr); - cplus_expand_expr_stmt (expr); - clear_momentary (); - finish_stmt (); } + { finish_expr_stmt ($1); } | simple_if ELSE - { expand_start_else (); } + { begin_else_clause (); } implicitly_scoped_stmt - { expand_end_cond (); } - .poplevel - { finish_stmt (); } - | simple_if %prec IF - { expand_end_cond (); - expand_end_bindings (getdecls (), kept_level_p (), 1); - poplevel (kept_level_p (), 1, 0); - pop_momentary (); - finish_stmt (); } + { + finish_else_clause ($1); + finish_if_stmt (); + } + | simple_if %prec IF + { finish_if_stmt (); } | WHILE - { emit_nop (); - emit_line_note (input_filename, lineno); - expand_start_loop (1); - cond_stmt_keyword = "while"; } - .pushlevel paren_cond_or_null - { expand_exit_loop_if_false (0, $4); } - already_scoped_stmt .poplevel - { expand_end_loop (); - finish_stmt (); } + { + $$ = begin_while_stmt (); + cond_stmt_keyword = "while"; + } + paren_cond_or_null + { finish_while_stmt_cond ($3, $2); } + already_scoped_stmt + { finish_while_stmt ($2); } | DO - { emit_nop (); - emit_line_note (input_filename, lineno); - expand_start_loop_continue_elsewhere (1); } + { $$ = begin_do_stmt (); } implicitly_scoped_stmt WHILE - { expand_loop_continue_here (); - cond_stmt_keyword = "do"; } + { + finish_do_body ($2); + cond_stmt_keyword = "do"; + } paren_expr_or_null ';' - { emit_line_note (input_filename, lineno); - expand_exit_loop_if_false (0, $6); - expand_end_loop (); - clear_momentary (); - finish_stmt (); } + { finish_do_stmt ($6, $2); } | FOR - { emit_line_note (input_filename, lineno); - if (flag_new_for_scope > 0) - { - /* Conditionalize .pushlevel */ - pushlevel (0); - note_level_for_for (); - clear_last_expr (); - push_momentary (); - expand_start_bindings (0); - } - } + { $$ = begin_for_stmt (); } '(' for.init.statement - { emit_nop (); - emit_line_note (input_filename, lineno); - expand_start_loop_continue_elsewhere (1); } - .pushlevel xcond ';' - { emit_line_note (input_filename, lineno); - if ($7) expand_exit_loop_if_false (0, $7); } + { finish_for_init_stmt ($2); } + xcond ';' + { finish_for_cond ($6, $2); } xexpr ')' - /* Don't let the tree nodes for $10 be discarded - by clear_momentary during the parsing of the next stmt. */ - { push_momentary (); } - already_scoped_stmt .poplevel - { emit_line_note (input_filename, lineno); - expand_loop_continue_here (); - if ($10) cplus_expand_expr_stmt ($10); - pop_momentary (); - expand_end_loop (); - if (flag_new_for_scope > 0) - { - expand_end_bindings (getdecls (), kept_level_p (), 1); - poplevel (kept_level_p (), 1, 0); - pop_momentary (); - } - finish_stmt (); } - | SWITCH .pushlevel '(' condition ')' - { emit_line_note (input_filename, lineno); - c_expand_start_case ($4); - push_switch (); - /* Don't let the tree nodes for $4 be discarded by - clear_momentary during the parsing of the next stmt. */ - push_momentary (); } + { finish_for_expr ($9, $2); } + already_scoped_stmt + { finish_for_stmt ($9, $2); } + | SWITCH + { begin_switch_stmt (); } + '(' condition ')' + { $$ = finish_switch_cond ($4); } implicitly_scoped_stmt - { expand_end_case ($4); - pop_momentary (); - pop_switch (); } - .poplevel - { finish_stmt (); } + { finish_switch_stmt ($4, $6); } | CASE expr_no_commas ':' - { register tree value = check_cp_case_value ($2); - register tree label - = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - - if (value != error_mark_node) - { - tree duplicate; - int success = pushcase (value, convert_and_check, - label, &duplicate); - if (success == 1) - cp_error ("case label `%E' not within a switch statement", $2); - else if (success == 2) - { - cp_error ("duplicate case value `%E'", $2); - cp_error_at ("previously used here", duplicate); - } - else if (success == 3) - warning ("case value out of range"); - else if (success == 5) - cp_error ("case label `%E' within scope of cleanup or variable array", $2); - } - define_case_label (label); - } + { finish_case_label ($2, NULL_TREE); } stmt | CASE expr_no_commas ELLIPSIS expr_no_commas ':' - { register tree value1 = check_cp_case_value ($2); - register tree value2 = check_cp_case_value ($4); - register tree label - = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - - if (pedantic) - pedwarn ("ANSI C++ forbids range expressions in switch statement"); - if (value1 != error_mark_node - && value2 != error_mark_node) - { - tree duplicate; - int success = pushcase_range (value1, value2, - convert_and_check, label, - &duplicate); - if (success == 1) - error ("case label not within a switch statement"); - else if (success == 2) - { - error ("duplicate (or overlapping) case value"); - error_with_decl (duplicate, "this is the first entry overlapping that value"); - } - else if (success == 3) - warning ("case value out of range"); - else if (success == 4) - warning ("empty range specified"); - else if (success == 5) - error ("case label within scope of cleanup or variable array"); - } - define_case_label (label); - } + { finish_case_label ($2, $4); } stmt | DEFAULT ':' - { - tree duplicate; - register tree label - = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - int success = pushcase (NULL_TREE, 0, label, &duplicate); - if (success == 1) - error ("default label not within a switch statement"); - else if (success == 2) - { - error ("multiple default labels in one switch"); - error_with_decl (duplicate, "this is the first default label"); - } - define_case_label (NULL_TREE); - } + { finish_case_label (NULL_TREE, NULL_TREE); } stmt | BREAK ';' - { emit_line_note (input_filename, lineno); - if ( ! expand_exit_something ()) - error ("break statement not within loop or switch"); } + { finish_break_stmt (); } | CONTINUE ';' - { emit_line_note (input_filename, lineno); - if (! expand_continue_loop (0)) - error ("continue statement not within a loop"); } + { finish_continue_stmt (); } | RETURN ';' - { emit_line_note (input_filename, lineno); - c_expand_return (NULL_TREE); } + { finish_return_stmt (NULL_TREE); } | RETURN expr ';' - { emit_line_note (input_filename, lineno); - c_expand_return ($2); - finish_stmt (); - } - | asm_keyword maybe_type_qual '(' string ')' ';' - { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - emit_line_note (input_filename, lineno); - expand_asm ($4); - finish_stmt (); + { finish_return_stmt ($2); } + | asm_keyword maybe_cv_qualifier '(' string ')' ';' + { + finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE, + NULL_TREE); } /* This is the case with just output operands. */ - | asm_keyword maybe_type_qual '(' string ':' asm_operands ')' ';' - { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - emit_line_note (input_filename, lineno); - c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE, - $2 == ridpointers[(int)RID_VOLATILE], - input_filename, lineno); - finish_stmt (); + | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';' + { + finish_asm_stmt ($2, $4, $6, NULL_TREE, + NULL_TREE); } /* This is the case with input operands as well. */ - | asm_keyword maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';' - { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - emit_line_note (input_filename, lineno); - c_expand_asm_operands ($4, $6, $8, NULL_TREE, - $2 == ridpointers[(int)RID_VOLATILE], - input_filename, lineno); - finish_stmt (); - } + | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ')' ';' + { finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); } /* This is the case with clobbered registers as well. */ - | asm_keyword maybe_type_qual '(' string ':' asm_operands ':' + | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ':' asm_clobbers ')' ';' - { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - emit_line_note (input_filename, lineno); - c_expand_asm_operands ($4, $6, $8, $10, - $2 == ridpointers[(int)RID_VOLATILE], - input_filename, lineno); - finish_stmt (); - } + { finish_asm_stmt ($2, $4, $6, $8, $10); } | GOTO '*' expr ';' - { emit_line_note (input_filename, lineno); - expand_computed_goto ($3); } + { + if (pedantic) + pedwarn ("ANSI C++ forbids computed gotos"); + finish_goto_stmt ($3); + } | GOTO identifier ';' - { tree decl; - emit_line_note (input_filename, lineno); - decl = lookup_label ($2); - TREE_USED (decl) = 1; - expand_goto (decl); } + { finish_goto_stmt ($2); } | label_colon stmt { finish_stmt (); } | label_colon '}' @@ -3463,6 +3309,10 @@ simple_stmt: | ';' { finish_stmt (); } | try_block + | using_directive + | namespace_using_decl + { do_local_using_decl ($1); } + | namespace_alias ; function_try_block: @@ -3472,40 +3322,45 @@ function_try_block: store_parm_decls (); expand_start_early_try_stmts (); } - ctor_initializer_opt compstmt_or_error - { expand_end_try_stmts (); - expand_start_all_catch (); } + ctor_initializer_opt compstmt + { + 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, 0); + finish_function (lineno, (int)$3, nested); } ; try_block: TRY - { expand_start_try_stmts (); } + { $$ = begin_try_block (); } compstmt - { expand_end_try_stmts (); - expand_start_all_catch (); } + { finish_try_block ($2); } handler_seq - { expand_end_all_catch (); } + { finish_handler_sequence ($2); } ; handler_seq: - /* empty */ - | handler_seq CATCH .pushlevel - { dont_allow_type_definitions = "inside exception declarations"; } - handler_args - { dont_allow_type_definitions = 0; } + handler + | handler_seq handler + ; + +handler: + CATCH + { $$ = begin_handler(); } + handler_args + { finish_handler_parms ($2); } compstmt - { expand_end_catch_block (); } - .poplevel + { finish_handler ($2); } ; type_specifier_seq: - typed_typespecs %prec EMPTY - | nonempty_type_quals %prec EMPTY + typed_typespecs %prec EMPTY + | nonempty_cv_qualifiers %prec EMPTY ; handler_args: @@ -3513,17 +3368,22 @@ handler_args: { expand_start_catch_block (NULL_TREE, NULL_TREE); } /* This doesn't allow reference parameters, the below does. | '(' type_specifier_seq absdcl ')' - { expand_start_catch_block ($2, $3); } + { check_for_new_type ("inside exception declarations", $2); + expand_start_catch_block ($2.t, $3); } | '(' type_specifier_seq ')' - { expand_start_catch_block ($2, NULL_TREE); } + { check_for_new_type ("inside exception declarations", $2); + expand_start_catch_block ($2.t, NULL_TREE); } | '(' type_specifier_seq notype_declarator ')' - { expand_start_catch_block ($2, $3); } + { check_for_new_type ("inside exception declarations", $2); + expand_start_catch_block ($2.t, $3); } | '(' typed_typespecs after_type_declarator ')' - { expand_start_catch_block ($2, $3); } - This allows reference parameters... */ + { check_for_new_type ("inside exception declarations", $2); + expand_start_catch_block ($2.t, $3); } + This allows reference parameters... */ | '(' parm ')' - { expand_start_catch_block (TREE_PURPOSE ($2), - TREE_VALUE ($2)); } + { check_for_new_type ("inside exception declarations", $2); + expand_start_catch_block (TREE_PURPOSE ($2.t), + TREE_VALUE ($2.t)); } ; label_colon: @@ -3531,13 +3391,15 @@ label_colon: { tree label; do_label: label = define_label (input_filename, lineno, $1); - if (label) + if (label && ! minimal_parse_mode) expand_label (label); } | PTYPENAME ':' { goto do_label; } | TYPENAME ':' { goto do_label; } + | SELFNAME ':' + { goto do_label; } ; for.init.statement: @@ -3545,20 +3407,23 @@ for.init.statement: { if ($1) cplus_expand_expr_stmt ($1); } | decl | '{' compstmtend + { if (pedantic) + pedwarn ("ANSI C++ forbids compound statements inside for initializations"); + } ; /* Either a type-qualifier or nothing. First thing in an `asm' statement. */ -maybe_type_qual: - /* empty */ +maybe_cv_qualifier: + /* empty */ { emit_line_note (input_filename, lineno); $$ = NULL_TREE; } - | TYPE_QUAL + | CV_QUALIFIER { emit_line_note (input_filename, lineno); } ; xexpr: - /* empty */ + /* empty */ { $$ = NULL_TREE; } | expr | error @@ -3567,7 +3432,8 @@ xexpr: /* These are the operands other than the first string and colon in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */ -asm_operands: /* empty */ +asm_operands: + /* empty */ { $$ = NULL_TREE; } | nonnull_asm_operands ; @@ -3596,69 +3462,39 @@ asm_clobbers: In C++, declaring a function with no parameters means that that function takes *no* parameters. */ -parmlist: /* empty */ +parmlist: + /* empty */ { - if (strict_prototype) - $$ = void_list_node; - else - $$ = NULL_TREE; + $$ = empty_parms(); } | complex_parmlist | type_id - { $$ = tree_cons (NULL_TREE, $$, void_list_node); - TREE_PARMLIST ($$) = 1; } + { $$ = finish_parmlist (build_tree_list (NULL_TREE, $1.t), 0); + check_for_new_type ("inside parameter list", $1); } ; /* This nonterminal does not include the common sequence '(' type_id ')', as it is ambiguous and must be disambiguated elsewhere. */ complex_parmlist: parms - { - $$ = chainon ($$, void_list_node); - TREE_PARMLIST ($$) = 1; - } + { $$ = finish_parmlist ($$, 0); } | parms_comma ELLIPSIS - { - TREE_PARMLIST ($$) = 1; - } + { $$ = finish_parmlist ($1, 1); } /* C++ allows an ellipsis without a separating ',' */ | parms ELLIPSIS - { - TREE_PARMLIST ($$) = 1; - } + { $$ = finish_parmlist ($1, 1); } | type_id ELLIPSIS - { - $$ = build_tree_list (NULL_TREE, $$); - TREE_PARMLIST ($$) = 1; - } + { $$ = finish_parmlist (build_tree_list (NULL_TREE, + $1.t), 1); } | ELLIPSIS - { - /* ARM $8.2.5 has this as a boxed-off comment. */ - if (pedantic) - warning ("use of `...' without a first argument is non-portable"); - $$ = NULL_TREE; - } - | TYPENAME_ELLIPSIS - { - TREE_PARMLIST ($$) = 1; - } - | parms TYPENAME_ELLIPSIS - { - TREE_PARMLIST ($$) = 1; - } - | type_id TYPENAME_ELLIPSIS - { - $$ = build_tree_list (NULL_TREE, $$); - TREE_PARMLIST ($$) = 1; - } + { $$ = finish_parmlist (NULL_TREE, 1); } | parms ':' { /* This helps us recover from really nasty parse errors, for example, a missing right parenthesis. */ yyerror ("possibly missing ')'"); - $$ = chainon ($$, void_list_node); - TREE_PARMLIST ($$) = 1; + $$ = finish_parmlist ($1, 0); yyungetc (':', 0); yychar = ')'; } @@ -3668,21 +3504,37 @@ complex_parmlist: parse errors, for example, a missing right parenthesis. */ yyerror ("possibly missing ')'"); - $$ = tree_cons (NULL_TREE, $$, void_list_node); - TREE_PARMLIST ($$) = 1; + $$ = finish_parmlist (build_tree_list (NULL_TREE, + $1.t), 0); yyungetc (':', 0); yychar = ')'; } ; +/* A default argument to a */ +defarg: + '=' + { maybe_snarf_defarg (); } + defarg1 + { $$ = $3; } + ; + +defarg1: + DEFARG + | init + ; + /* A nonempty list of parameter declarations or type names. */ parms: named_parm - { $$ = build_tree_list (NULL_TREE, $$); } - | parm '=' init - { $$ = build_tree_list ($3, $$); } + { check_for_new_type ("in a parameter list", $1); + $$ = build_tree_list (NULL_TREE, $1.t); } + | parm defarg + { check_for_new_type ("in a parameter list", $1); + $$ = build_tree_list ($2, $1.t); } | parms_comma full_parm - { $$ = chainon ($$, $2); } + { check_for_new_type ("in a parameter list", $2); + $$ = chainon ($$, $2.t); } | parms_comma bad_parm { $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); } | parms_comma bad_parm '=' init @@ -3692,80 +3544,58 @@ parms: parms_comma: parms ',' | type_id ',' - { $$ = build_tree_list (NULL_TREE, $$); } + { check_for_new_type ("in a parameter list", $1); + $$ = build_tree_list (NULL_TREE, $1.t); } ; /* A single parameter declaration or parameter type name, - as found in a parmlist. The first four cases make up for 10% - of the time spent parsing C++. We cannot use them because - of `int id[]' which won't get parsed properly. */ + as found in a parmlist. */ named_parm: -/* - typed_declspecs dont_see_typename '*' IDENTIFIER - { tree specs = strip_attrs ($1); - $$ = build_tree_list (specs, build_parse_node (INDIRECT_REF, $4)); - see_typename (); } - | typed_declspecs dont_see_typename '&' IDENTIFIER - { tree specs = strip_attrs ($1); - $$ = build_tree_list (specs, build_parse_node (ADDR_EXPR, $4)); - see_typename (); } - | TYPENAME IDENTIFIER - { $$ = build_tree_list (get_decl_list ($$), $2); } - | TYPESPEC IDENTIFIER - { $$ = build_tree_list (get_decl_list ($$), $2); } - | */ /* Here we expand typed_declspecs inline to avoid mis-parsing of TYPESPEC IDENTIFIER. */ typed_declspecs1 declarator - { tree specs = strip_attrs ($1); - $$ = build_tree_list (specs, $2); } + { tree specs = strip_attrs ($1.t); + $$.new_type_flag = $1.new_type_flag; + $$.t = build_tree_list (specs, $2); } | typed_typespecs declarator - { $$ = build_tree_list ($$, $2); } + { $$.t = build_tree_list ($1.t, $2); + $$.new_type_flag = $1.new_type_flag; } | typespec declarator - { $$ = build_tree_list (get_decl_list ($$), $2); } + { $$.t = build_tree_list (get_decl_list ($1.t), $2); + $$.new_type_flag = $1.new_type_flag; } | typed_declspecs1 absdcl - { tree specs = strip_attrs ($1); - $$ = build_tree_list (specs, $2); } - | typed_declspecs1 %prec EMPTY - { tree specs = strip_attrs ($1); - $$ = build_tree_list (specs, NULL_TREE); } + { tree specs = strip_attrs ($1.t); + $$.t = build_tree_list (specs, $2); + $$.new_type_flag = $1.new_type_flag; } + | typed_declspecs1 %prec EMPTY + { tree specs = strip_attrs ($1.t); + $$.t = build_tree_list (specs, NULL_TREE); + $$.new_type_flag = $1.new_type_flag; } | declmods notype_declarator { tree specs = strip_attrs ($1); - $$ = build_tree_list (specs, $2); } + $$.t = build_tree_list (specs, $2); + $$.new_type_flag = 0; } ; full_parm: - parm maybe_init - { $$ = build_tree_list ($2, $$); } + parm + { $$.t = build_tree_list (NULL_TREE, $1.t); + $$.new_type_flag = $1.new_type_flag; } + | parm defarg + { $$.t = build_tree_list ($2, $1.t); + $$.new_type_flag = $1.new_type_flag; } ; parm: - named_parm + named_parm | type_id ; -see_typename: %prec EMPTY - { see_typename (); } +see_typename: + /* empty */ %prec EMPTY + { see_typename (); } ; -/* -dont_see_typename: %prec EMPTY - { dont_see_typename (); } - ; - -try_for_typename: - { - if ($-1 == error_mark_node) - $$ = 0; - else - { - $$ = 1; - pushclass ($-1, 1); - } - } - ; -*/ - bad_parm: /* empty */ %prec EMPTY { @@ -3775,22 +3605,26 @@ bad_parm: | notype_declarator { error ("type specifier omitted for parameter"); + if (TREE_CODE ($$) == SCOPE_REF + && (TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM + || TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TEMPLATE_PARM)) + cp_error (" perhaps you want `typename %E' to make it a type", $$); $$ = build_tree_list (integer_type_node, $$); } ; exception_specification_opt: - %prec EMPTY /* empty */ + /* empty */ %prec EMPTY { $$ = NULL_TREE; } - | THROW '(' ansi_raise_identifiers ')' %prec EMPTY + | THROW '(' ansi_raise_identifiers ')' %prec EMPTY { $$ = $3; } - | THROW LEFT_RIGHT %prec EMPTY + | THROW LEFT_RIGHT %prec EMPTY { $$ = build_decl_list (NULL_TREE, NULL_TREE); } ; ansi_raise_identifier: type_id - { $$ = build_decl_list (NULL_TREE, groktypename($$)); } + { $$ = build_decl_list (NULL_TREE, groktypename($1.t)); } ; ansi_raise_identifiers: @@ -3803,19 +3637,20 @@ ansi_raise_identifiers: ; conversion_declarator: - /* empty */ %prec EMPTY + /* empty */ %prec EMPTY { $$ = NULL_TREE; } - | '*' type_quals conversion_declarator + | '*' cv_qualifiers conversion_declarator { $$ = make_pointer_declarator ($2, $3); } - | '&' type_quals conversion_declarator + | '&' cv_qualifiers conversion_declarator { $$ = make_reference_declarator ($2, $3); } - | ptr_to_mem type_quals conversion_declarator + | ptr_to_mem cv_qualifiers conversion_declarator { tree arg = make_pointer_declarator ($2, $3); $$ = build_parse_node (SCOPE_REF, $1, arg); } ; -operator: OPERATOR +operator: + OPERATOR { got_scope = NULL_TREE; } ; @@ -3878,9 +3713,9 @@ operator_name: { $$ = ansi_opname[CALL_EXPR]; } | operator '[' ']' { $$ = ansi_opname[ARRAY_REF]; } - | operator NEW %prec EMPTY + | operator NEW %prec EMPTY { $$ = ansi_opname[NEW_EXPR]; } - | operator DELETE %prec EMPTY + | operator DELETE %prec EMPTY { $$ = ansi_opname[DELETE_EXPR]; } | operator NEW '[' ']' { $$ = ansi_opname[VEC_NEW_EXPR]; } @@ -3888,7 +3723,7 @@ operator_name: { $$ = ansi_opname[VEC_DELETE_EXPR]; } /* Names here should be looked up in class scope ALSO. */ | operator type_specifier_seq conversion_declarator - { $$ = grokoptypename ($2, $3); } + { $$ = grokoptypename ($2.t, $3); } | operator error { $$ = ansi_opname[ERROR_MARK]; } ; diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c index 3ce0224..556b761 100644 --- a/contrib/gcc/cp/pt.c +++ b/contrib/gcc/cp/pt.c @@ -1,6 +1,7 @@ /* Handle parameterized types (templates) for GNU C++. - Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing. + Rewritten by Jason Merrill (jason@cygnus.com). This file is part of GNU CC. @@ -20,17 +21,12 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Known bugs or deficiencies include: - * templates for class static data don't work (methods only) - * duplicated method templates can crash the compiler - * interface/impl data is taken from file defining the template - * all methods must be provided in header files; can't use a source - file that contains only the method templates and "just win" - * method templates must be seen before the expansion of the - class template is done - */ + + all methods must be provided in header files; can't use a source + file that contains only the method templates and "just win". */ #include "config.h" -#include +#include "system.h" #include "obstack.h" #include "tree.h" @@ -41,6 +37,12 @@ Boston, MA 02111-1307, USA. */ #include "lex.h" #include "output.h" #include "defaults.h" +#include "except.h" +#include "toplev.h" + +/* The type of functions taking a tree, and some additional data, and + returning an int. */ +typedef int (*tree_fn_t) PROTO((tree, void*)); extern struct obstack permanent_obstack; @@ -48,40 +50,1348 @@ extern int lineno; extern char *input_filename; struct pending_inline *pending_template_expansions; -int processing_template_decl; -int processing_template_defn; +tree current_template_parms; +HOST_WIDE_INT processing_template_decl; + +tree pending_templates; +static tree *template_tail = &pending_templates; + +tree maybe_templates; +static tree *maybe_template_tail = &maybe_templates; -/* This is a kludge to handle instantiation of template methods that are - used before their definition. It should not be necessary after the - template rewrite. */ -static tree template_classes; +int minimal_parse_mode; + +int processing_specialization; +int processing_explicit_instantiation; +int processing_template_parmlist; +static int template_header_count; + +static tree saved_trees; #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free -static int unify (); -static void add_pending_template (); +#define UNIFY_ALLOW_NONE 0 +#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*)); +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 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 coerce_template_parms PROTO((tree, tree, tree, int, int)); +static tree tsubst_enum PROTO((tree, tree, tree *)); +static tree add_to_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)); +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 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 reduce_template_parm_level PROTO((tree, tree, int)); +static tree build_template_decl PROTO((tree, tree)); +static int mark_template_parm PROTO((tree, void *)); +static tree tsubst_friend_function PROTO((tree, tree)); +static tree tsubst_friend_class PROTO((tree, tree)); +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 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 \ + && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) + +/* 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; + tree decl; +{ + if (template_parameters) + end_template_decl (); + else + end_specialization (); + + if (decl == NULL_TREE || decl == void_type_node) + return NULL_TREE; + else if (TREE_CODE (decl) == TREE_LIST) + { + /* Assume that the class is the only declspec. */ + decl = TREE_VALUE (decl); + if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl) + && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl)) + { + tree tmpl = CLASSTYPE_TI_TEMPLATE (decl); + check_member_template (tmpl); + return tmpl; + } + return NULL_TREE; + } + else if (DECL_TEMPLATE_INFO (decl)) + { + if (!DECL_TEMPLATE_SPECIALIZATION (decl)) + { + check_member_template (DECL_TI_TEMPLATE (decl)); + return DECL_TI_TEMPLATE (decl); + } + else + return decl; + } + else + cp_error ("invalid member template declaration `%D'", decl); + + + return error_mark_node; +} + +/* Returns the template nesting level of the indicated class TYPE. + + For example, in: + template + struct A + { + template + struct B {}; + }; + + A::B has depth two, while A has depth one. Also, + both A::B and A::B have depth one. */ + +int +template_class_depth (type) + tree type; +{ + 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; + + return depth; +} + +/* Return the original template for this decl, disregarding any + specializations. */ + +static tree +original_template (decl) + tree decl; +{ + while (DECL_TEMPLATE_INFO (decl)) + decl = DECL_TI_TEMPLATE (decl); + return decl; +} + +/* Returns 1 if processing DECL as part of do_pending_inlines + needs us to push template parms. */ + +static int +inline_needs_template_parms (decl) + tree decl; +{ + if (! DECL_TEMPLATE_INFO (decl)) + return 0; + + return (list_length (DECL_TEMPLATE_PARMS (original_template (decl))) + > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl))); +} + +/* Subroutine of maybe_begin_member_template_processing. + Push the template parms in PARMS, starting from LEVELS steps into the + chain, and ending at the beginning, since template parms are listed + innermost first. */ + +static void +push_inline_template_parms_recursive (parmlist, levels) + tree parmlist; + int levels; +{ + tree parms = TREE_VALUE (parmlist); + int i; + + if (levels > 1) + push_inline_template_parms_recursive (TREE_CHAIN (parmlist), levels - 1); + + ++processing_template_decl; + current_template_parms + = tree_cons (build_int_2 (0, processing_template_decl), + parms, current_template_parms); + TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1; + + pushlevel (0); + for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0); + + switch (TREE_CODE (parm)) + { + case TYPE_DECL: + case TEMPLATE_DECL: + pushdecl (parm); + break; + + case PARM_DECL: + { + /* Make a CONST_DECL as is done in process_template_parm. */ + tree decl = build_decl (CONST_DECL, DECL_NAME (parm), + TREE_TYPE (parm)); + DECL_INITIAL (decl) = DECL_INITIAL (parm); + pushdecl (decl); + } + break; + + default: + my_friendly_abort (0); + } + } +} -void overload_template_name (), pop_template_decls (); +/* Restore the template parameter context for a member template or + a friend template defined in a class definition. */ + +void +maybe_begin_member_template_processing (decl) + tree decl; +{ + tree parms; + int levels; + + if (! inline_needs_template_parms (decl)) + return; + + parms = DECL_TEMPLATE_PARMS (original_template (decl)); + + levels = list_length (parms) - processing_template_decl; + + if (DECL_TEMPLATE_SPECIALIZATION (decl)) + { + --levels; + parms = TREE_CHAIN (parms); + } + + push_inline_template_parms_recursive (parms, levels); +} + +/* Undo the effects of begin_member_template_processing. */ + +void +maybe_end_member_template_processing (decl) + tree decl; +{ + if (! processing_template_decl) + return; + + while (current_template_parms + && TEMPLATE_PARMS_FOR_INLINE (current_template_parms)) + { + --processing_template_decl; + current_template_parms = TREE_CHAIN (current_template_parms); + poplevel (0, 0, 0); + } +} + +/* Returns non-zero iff T is a member template function. We must be + careful as in + + template class C { void f(); } + + Here, f is a template function, and a member, but not a member + template. This function does not concern itself with the origin of + T, only its present state. So if we have + + template class C { template void f(U); } + + then neither C::f nor C::f is considered + to be a member template. */ + +int +is_member_template (t) + tree t; +{ + if (TREE_CODE (t) != FUNCTION_DECL + && !DECL_FUNCTION_TEMPLATE_P (t)) + /* Anything that isn't a function or a template function is + certainly not a member template. */ + return 0; + + /* A local class can't have member templates. */ + 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 + /* 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; +} + +/* Returns non-zero iff T is a member template class. See + is_member_template for a description of what precisely constitutes + a member template. */ + +int +is_member_template_class (t) + tree t; +{ + if (!DECL_CLASS_TEMPLATE_P (t)) + /* Anything that isn't a class template, is certainly not a member + template. */ + return 0; + + if (!DECL_CLASS_SCOPE_P (t)) + /* Anything whose context isn't a class type is surely not a + member template. */ + return 0; + + /* 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)) > + template_class_depth (DECL_CONTEXT (t))); +} + +/* 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. */ + +static tree +complete_template_args (tmpl, extra_args, unbound_only) + tree tmpl, extra_args; + int unbound_only; +{ + /* 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); + } + } + } + } + + 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); + + if (spec_args) + TREE_VEC_ELT (new_args, depth) = spec_args; + + 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. */ + +static tree +add_to_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; + + new_args = make_tree_vec (TREE_VEC_LENGTH (args) + 1); + + 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; + + return new_args; +} + +/* We've got a template header coming up; push to a new level for storing + the parms. */ -/* We've got a template header coming up; set obstacks up to save the - nodes created permanently. (There might be cases with nested templates - where we don't have to do this, but they aren't implemented, and it - probably wouldn't be worth the effort.) */ void begin_template_parm_list () { + /* We use a non-tag-transparent scope here, which causes pushtag to + put tags in this scope, rather than in the enclosing class or + namespace scope. This is the right thing, since we want + TEMPLATE_DECLS, and not TYPE_DECLS for template classes. For a + global template class, push_template_decl handles putting the + TEMPLATE_DECL into top-level scope. For a nested template class, + e.g.: + + template struct S1 { + template struct S2 {}; + }; + + pushtag contains special code to call pushdecl_with_scope on the + TEMPLATE_DECL for S2. */ pushlevel (0); - push_obstacks (&permanent_obstack, &permanent_obstack); - pushlevel (0); + declare_pseudo_global_level (); + ++processing_template_decl; + ++processing_template_parmlist; + note_template_header (0); +} + +/* We've just seen template <>. */ + +void +begin_specialization () +{ + note_template_header (1); +} + +/* Called at then end of processing a declaration preceeded by + template<>. */ + +void +end_specialization () +{ + reset_specialization (); +} + +/* Any template <>'s that we have seen thus far are not referring to a + function specialization. */ + +void +reset_specialization () +{ + processing_specialization = 0; + template_header_count = 0; +} + +/* We've just seen a template header. If SPECIALIZATION is non-zero, + it was of the form template <>. */ + +static void +note_template_header (specialization) + int specialization; +{ + processing_specialization = specialization; + template_header_count++; +} + +/* We're beginning an explicit instantiation. */ + +void +begin_explicit_instantiation () +{ + ++processing_explicit_instantiation; +} + + +void +end_explicit_instantiation () +{ + my_friendly_assert(processing_explicit_instantiation > 0, 0); + --processing_explicit_instantiation; +} + +/* 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 + no such specialization, return NULL_TREE. The ARGS are a vector of + arguments, or a vector of vectors of arguments, in the case of + templates with more than one level of parameters. */ + +static tree +retrieve_specialization (tmpl, args) + tree tmpl; + tree args; +{ + tree s; + + my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); + + for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + s != NULL_TREE; + s = TREE_CHAIN (s)) + if (comp_template_args (TREE_PURPOSE (s), args)) + return TREE_VALUE (s); + + return NULL_TREE; +} + +/* Returns non-zero iff DECL is a specialization of TMPL. */ + +int +is_specialization_of (decl, tmpl) + tree decl; + tree tmpl; +{ + tree t; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + for (t = decl; + t != NULL_TREE; + t = DECL_TEMPLATE_INFO (t) ? DECL_TI_TEMPLATE (t) : NULL_TREE) + if (t == tmpl) + return 1; + } + else + { + my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 0); + + for (t = TREE_TYPE (decl); + 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)) + return 1; + } + + return 0; +} + +/* Register the specialization SPEC as a specialization of TMPL with + the indicated ARGS. */ + +static void +register_specialization (spec, tmpl, args) + tree spec; + tree tmpl; + tree args; +{ + tree s; + + 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; + + for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + s != NULL_TREE; + s = TREE_CHAIN (s)) + if (comp_template_args (TREE_PURPOSE (s), args)) + { + tree fn = TREE_VALUE (s); + + if (DECL_TEMPLATE_SPECIALIZATION (spec)) + { + if (DECL_TEMPLATE_INSTANTIATION (fn)) + { + if (TREE_USED (fn) + || DECL_EXPLICIT_INSTANTIATION (fn)) + { + cp_error ("specialization of %D after instantiation", + fn); + return; + } + else + { + /* This situation should occur only if the first + specialization is an implicit instantiation, + 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; + } + } + else if (DECL_TEMPLATE_SPECIALIZATION (fn)) + { + if (DECL_INITIAL (fn)) + cp_error ("duplicate specialization of %D", fn); + + TREE_VALUE (s) = spec; + return; + } + } + } + + DECL_TEMPLATE_SPECIALIZATIONS (tmpl) + = perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); +} + +/* Print the list of candidate FNS in an error message. */ + +static void +print_candidates (fns) + tree fns; +{ + tree fn; + + char* str = "candidates are:"; + + for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn)) + { + cp_error_at ("%s %+#D", str, TREE_VALUE (fn)); + 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. */ + +tree +determine_specialization (template_id, decl, targs_out, + need_member_template, + complain) + 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; + + *targs_out = NULL_TREE; + + if (template_id == error_mark_node) + return error_mark_node; + + fns = TREE_OPERAND (template_id, 0); + targs_in = TREE_OPERAND (template_id, 1); + + if (fns == error_mark_node) + return error_mark_node; + + /* Check for baselinks. */ + if (TREE_CODE (fns) == TREE_LIST) + fns = TREE_VALUE (fns); + + for (; fns; fns = OVL_NEXT (fns)) + { + 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 X { void f(); } + template <> void X::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))) + continue; + else + tmpl = fn; + + if (list_length (targs_in) > DECL_NTPARMS (tmpl)) + continue; + + 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); + } + 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; + + *targs_out = get_bindings (tmpl, decl, targs_in); + return tmpl; + } + + if (templates == NULL_TREE) + { + 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; + } + else if (TREE_CHAIN (templates) != NULL_TREE) + { + 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; + } + + /* We have one, and exactly one, match. */ + *targs_out = TREE_PURPOSE (templates); + return TREE_VALUE (templates); +} + +/* Check to see if the function just declared, as indicated in + DECLARATOR, and in DECL, is a specialization of a function + template. We may also discover that the declaration is an explicit + instantiation at this point. + + Returns DECL, or an equivalent declaration that should be used + instead. + + 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 + example, in + + template struct S { void f(); }; + void S::f(); + + the TEMPLATE_COUNT would be 1. However, explicitly specialized + classes are not counted in the TEMPLATE_COUNT, so that in + + template struct S {}; + template <> struct S { void f(); } + template <> + void S::f(); + + the TEMPLATE_COUNT would be 0. (Note that this declaration is + illegal; there should be no template <>.) + + If the function is a specialization, it is marked as such via + DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO + is set up correctly, and it is added to the list of specializations + for that template. */ + +tree +check_explicit_specialization (declarator, decl, template_count, flags) + tree declarator; + tree decl; + 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; + + tree ctype = DECL_CLASS_CONTEXT (decl); + tree dname = DECL_NAME (decl); + + if (!finish_member) + { + if (processing_specialization) + { + /* 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 struct S { + void f(int i); + }; + template <> + void S::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::T::f(); + + 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)) + { + /* This case catches outdated code that looks like this: + + template struct S { void f(); }; + void S::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 void S::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); + } + else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + { + /* This case handles bogus declarations like + template <> template + void f(); */ + + cp_error ("template-id `%D' in declaration of primary template", + declarator); + return decl; + } + } + + if (specialization || member_specialization) + { + tree t = TYPE_ARG_TYPES (TREE_TYPE (decl)); + for (; t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t)) + { + cp_pedwarn + ("default argument specified in explicit specialization"); + break; + } + } + + if (specialization || member_specialization || explicit_instantiation) + { + tree tmpl = NULL_TREE; + tree targs = NULL_TREE; + + /* Make sure that the declarator is a TEMPLATE_ID_EXPR. */ + if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR) + { + tree fns; + + my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE, + 0); + if (!ctype) + fns = IDENTIFIER_NAMESPACE_VALUE (dname); + else + fns = dname; + + declarator = + lookup_template_function (fns, NULL_TREE); + } + + 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; + } + else + /* It's not legal to write an explicit instantiation in + class scope, e.g.: + + class C { template void f(); } + + This case is caught by the parser. However, on + something like: + + template class C { void f(); }; + + (which is illegal) we can get here. The error will be + issued later. */ + ; + + return decl; + } + else if (ctype != NULL_TREE + && (TREE_CODE (TREE_OPERAND (declarator, 0)) == + IDENTIFIER_NODE)) + { + /* Find the list of functions in ctype that have the same + name as the declared function. */ + tree name = TREE_OPERAND (declarator, 0); + tree fns; + + if (name == constructor_name (ctype) + || name == constructor_name_full (ctype)) + { + int is_constructor = DECL_CONSTRUCTOR_P (decl); + + if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype) + : !TYPE_HAS_DESTRUCTOR (ctype)) + { + /* From [temp.expl.spec]: + + If such an explicit specialization for the member + of a class template names an implicitly-declared + special member function (clause _special_), the + program is ill-formed. + + Similar language is found in [temp.explicit]. */ + cp_error ("specialization of implicitly-declared special member function"); + + return decl; + } + + name = is_constructor ? ctor_identifier : dtor_identifier; + } + + fns = lookup_fnfields (TYPE_BINFO (ctype), name, 1); + + if (fns == NULL_TREE) + { + cp_error ("no member function `%s' declared in `%T'", + IDENTIFIER_POINTER (name), + ctype); + return decl; + } + else + TREE_OPERAND (declarator, 0) = fns; + } + + /* Figure out what exactly is being specialized at this point. + 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. */ + tmpl = determine_specialization (declarator, decl, + &targs, + member_specialization, + 1); + + if (tmpl && tmpl != error_mark_node) + { + if (explicit_instantiation) + { + 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)) + { + revert_static_member_fn (&decl, 0, 0); + last_function_parms = TREE_CHAIN (last_function_parms); + } + + /* Mangle the function name appropriately. Note that we do + not mangle specializations of non-template member + functions of template classes, e.g. with + template struct S { void f(); } + and given the specialization + template <> void S::f() {} + we do not mangle S::f() here. That's because it's + just an ordinary member function and doesn't need special + treatment. */ + 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); + } + + 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; + } + + /* 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.) + + According to the CD2, + + 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. + + 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); + + register_specialization (decl, tmpl, targs); + + return decl; + } + } + + return decl; +} + +/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template + parameters. These are represented in the same format used for + DECL_TEMPLATE_PARMS. */ + +int comp_template_parms (parms1, parms2) + tree parms1; + tree parms2; +{ + tree p1; + tree p2; + + if (parms1 == parms2) + return 1; + + for (p1 = parms1, p2 = parms2; + p1 != NULL_TREE && p2 != NULL_TREE; + p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2)) + { + tree t1 = TREE_VALUE (p1); + tree t2 = TREE_VALUE (p2); + int i; + + my_friendly_assert (TREE_CODE (t1) == TREE_VEC, 0); + my_friendly_assert (TREE_CODE (t2) == TREE_VEC, 0); + + if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2)) + return 0; + + for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) + { + tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); + tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); + + if (TREE_CODE (parm1) != TREE_CODE (parm2)) + return 0; + + if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM) + continue; + else if (!comptypes (TREE_TYPE (parm1), + TREE_TYPE (parm2), 1)) + return 0; + } + } + + if ((p1 != NULL_TREE) != (p2 != NULL_TREE)) + /* One set of parameters has more parameters lists than the + other. */ + return 0; + + return 1; +} + +/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL, + ORIG_LEVEL, DECL, and TYPE. */ + +static tree +build_template_parm_index (index, level, orig_level, decl, type) + int index; + int level; + int orig_level; + tree decl; + tree type; +{ + tree t = make_node (TEMPLATE_PARM_INDEX); + TEMPLATE_PARM_IDX (t) = index; + TEMPLATE_PARM_LEVEL (t) = level; + TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level; + TEMPLATE_PARM_DECL (t) = decl; + TREE_TYPE (t) = type; + + return t; +} + +/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose + TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a + TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a + new one is created. */ + +static tree +reduce_template_parm_level (index, type, levels) + tree index; + tree type; + int levels; +{ + if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE + || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index)) + != TEMPLATE_PARM_LEVEL (index) - levels)) + { + tree decl + = build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)), + DECL_NAME (TEMPLATE_PARM_DECL (index)), + type); + tree t + = build_template_parm_index (TEMPLATE_PARM_IDX (index), + TEMPLATE_PARM_LEVEL (index) - levels, + TEMPLATE_PARM_ORIG_LEVEL (index), + decl, type); + TEMPLATE_PARM_DESCENDANTS (index) = t; + + /* Template template parameters need this. */ + DECL_TEMPLATE_PARMS (decl) + = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)); + } + + return TEMPLATE_PARM_DESCENDANTS (index); } /* Process information from new template parameter NEXT and append it to the - LIST being built. The rules for use of a template parameter type name - by later parameters are not well-defined for us just yet. However, the - only way to avoid having to parse expressions of unknown complexity (and - with tokens of unknown types) is to disallow it completely. So for now, - that is what is assumed. */ + LIST being built. */ + tree process_template_parm (list, next) tree list, next; @@ -89,51 +1399,92 @@ process_template_parm (list, next) tree parm; tree decl = 0; tree defval; - int is_type; + int is_type, idx; + parm = next; my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259); defval = TREE_PURPOSE (parm); parm = TREE_VALUE (parm); is_type = TREE_PURPOSE (parm) == class_type_node; + + if (list) + { + tree p = TREE_VALUE (tree_last (list)); + + if (TREE_CODE (p) == TYPE_DECL) + idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p)); + else if (TREE_CODE (p) == TEMPLATE_DECL) + idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p))); + else + idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p)); + ++idx; + } + else + idx = 0; + if (!is_type) { - tree tinfo = 0; my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260); /* is a const-param */ parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), - PARM, 0, NULL_TREE, NULL_TREE); + PARM, 0, NULL_TREE); /* A template parameter is not modifiable. */ TREE_READONLY (parm) = 1; - if (IS_AGGR_TYPE (TREE_TYPE (parm))) + if (IS_AGGR_TYPE (TREE_TYPE (parm)) + && TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM + && TREE_CODE (TREE_TYPE (parm)) != TYPENAME_TYPE) { - sorry ("aggregate template parameter types"); + cp_error ("`%#T' is not a valid type for a template constant parameter", + TREE_TYPE (parm)); + if (DECL_NAME (parm) == NULL_TREE) + error (" a template type parameter must begin with `class' or `typename'"); TREE_TYPE (parm) = void_type_node; } - tinfo = make_node (TEMPLATE_CONST_PARM); - my_friendly_assert (TREE_PERMANENT (tinfo), 260.5); + else if (pedantic + && (TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE + || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE)) + cp_pedwarn ("`%T' is not a valid type for a template constant parameter", + TREE_TYPE (parm)); if (TREE_PERMANENT (parm) == 0) { parm = copy_node (parm); TREE_PERMANENT (parm) = 1; } - TREE_TYPE (tinfo) = TREE_TYPE (parm); decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm)); - DECL_INITIAL (decl) = tinfo; - DECL_INITIAL (parm) = tinfo; + DECL_INITIAL (parm) = DECL_INITIAL (decl) + = build_template_parm_index (idx, processing_template_decl, + processing_template_decl, + decl, TREE_TYPE (parm)); } else { - tree t = make_node (TEMPLATE_TYPE_PARM); - decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t); - TYPE_MAIN_DECL (t) = decl; - parm = decl; - if (defval) + tree t; + parm = TREE_VALUE (parm); + + if (parm && TREE_CODE (parm) == TEMPLATE_DECL) { - if (IDENTIFIER_HAS_TYPE_VALUE (defval)) - defval = IDENTIFIER_TYPE_VALUE (defval); - else - defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval)); + t = make_lang_type (TEMPLATE_TEMPLATE_PARM); + /* This is for distinguishing between real templates and template + template parameters */ + TREE_TYPE (parm) = t; + TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t; + decl = parm; } + else + { + t = make_lang_type (TEMPLATE_TYPE_PARM); + /* parm is either IDENTIFIER_NODE or NULL_TREE */ + decl = build_decl (TYPE_DECL, parm, t); + } + + CLASSTYPE_GOT_SEMICOLON (t) = 1; + TYPE_NAME (t) = decl; + TYPE_STUB_DECL (t) = decl; + parm = decl; + TEMPLATE_TYPE_PARM_INDEX (t) + = build_template_parm_index (idx, processing_template_decl, + processing_template_decl, + decl, TREE_TYPE (parm)); } SET_DECL_ARTIFICIAL (decl); pushdecl (decl); @@ -141,205 +1492,974 @@ process_template_parm (list, next) return chainon (list, parm); } -/* The end of a template parameter list has been reached. Process the - tree list into a parameter vector, converting each parameter into a more - useful form. Type parameters are saved as IDENTIFIER_NODEs, and others - as PARM_DECLs. */ +/* The end of a template parameter list has been reached. Process the + tree list into a parameter vector, converting each parameter into a more + useful form. Type parameters are saved as IDENTIFIER_NODEs, and others + as PARM_DECLs. */ + +tree +end_template_parm_list (parms) + tree parms; +{ + int nparms; + tree parm; + tree saved_parmlist = make_tree_vec (list_length (parms)); + + current_template_parms + = tree_cons (build_int_2 (0, processing_template_decl), + saved_parmlist, current_template_parms); + + for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) + TREE_VEC_ELT (saved_parmlist, nparms) = parm; + + --processing_template_parmlist; + + return saved_parmlist; +} + +/* end_template_decl is called after a template declaration is seen. */ + +void +end_template_decl () +{ + reset_specialization (); + + if (! processing_template_decl) + return; + + /* This matches the pushlevel in begin_template_parm_list. */ + poplevel (0, 0, 0); + + --processing_template_decl; + current_template_parms = TREE_CHAIN (current_template_parms); + (void) get_pending_sizes (); /* Why? */ +} + +/* Generate a valid set of template args from current_template_parms. */ + +tree +current_template_args () +{ + tree header = current_template_parms; + int length = list_length (header); + tree args = make_tree_vec (length); + int l = length; + + while (header) + { + tree a = copy_node (TREE_VALUE (header)); + int i = TREE_VEC_LENGTH (a); + TREE_TYPE (a) = NULL_TREE; + while (i--) + { + tree t = TREE_VEC_ELT (a, i); + + /* 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) + { + t = TREE_VALUE (t); + + if (TREE_CODE (t) == TYPE_DECL + || TREE_CODE (t) == TEMPLATE_DECL) + t = TREE_TYPE (t); + else + t = DECL_INITIAL (t); + } + + TREE_VEC_ELT (a, i) = t; + } + TREE_VEC_ELT (args, --l) = a; + header = TREE_CHAIN (header); + } + + return args; +} + + +/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated + template PARMS. Used by push_template_decl below. */ + +static tree +build_template_decl (decl, parms) + tree decl; + tree parms; +{ + tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE); + DECL_TEMPLATE_PARMS (tmpl) = parms; + DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl); + if (DECL_LANG_SPECIFIC (decl)) + { + DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl); + DECL_STATIC_FUNCTION_P (tmpl) = + DECL_STATIC_FUNCTION_P (decl); + } + + return tmpl; +} + +struct template_parm_data +{ + int level; + int* parms; +}; + +/* Subroutine of push_template_decl used to see if each template + parameter in a partial specialization is used in the explicit + argument list. If T is of the LEVEL given in DATA (which is + treated as a template_parm_data*), then DATA->PARMS is marked + appropriately. */ + +static int +mark_template_parm (t, data) + tree t; + void* data; +{ + int level; + int idx; + struct template_parm_data* tpd = (struct template_parm_data*) data; + + if (TREE_CODE (t) == TEMPLATE_PARM_INDEX) + { + level = TEMPLATE_PARM_LEVEL (t); + idx = TEMPLATE_PARM_IDX (t); + } + else + { + level = TEMPLATE_TYPE_LEVEL (t); + idx = TEMPLATE_TYPE_IDX (t); + } + + if (level == tpd->level) + tpd->parms[idx] = 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; +} + +/* 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 + equivalent one, if it is replaced via a call to duplicate_decls. + + If IS_FRIEND is non-zero, DECL is a friend declaration. */ + +tree +push_template_decl_real (decl, is_friend) + tree decl; + int is_friend; +{ + tree tmpl; + tree args; + tree info; + tree ctx; + int primary; + + is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl)); + + if (is_friend) + /* For a friend, we want the context of the friend function, not + the type of which it is a friend. */ + ctx = DECL_CONTEXT (decl); + else if (DECL_REAL_CONTEXT (decl) + && TREE_CODE (DECL_REAL_CONTEXT (decl)) != NAMESPACE_DECL) + /* In the case of a virtual function, we want the class in which + it is defined. */ + ctx = DECL_REAL_CONTEXT (decl); + else + /* Otherwise, if we're currently definining some class, the DECL + is assumed to be a member of the class. */ + ctx = current_class_type; + + if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL) + ctx = NULL_TREE; + + if (!DECL_CONTEXT (decl)) + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + + /* 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; + else + info = ctx; + + if (info && TREE_CODE (info) == FUNCTION_DECL) + primary = 0; + /* Note that template_class_depth returns 0 if given NULL_TREE, so + this next line works even when we are at global scope. */ + else if (processing_template_decl > template_class_depth (info)) + primary = 1; + else + primary = 0; + + if (primary) + { + if (current_lang_name == lang_name_c) + 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"); + } + + /* 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 struct S; + template struct S; + + The second declaration is OK because `T*' uses the template + parameter T, whereas + + template struct S; + + is no good. Even trickier is: + + template + struct S1 + { + template + struct S2; + template + struct S2; + }; + + The S2 declaration is actually illegal; it is a + full-specialization. Of course, + + template + struct S2; + + 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))); + } + + 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; + } + + args = current_template_args (); + + if (!ctx + || TREE_CODE (ctx) == FUNCTION_DECL + || TYPE_BEING_DEFINED (ctx) + || (is_friend && !DECL_TEMPLATE_INFO (decl))) + { + if (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INFO (decl) + && DECL_TI_TEMPLATE (decl)) + tmpl = DECL_TI_TEMPLATE (decl); + else + { + tmpl = build_template_decl (decl, current_template_parms); + + if (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_SPECIALIZATION (decl)) + { + /* A specialization of a member template of a template + class. */ + SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); + DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl); + DECL_TEMPLATE_INFO (decl) = NULL_TREE; + } + } + } + else + { + tree t; + tree a; + + 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)); + else + { + cp_error ("`%D' does not declare a template type", decl); + return decl; + } + } + else if (! DECL_TEMPLATE_INFO (decl)) + { + cp_error ("template definition of non-template `%#D'", decl); + return decl; + } + else + tmpl = DECL_TI_TEMPLATE (decl); + + if (is_member_template (tmpl) || is_member_template_class (tmpl)) + { + 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; + } + else + a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); + + t = NULL_TREE; + + if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx)) + { + /* 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)); + } + else if (CLASSTYPE_TEMPLATE_INFO (ctx)) + t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx)); + + /* 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 (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)); + } + } + /* 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. */ + tmpl = pushdecl_namespace_level (tmpl); + + if (primary) + DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; + + info = perm_tree_cons (tmpl, args, NULL_TREE); + + if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) + { + CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info; + if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL) + DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl)); + } + else if (! DECL_LANG_SPECIFIC (decl)) + cp_error ("template declaration of `%#D'", decl); + else + DECL_TEMPLATE_INFO (decl) = info; + + return DECL_TEMPLATE_RESULT (tmpl); +} + +tree +push_template_decl (decl) + tree decl; +{ + return push_template_decl_real (decl, 0); +} + +/* Called when a class template TYPE is redeclared with the indicated + template PARMS, e.g.: + + template struct S; + template struct S {}; */ + +void +redeclare_class_template (type, parms) + tree type; + tree parms; +{ + tree tmpl = CLASSTYPE_TI_TEMPLATE (type); + tree tmpl_parms; + int i; + + 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 + type. */ + return; + + parms = INNERMOST_TEMPLATE_PARMS (parms); + tmpl_parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + + if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms)) + { + cp_error_at ("previous declaration `%D'", tmpl); + cp_error ("used %d template parameter%s instead of %d", + TREE_VEC_LENGTH (tmpl_parms), + TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s", + TREE_VEC_LENGTH (parms)); + return; + } + + for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i) + { + tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i)); + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)); + tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i)); + + if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)) + { + cp_error_at ("template parameter `%#D'", tmpl_parm); + cp_error ("redeclared here as `%#D'", parm); + return; + } + + if (tmpl_default != NULL_TREE && parm_default != NULL_TREE) + { + /* We have in [temp.param]: + + A template-parameter may not be given default arguments + by two different declarations in the same scope. */ + cp_error ("redefinition of default argument for `%#D'", parm); + cp_error_at (" original definition appeared here", tmpl_parm); + return; + } + + if (parm_default != NULL_TREE) + /* Update the previous template parameters (which are the ones + that will really count) with the new default value. */ + TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)) = parm_default; + } +} + +/* Attempt to convert the non-type template parameter EXPR to the + indicated TYPE. If the conversion is successful, return the + converted value. If the conversion is unsuccesful, return + NULL_TREE if we issued an error message, or error_mark_node if we + did not. We issue error messages for out-and-out bad template + parameters, but not simply because the conversion failed, since we + might be just trying to do argument deduction. By the time this + function is called, neither TYPE nor EXPR may make use of template + parameters. */ + +static tree +convert_nontype_argument (type, expr) + tree type; + tree expr; +{ + tree expr_type = TREE_TYPE (expr); + + /* A template-argument for a non-type, non-template + template-parameter shall be one of: + + --an integral constant-expression of integral or enumeration + type; or + + --the name of a non-type template-parameter; or + + --the name of an object or function with external linkage, + including function templates and function template-ids but + excluding non-static class members, expressed as id-expression; + or + + --the address of an object or function with external linkage, + including function templates and function template-ids but + excluding non-static class members, expressed as & id-expression + where the & is optional if the name refers to a function or + array; or + + --a pointer to member expressed as described in _expr.unary.op_. */ + + /* An integral constant-expression can include const variables + or enumerators. */ + if (INTEGRAL_TYPE_P (expr_type) && TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + + if (is_overloaded_fn (expr)) + /* OK for now. We'll check that it has external linkage later. + 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) + { + if (! TREE_CONSTANT (expr)) + { + non_constant: + cp_error ("non-constant `%E' cannot be used as template argument", + expr); + return NULL_TREE; + } + } + else if (TYPE_PTR_P (expr_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) + { + tree referent; + tree e = expr; + STRIP_NOPS (e); + + if (TREE_CODE (e) != ADDR_EXPR) + { + 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; + } + + 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", + referent); + error ("because it is the address of an object with static linkage"); + return NULL_TREE; + } + + if (is_overloaded_fn (referent)) + /* We'll check that it has external linkage later. */ + ; + else if (TREE_CODE (referent) != VAR_DECL) + goto bad_argument; + else if (!TREE_PUBLIC (referent)) + { + cp_error ("address of non-extern `%E' cannot be used as template argument", referent); + return error_mark_node; + } + } + else if (TREE_CODE (expr) == VAR_DECL) + { + if (!TREE_PUBLIC (expr)) + goto bad_argument; + } + else + { + cp_error ("object `%E' cannot be used as template argument", expr); + return NULL_TREE; + } + + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: + case BOOLEAN_TYPE: + case ENUMERAL_TYPE: + /* For a non-type template-parameter of integral or enumeration + type, integral promotions (_conv.prom_) and integral + conversions (_conv.integral_) are applied. */ + if (!INTEGRAL_TYPE_P (expr_type)) + return error_mark_node; + + /* It's safe to call digest_init in this case; we know we're + just converting one integral constant expression to another. */ + expr = digest_init (type, expr, (tree*) 0); + + if (TREE_CODE (expr) != INTEGER_CST) + /* Curiously, some TREE_CONSTNAT integral expressions do not + simplify to integer constants. For example, `3 % 0', + remains a TRUNC_MOD_EXPR. */ + goto non_constant; + + return expr; + + case REAL_TYPE: + case COMPLEX_TYPE: + /* These are g++ extensions. */ + if (TREE_CODE (expr_type) != TREE_CODE (type)) + return error_mark_node; + + expr = digest_init (type, expr, (tree*) 0); + + if (TREE_CODE (expr) != REAL_CST) + goto non_constant; + + return expr; + + case POINTER_TYPE: + { + 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); + else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE) + { + /* For a non-type template-parameter of type pointer to + function, only the function-to-pointer conversion + (_conv.func_) is applied. If the template-argument + represents a set of overloaded functions (or a pointer to + such), the matching function is selected from the set + (_over.over_). */ + tree fns; + tree fn; + + if (TREE_CODE (expr) == ADDR_EXPR) + fns = TREE_OPERAND (expr, 0); + else + fns = expr; + + fn = instantiate_type (type_pointed_to, fns, 0); + + if (fn == error_mark_node) + return error_mark_node; + + if (!TREE_PUBLIC (fn)) + { + if (really_overloaded_fn (fns)) + return error_mark_node; + else + goto bad_argument; + } + + expr = build_unary_op (ADDR_EXPR, fn, 0); + + my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1), + 0); + return expr; + } + else + { + /* For a non-type template-parameter of type pointer to + object, qualification conversions (_conv.qual_) and the + array-to-pointer conversion (_conv.array_) are applied. + [Note: In particular, neither the null pointer conversion + (_conv.ptr_) nor the derived-to-base conversion + (_conv.ptr_) are applied. Although 0 is a valid + template-argument for a non-type template-parameter of + integral type, it is not a valid template-argument for a + non-type template-parameter of pointer type.] + + The call to decay_conversion performs the + array-to-pointer conversion, if appropriate. */ + expr = decay_conversion (expr); + + if (expr == error_mark_node) + return error_mark_node; + else + return perform_qualification_conversions (type, expr); + } + } + break; + + case REFERENCE_TYPE: + { + tree type_referred_to = TREE_TYPE (type); + + 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_). */ + tree fns = expr; + tree fn; + + fn = instantiate_type (type_referred_to, fns, 0); + + if (!TREE_PUBLIC (fn)) + { + if (really_overloaded_fn (fns)) + /* Don't issue an error here; we might get a different + function if the overloading had worked out + differently. */ + return error_mark_node; + else + goto bad_argument; + } + + if (fn == error_mark_node) + return error_mark_node; + + my_friendly_assert (comptypes (type, TREE_TYPE (fn), 1), + 0); + + return fn; + } + else + { + /* For a non-type template-parameter of type reference to + object, no conversions apply. The type referred to by the + reference may be more cv-qualified than the (otherwise + 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)) + || !real_lvalue_p (expr)) + return error_mark_node; + else + return expr; + } + } + break; -tree -end_template_parm_list (parms) - tree parms; -{ - int nparms = 0; - int saw_default = 0; - tree saved_parmlist; - tree parm; - for (parm = parms; parm; parm = TREE_CHAIN (parm)) - nparms++; - saved_parmlist = make_tree_vec (nparms); + case RECORD_TYPE: + { + tree fns; + tree fn; + + if (!TYPE_PTRMEMFUNC_P (type)) + /* This handles templates like + template void f(); + when T is substituted with any class. The second template + parameter becomes invalid and the template candidate is + rejected. */ + return error_mark_node; + + /* For a non-type template-parameter of type pointer to member + function, no conversions apply. If the template-argument + represents a set of overloaded member functions, the + matching member function is selected from the set + (_over.over_). */ + + if (!TYPE_PTRMEMFUNC_P (expr_type) && + expr_type != unknown_type_node) + return error_mark_node; + + if (TREE_CODE (expr) == CONSTRUCTOR) + { + /* A ptr-to-member constant. */ + if (!comptypes (type, expr_type, 1)) + return error_mark_node; + else + return expr; + } - for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) - { - tree p = TREE_VALUE (parm); - if (TREE_PURPOSE (parm)) - saw_default = 1; - else if (saw_default) - { - error ("if a default argument is given for one template parameter"); - error ("default arguments must be given for all subsequent"); - error ("parameters as well"); - } + if (TREE_CODE (expr) != ADDR_EXPR) + return error_mark_node; - if (TREE_CODE (p) == TYPE_DECL) - { - tree t = TREE_TYPE (p); - TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms); - } - else - { - tree tinfo = DECL_INITIAL (p); - DECL_INITIAL (p) = NULL_TREE; - TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms); - } - TREE_VEC_ELT (saved_parmlist, nparms) = parm; + fns = TREE_OPERAND (expr, 0); + + fn = instantiate_type (TREE_TYPE (TREE_TYPE (type)), + fns, 0); + + if (fn == error_mark_node) + return error_mark_node; + + expr = build_unary_op (ADDR_EXPR, fn, 0); + + my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1), + 0); + return expr; + } + break; + + default: + /* All non-type parameters must have one of these types. */ + my_friendly_abort (0); + break; } - set_current_level_tags_transparency (1); - processing_template_decl++; - return saved_parmlist; + + return error_mark_node; } -/* end_template_decl is called after a template declaration is seen. - D1 is template header; D2 is class_head_sans_basetype or a - TEMPLATE_DECL with its DECL_RESULT field set. */ -void -end_template_decl (d1, d2, is_class, defn) - tree d1, d2, is_class; - int defn; +/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for + template template parameters. Both PARM_PARMS and ARG_PARMS are + vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL + or PARM_DECL. + + ARG_PARMS may contain more parameters than PARM_PARMS. If this is + the case, then extra parameters must have default arguments. + + Consider the example: + template class vector; + template